blob: 45b4802b11fe21cd609166e92f3bc41f09f0fd35 [file] [log] [blame]
Jon Hall5cf14d52015-07-16 12:15:19 -07001"""
2Description: This test is to determine if ONOS can handle
3 a minority of it's nodes restarting
4
5List of test cases:
6CASE1: Compile ONOS and push it to the test machines
7CASE2: Assign devices to controllers
8CASE21: Assign mastership to controllers
9CASE3: Assign intents
10CASE4: Ping across added host intents
11CASE5: Reading state of ONOS
Jon Hallb3ed8ed2015-10-28 16:43:55 -070012CASE61: The Failure inducing case.
13CASE62: The Failure recovery case.
Jon Hall5cf14d52015-07-16 12:15:19 -070014CASE7: Check state after control plane failure
15CASE8: Compare topo
16CASE9: Link s3-s28 down
17CASE10: Link s3-s28 up
18CASE11: Switch down
19CASE12: Switch up
20CASE13: Clean up
21CASE14: start election app on all onos nodes
22CASE15: Check that Leadership Election is still functional
23CASE16: Install Distributed Primitives app
24CASE17: Check for basic functionality with distributed primitives
25"""
26
27
Jon Hallb3ed8ed2015-10-28 16:43:55 -070028class HAstopNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -070029
30 def __init__( self ):
31 self.default = ''
32
33 def CASE1( self, main ):
34 """
35 CASE1 is to compile ONOS and push it to the test machines
36
37 Startup sequence:
38 cell <name>
39 onos-verify-cell
40 NOTE: temporary - onos-remove-raft-logs
41 onos-uninstall
42 start mininet
43 git pull
44 mvn clean install
45 onos-package
46 onos-install -f
47 onos-wait-for-start
48 start cli sessions
49 start tcpdump
50 """
Jon Halle1a3b752015-07-22 13:02:46 -070051 import imp
Jon Hall3b489db2015-10-05 14:38:37 -070052 import pexpect
Jon Hallf3d16e72015-12-16 17:45:08 -080053 import time
Jon Halla440e872016-03-31 15:15:50 -070054 import json
Jon Hallb3ed8ed2015-10-28 16:43:55 -070055 main.log.info( "ONOS HA test: Stop a minority of ONOS nodes - " +
Jon Hall5cf14d52015-07-16 12:15:19 -070056 "initialization" )
57 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070058 main.caseExplanation = "Setup the test environment including " +\
Jon Hall5cf14d52015-07-16 12:15:19 -070059 "installing ONOS, starting Mininet and ONOS" +\
60 "cli sessions."
Jon Hall5cf14d52015-07-16 12:15:19 -070061
62 # load some variables from the params file
63 PULLCODE = False
64 if main.params[ 'Git' ] == 'True':
65 PULLCODE = True
66 gitBranch = main.params[ 'branch' ]
67 cellName = main.params[ 'ENV' ][ 'cellName' ]
68
Jon Halle1a3b752015-07-22 13:02:46 -070069 main.numCtrls = int( main.params[ 'num_controllers' ] )
Jon Hall5cf14d52015-07-16 12:15:19 -070070 if main.ONOSbench.maxNodes:
Jon Halle1a3b752015-07-22 13:02:46 -070071 if main.ONOSbench.maxNodes < main.numCtrls:
72 main.numCtrls = int( main.ONOSbench.maxNodes )
73 # set global variables
Jon Hall5cf14d52015-07-16 12:15:19 -070074 global ONOS1Port
75 global ONOS2Port
76 global ONOS3Port
77 global ONOS4Port
78 global ONOS5Port
79 global ONOS6Port
80 global ONOS7Port
Jon Halla440e872016-03-31 15:15:50 -070081 # These are for csv plotting in jenkins
82 global labels
83 global data
84 labels = []
85 data = []
Jon Hall5cf14d52015-07-16 12:15:19 -070086
87 # FIXME: just get controller port from params?
88 # TODO: do we really need all these?
89 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
90 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
91 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
92 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
93 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
94 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
95 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
96
Jon Halle1a3b752015-07-22 13:02:46 -070097 try:
Jon Halla440e872016-03-31 15:15:50 -070098 from tests.HAsanity.dependencies.Counters import Counters
99 main.Counters = Counters()
Jon Halle1a3b752015-07-22 13:02:46 -0700100 except Exception as e:
101 main.log.exception( e )
102 main.cleanup()
103 main.exit()
104
105 main.CLIs = []
106 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700107 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700108 for i in range( 1, main.numCtrls + 1 ):
109 try:
110 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
111 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
112 ipList.append( main.nodes[ -1 ].ip_address )
113 except AttributeError:
114 break
Jon Hall5cf14d52015-07-16 12:15:19 -0700115
116 main.step( "Create cell file" )
117 cellAppString = main.params[ 'ENV' ][ 'appString' ]
118 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
119 main.Mininet1.ip_address,
120 cellAppString, ipList )
121 main.step( "Applying cell variable to environment" )
122 cellResult = main.ONOSbench.setCell( cellName )
123 verifyResult = main.ONOSbench.verifyCell()
124
125 # FIXME:this is short term fix
126 main.log.info( "Removing raft logs" )
127 main.ONOSbench.onosRemoveRaftLogs()
128
129 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700130 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700131 main.ONOSbench.onosUninstall( node.ip_address )
132
133 # Make sure ONOS is DEAD
134 main.log.info( "Killing any ONOS processes" )
135 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700136 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700137 killed = main.ONOSbench.onosKill( node.ip_address )
138 killResults = killResults and killed
139
140 cleanInstallResult = main.TRUE
141 gitPullResult = main.TRUE
142
143 main.step( "Starting Mininet" )
144 # scp topo file to mininet
145 # TODO: move to params?
146 topoName = "obelisk.py"
147 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700148 main.ONOSbench.scp( main.Mininet1,
149 filePath + topoName,
150 main.Mininet1.home,
151 direction="to" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700152 mnResult = main.Mininet1.startNet( )
153 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
154 onpass="Mininet Started",
155 onfail="Error starting Mininet" )
156
157 main.step( "Git checkout and pull " + gitBranch )
158 if PULLCODE:
159 main.ONOSbench.gitCheckout( gitBranch )
160 gitPullResult = main.ONOSbench.gitPull()
161 # values of 1 or 3 are good
162 utilities.assert_lesser( expect=0, actual=gitPullResult,
163 onpass="Git pull successful",
164 onfail="Git pull failed" )
165 main.ONOSbench.getVersion( report=True )
166
167 main.step( "Using mvn clean install" )
168 cleanInstallResult = main.TRUE
169 if PULLCODE and gitPullResult == main.TRUE:
170 cleanInstallResult = main.ONOSbench.cleanInstall()
171 else:
172 main.log.warn( "Did not pull new code so skipping mvn " +
173 "clean install" )
174 utilities.assert_equals( expect=main.TRUE,
175 actual=cleanInstallResult,
176 onpass="MCI successful",
177 onfail="MCI failed" )
178 # GRAPHS
179 # NOTE: important params here:
180 # job = name of Jenkins job
181 # Plot Name = Plot-HA, only can be used if multiple plots
182 # index = The number of the graph under plot name
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700183 job = "HAstopNodes"
Jon Hall5cf14d52015-07-16 12:15:19 -0700184 plotName = "Plot-HA"
Jon Hall843f8bc2016-03-18 14:28:13 -0700185 index = "2"
Jon Hall5cf14d52015-07-16 12:15:19 -0700186 graphs = '<ac:structured-macro ac:name="html">\n'
187 graphs += '<ac:plain-text-body><![CDATA[\n'
188 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Halla9845df2016-01-15 14:55:58 -0800189 '/plot/' + plotName + '/getPlot?index=' + index +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700190 '&width=500&height=300"' +\
191 'noborder="0" width="500" height="300" scrolling="yes" ' +\
192 'seamless="seamless"></iframe>\n'
193 graphs += ']]></ac:plain-text-body>\n'
194 graphs += '</ac:structured-macro>\n'
195 main.log.wiki(graphs)
196
197 main.step( "Creating ONOS package" )
Jon Hall3b489db2015-10-05 14:38:37 -0700198 # copy gen-partions file to ONOS
199 # NOTE: this assumes TestON and ONOS are on the same machine
200 srcFile = main.testDir + "/" + main.TEST + "/dependencies/onos-gen-partitions"
201 dstDir = main.ONOSbench.home + "/tools/test/bin/onos-gen-partitions"
202 cpResult = main.ONOSbench.secureCopy( main.ONOSbench.user_name,
203 main.ONOSbench.ip_address,
204 srcFile,
205 dstDir,
206 pwd=main.ONOSbench.pwd,
207 direction="from" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700208 packageResult = main.ONOSbench.onosPackage()
209 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
210 onpass="ONOS package successful",
211 onfail="ONOS package failed" )
212
213 main.step( "Installing ONOS package" )
214 onosInstallResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700215 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700216 tmpResult = main.ONOSbench.onosInstall( options="-f",
217 node=node.ip_address )
218 onosInstallResult = onosInstallResult and tmpResult
219 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
220 onpass="ONOS install successful",
221 onfail="ONOS install failed" )
Jon Hall3b489db2015-10-05 14:38:37 -0700222 # clean up gen-partitions file
223 try:
224 main.ONOSbench.handle.sendline( "cd " + main.ONOSbench.home )
225 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
226 main.ONOSbench.handle.sendline( "git checkout -- tools/test/bin/onos-gen-partitions" )
227 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
228 main.log.info( " Cleaning custom gen partitions file, response was: \n" +
229 str( main.ONOSbench.handle.before ) )
230 except ( pexpect.TIMEOUT, pexpect.EOF ):
231 main.log.exception( "ONOSbench: pexpect exception found:" +
232 main.ONOSbench.handle.before )
233 main.cleanup()
234 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -0700235
236 main.step( "Checking if ONOS is up yet" )
237 for i in range( 2 ):
238 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700239 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700240 started = main.ONOSbench.isup( node.ip_address )
241 if not started:
Jon Hallc6793552016-01-19 14:18:37 -0800242 main.log.error( node.name + " hasn't started" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700243 onosIsupResult = onosIsupResult and started
244 if onosIsupResult == main.TRUE:
245 break
246 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
247 onpass="ONOS startup successful",
248 onfail="ONOS startup failed" )
249
250 main.log.step( "Starting ONOS CLI sessions" )
251 cliResults = main.TRUE
252 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700253 for i in range( main.numCtrls ):
254 t = main.Thread( target=main.CLIs[i].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -0700255 name="startOnosCli-" + str( i ),
Jon Halle1a3b752015-07-22 13:02:46 -0700256 args=[main.nodes[i].ip_address] )
Jon Hall5cf14d52015-07-16 12:15:19 -0700257 threads.append( t )
258 t.start()
259
260 for t in threads:
261 t.join()
262 cliResults = cliResults and t.result
263 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
264 onpass="ONOS cli startup successful",
265 onfail="ONOS cli startup failed" )
266
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700267 # Create a list of active nodes for use when some nodes are stopped
268 main.activeNodes = [ i for i in range( 0, len( main.CLIs ) ) ]
269
Jon Hall5cf14d52015-07-16 12:15:19 -0700270 if main.params[ 'tcpdump' ].lower() == "true":
271 main.step( "Start Packet Capture MN" )
272 main.Mininet2.startTcpdump(
273 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
274 + "-MN.pcap",
275 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
276 port=main.params[ 'MNtcpdump' ][ 'port' ] )
277
278 main.step( "App Ids check" )
279 appCheck = main.TRUE
280 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700281 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -0700282 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700283 name="appToIDCheck-" + str( i ),
284 args=[] )
285 threads.append( t )
286 t.start()
287
288 for t in threads:
289 t.join()
290 appCheck = appCheck and t.result
291 if appCheck != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700292 node = main.activeNodes[0]
293 main.log.warn( main.CLIs[node].apps() )
294 main.log.warn( main.CLIs[node].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700295 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
296 onpass="App Ids seem to be correct",
297 onfail="Something is wrong with app Ids" )
298
Jon Halla440e872016-03-31 15:15:50 -0700299 main.step( "Checking ONOS nodes" )
300 nodesOutput = []
301 nodeResults = main.TRUE
302 threads = []
303 for i in main.activeNodes:
304 t = main.Thread( target=main.CLIs[i].nodes,
305 name="nodes-" + str( i ),
306 args=[ ] )
307 threads.append( t )
308 t.start()
309
310 for t in threads:
311 t.join()
312 nodesOutput.append( t.result )
313 ips = [ main.nodes[node].ip_address for node in main.activeNodes ]
314 ips.sort()
315 for i in nodesOutput:
316 try:
317 current = json.loads( i )
318 activeIps = []
319 currentResult = main.FALSE
320 for node in current:
321 if node['state'] == 'READY':
322 activeIps.append( node['ip'] )
323 activeIps.sort()
324 if ips == activeIps:
325 currentResult = main.TRUE
326 except ( ValueError, TypeError ):
327 main.log.error( "Error parsing nodes output" )
328 main.log.warn( repr( i ) )
329 currentResult = main.FALSE
330 nodeResults = nodeResults and currentResult
331 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
332 onpass="Nodes check successful",
333 onfail="Nodes check NOT successful" )
334
335 if not nodeResults:
336 for cli in main.CLIs:
337 main.log.debug( "{} components not ACTIVE: \n{}".format(
338 cli.name,
339 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
340
Jon Hall5cf14d52015-07-16 12:15:19 -0700341 if cliResults == main.FALSE:
342 main.log.error( "Failed to start ONOS, stopping test" )
343 main.cleanup()
344 main.exit()
345
346 def CASE2( self, main ):
347 """
348 Assign devices to controllers
349 """
350 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700351 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700352 assert main, "main not defined"
353 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700354 assert main.CLIs, "main.CLIs not defined"
355 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700356 assert ONOS1Port, "ONOS1Port not defined"
357 assert ONOS2Port, "ONOS2Port not defined"
358 assert ONOS3Port, "ONOS3Port not defined"
359 assert ONOS4Port, "ONOS4Port not defined"
360 assert ONOS5Port, "ONOS5Port not defined"
361 assert ONOS6Port, "ONOS6Port not defined"
362 assert ONOS7Port, "ONOS7Port not defined"
363
364 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700365 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700366 "and check that an ONOS node becomes the " +\
367 "master of the device."
368 main.step( "Assign switches to controllers" )
369
370 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700371 for i in range( main.numCtrls ):
372 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700373 swList = []
374 for i in range( 1, 29 ):
375 swList.append( "s" + str( i ) )
376 main.Mininet1.assignSwController( sw=swList, ip=ipList )
377
378 mastershipCheck = main.TRUE
379 for i in range( 1, 29 ):
380 response = main.Mininet1.getSwController( "s" + str( i ) )
381 try:
382 main.log.info( str( response ) )
383 except Exception:
384 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700385 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700386 if re.search( "tcp:" + node.ip_address, response ):
387 mastershipCheck = mastershipCheck and main.TRUE
388 else:
389 main.log.error( "Error, node " + node.ip_address + " is " +
390 "not in the list of controllers s" +
391 str( i ) + " is connecting to." )
392 mastershipCheck = main.FALSE
393 utilities.assert_equals(
394 expect=main.TRUE,
395 actual=mastershipCheck,
396 onpass="Switch mastership assigned correctly",
397 onfail="Switches not assigned correctly to controllers" )
398
399 def CASE21( self, main ):
400 """
401 Assign mastership to controllers
402 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700403 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700404 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700405 assert main, "main not defined"
406 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700407 assert main.CLIs, "main.CLIs not defined"
408 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700409 assert ONOS1Port, "ONOS1Port not defined"
410 assert ONOS2Port, "ONOS2Port not defined"
411 assert ONOS3Port, "ONOS3Port not defined"
412 assert ONOS4Port, "ONOS4Port not defined"
413 assert ONOS5Port, "ONOS5Port not defined"
414 assert ONOS6Port, "ONOS6Port not defined"
415 assert ONOS7Port, "ONOS7Port not defined"
416
417 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700418 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700419 "device. Then manually assign" +\
420 " mastership to specific ONOS nodes using" +\
421 " 'device-role'"
422 main.step( "Assign mastership of switches to specific controllers" )
423 # Manually assign mastership to the controller we want
424 roleCall = main.TRUE
425
426 ipList = [ ]
427 deviceList = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700428 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700429 try:
430 # Assign mastership to specific controllers. This assignment was
431 # determined for a 7 node cluser, but will work with any sized
432 # cluster
433 for i in range( 1, 29 ): # switches 1 through 28
434 # set up correct variables:
435 if i == 1:
436 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700437 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700438 deviceId = onosCli.getDevice( "1000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700439 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700440 c = 1 % main.numCtrls
441 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700442 deviceId = onosCli.getDevice( "2000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700443 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700444 c = 1 % main.numCtrls
445 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700446 deviceId = onosCli.getDevice( "3000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700447 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700448 c = 3 % main.numCtrls
449 ip = main.nodes[ c ].ip_address # ONOS4
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700450 deviceId = onosCli.getDevice( "3004" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700451 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700452 c = 2 % main.numCtrls
453 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700454 deviceId = onosCli.getDevice( "5000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700455 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700456 c = 2 % main.numCtrls
457 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700458 deviceId = onosCli.getDevice( "6000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700459 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700460 c = 5 % main.numCtrls
461 ip = main.nodes[ c ].ip_address # ONOS6
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700462 deviceId = onosCli.getDevice( "6007" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700463 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700464 c = 4 % main.numCtrls
465 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700466 dpid = '3' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700467 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700468 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700469 c = 6 % main.numCtrls
470 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700471 dpid = '6' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700472 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700473 elif i == 28:
474 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700475 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700476 deviceId = onosCli.getDevice( "2800" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700477 else:
478 main.log.error( "You didn't write an else statement for " +
479 "switch s" + str( i ) )
480 roleCall = main.FALSE
481 # Assign switch
482 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
483 # TODO: make this controller dynamic
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700484 roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
Jon Hall5cf14d52015-07-16 12:15:19 -0700485 ipList.append( ip )
486 deviceList.append( deviceId )
487 except ( AttributeError, AssertionError ):
488 main.log.exception( "Something is wrong with ONOS device view" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700489 main.log.info( onosCli.devices() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700490 utilities.assert_equals(
491 expect=main.TRUE,
492 actual=roleCall,
493 onpass="Re-assigned switch mastership to designated controller",
494 onfail="Something wrong with deviceRole calls" )
495
496 main.step( "Check mastership was correctly assigned" )
497 roleCheck = main.TRUE
498 # NOTE: This is due to the fact that device mastership change is not
499 # atomic and is actually a multi step process
500 time.sleep( 5 )
501 for i in range( len( ipList ) ):
502 ip = ipList[i]
503 deviceId = deviceList[i]
504 # Check assignment
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700505 master = onosCli.getRole( deviceId ).get( 'master' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700506 if ip in master:
507 roleCheck = roleCheck and main.TRUE
508 else:
509 roleCheck = roleCheck and main.FALSE
510 main.log.error( "Error, controller " + ip + " is not" +
511 " master " + "of device " +
512 str( deviceId ) + ". Master is " +
513 repr( master ) + "." )
514 utilities.assert_equals(
515 expect=main.TRUE,
516 actual=roleCheck,
517 onpass="Switches were successfully reassigned to designated " +
518 "controller",
519 onfail="Switches were not successfully reassigned" )
520
521 def CASE3( self, main ):
522 """
523 Assign intents
524 """
525 import time
526 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700527 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700528 assert main, "main not defined"
529 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700530 assert main.CLIs, "main.CLIs not defined"
531 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700532 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700533 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700534 "assign predetermined host-to-host intents." +\
535 " After installation, check that the intent" +\
536 " is distributed to all nodes and the state" +\
537 " is INSTALLED"
538
539 # install onos-app-fwd
540 main.step( "Install reactive forwarding app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700541 onosCli = main.CLIs[ main.activeNodes[0] ]
542 installResults = onosCli.activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700543 utilities.assert_equals( expect=main.TRUE, actual=installResults,
544 onpass="Install fwd successful",
545 onfail="Install fwd failed" )
546
547 main.step( "Check app ids" )
548 appCheck = main.TRUE
549 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700550 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -0700551 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700552 name="appToIDCheck-" + str( i ),
553 args=[] )
554 threads.append( t )
555 t.start()
556
557 for t in threads:
558 t.join()
559 appCheck = appCheck and t.result
560 if appCheck != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700561 main.log.warn( onosCli.apps() )
562 main.log.warn( onosCli.appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700563 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
564 onpass="App Ids seem to be correct",
565 onfail="Something is wrong with app Ids" )
566
567 main.step( "Discovering Hosts( Via pingall for now )" )
568 # FIXME: Once we have a host discovery mechanism, use that instead
569 # REACTIVE FWD test
570 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700571 passMsg = "Reactive Pingall test passed"
572 time1 = time.time()
573 pingResult = main.Mininet1.pingall()
574 time2 = time.time()
575 if not pingResult:
576 main.log.warn("First pingall failed. Trying again...")
Jon Hall5cf14d52015-07-16 12:15:19 -0700577 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700578 passMsg += " on the second try"
579 utilities.assert_equals(
580 expect=main.TRUE,
581 actual=pingResult,
582 onpass= passMsg,
583 onfail="Reactive Pingall failed, " +
584 "one or more ping pairs failed" )
585 main.log.info( "Time for pingall: %2f seconds" %
586 ( time2 - time1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700587 # timeout for fwd flows
588 time.sleep( 11 )
589 # uninstall onos-app-fwd
590 main.step( "Uninstall reactive forwarding app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700591 node = main.activeNodes[0]
592 uninstallResult = main.CLIs[node].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700593 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
594 onpass="Uninstall fwd successful",
595 onfail="Uninstall fwd failed" )
596
597 main.step( "Check app ids" )
598 threads = []
599 appCheck2 = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700600 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -0700601 t = main.Thread( target=main.CLIs[i].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700602 name="appToIDCheck-" + str( i ),
603 args=[] )
604 threads.append( t )
605 t.start()
606
607 for t in threads:
608 t.join()
609 appCheck2 = appCheck2 and t.result
610 if appCheck2 != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700611 node = main.activeNodes[0]
612 main.log.warn( main.CLIs[node].apps() )
613 main.log.warn( main.CLIs[node].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700614 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
615 onpass="App Ids seem to be correct",
616 onfail="Something is wrong with app Ids" )
617
618 main.step( "Add host intents via cli" )
619 intentIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700620 # TODO: move the host numbers to params
621 # Maybe look at all the paths we ping?
Jon Hall5cf14d52015-07-16 12:15:19 -0700622 intentAddResult = True
623 hostResult = main.TRUE
624 for i in range( 8, 18 ):
625 main.log.info( "Adding host intent between h" + str( i ) +
626 " and h" + str( i + 10 ) )
627 host1 = "00:00:00:00:00:" + \
628 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
629 host2 = "00:00:00:00:00:" + \
630 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
631 # NOTE: getHost can return None
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700632 host1Dict = onosCli.getHost( host1 )
633 host2Dict = onosCli.getHost( host2 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700634 host1Id = None
635 host2Id = None
636 if host1Dict and host2Dict:
637 host1Id = host1Dict.get( 'id', None )
638 host2Id = host2Dict.get( 'id', None )
639 if host1Id and host2Id:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700640 nodeNum = ( i % len( main.activeNodes ) )
641 node = main.activeNodes[nodeNum]
642 tmpId = main.CLIs[node].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700643 if tmpId:
644 main.log.info( "Added intent with id: " + tmpId )
645 intentIds.append( tmpId )
646 else:
647 main.log.error( "addHostIntent returned: " +
648 repr( tmpId ) )
649 else:
650 main.log.error( "Error, getHost() failed for h" + str( i ) +
651 " and/or h" + str( i + 10 ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700652 node = main.activeNodes[0]
653 hosts = main.CLIs[node].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700654 main.log.warn( "Hosts output: " )
655 try:
656 main.log.warn( json.dumps( json.loads( hosts ),
657 sort_keys=True,
658 indent=4,
659 separators=( ',', ': ' ) ) )
660 except ( ValueError, TypeError ):
661 main.log.warn( repr( hosts ) )
662 hostResult = main.FALSE
663 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
664 onpass="Found a host id for each host",
665 onfail="Error looking up host ids" )
666
667 intentStart = time.time()
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700668 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700669 main.log.info( "Submitted intents: " + str( intentIds ) )
670 main.log.info( "Intents in ONOS: " + str( onosIds ) )
671 for intent in intentIds:
672 if intent in onosIds:
673 pass # intent submitted is in onos
674 else:
675 intentAddResult = False
676 if intentAddResult:
677 intentStop = time.time()
678 else:
679 intentStop = None
680 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700681 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700682 intentStates = []
683 installedCheck = True
684 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
685 count = 0
686 try:
687 for intent in json.loads( intents ):
688 state = intent.get( 'state', None )
689 if "INSTALLED" not in state:
690 installedCheck = False
691 intentId = intent.get( 'id', None )
692 intentStates.append( ( intentId, state ) )
693 except ( ValueError, TypeError ):
694 main.log.exception( "Error parsing intents" )
695 # add submitted intents not in the store
696 tmplist = [ i for i, s in intentStates ]
697 missingIntents = False
698 for i in intentIds:
699 if i not in tmplist:
700 intentStates.append( ( i, " - " ) )
701 missingIntents = True
702 intentStates.sort()
703 for i, s in intentStates:
704 count += 1
705 main.log.info( "%-6s%-15s%-15s" %
706 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700707 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700708 try:
709 missing = False
710 if leaders:
711 parsedLeaders = json.loads( leaders )
712 main.log.warn( json.dumps( parsedLeaders,
713 sort_keys=True,
714 indent=4,
715 separators=( ',', ': ' ) ) )
716 # check for all intent partitions
717 topics = []
718 for i in range( 14 ):
719 topics.append( "intent-partition-" + str( i ) )
720 main.log.debug( topics )
721 ONOStopics = [ j['topic'] for j in parsedLeaders ]
722 for topic in topics:
723 if topic not in ONOStopics:
724 main.log.error( "Error: " + topic +
725 " not in leaders" )
726 missing = True
727 else:
728 main.log.error( "leaders() returned None" )
729 except ( ValueError, TypeError ):
730 main.log.exception( "Error parsing leaders" )
731 main.log.error( repr( leaders ) )
732 # Check all nodes
733 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700734 for i in main.activeNodes:
735 response = main.CLIs[i].leaders( jsonFormat=False)
736 main.log.warn( str( main.CLIs[i].name ) + " leaders output: \n" +
Jon Hall5cf14d52015-07-16 12:15:19 -0700737 str( response ) )
738
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700739 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700740 try:
741 if partitions :
742 parsedPartitions = json.loads( partitions )
743 main.log.warn( json.dumps( parsedPartitions,
744 sort_keys=True,
745 indent=4,
746 separators=( ',', ': ' ) ) )
747 # TODO check for a leader in all paritions
748 # TODO check for consistency among nodes
749 else:
750 main.log.error( "partitions() returned None" )
751 except ( ValueError, TypeError ):
752 main.log.exception( "Error parsing partitions" )
753 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700754 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700755 try:
756 if pendingMap :
757 parsedPending = json.loads( pendingMap )
758 main.log.warn( json.dumps( parsedPending,
759 sort_keys=True,
760 indent=4,
761 separators=( ',', ': ' ) ) )
762 # TODO check something here?
763 else:
764 main.log.error( "pendingMap() returned None" )
765 except ( ValueError, TypeError ):
766 main.log.exception( "Error parsing pending map" )
767 main.log.error( repr( pendingMap ) )
768
769 intentAddResult = bool( intentAddResult and not missingIntents and
770 installedCheck )
771 if not intentAddResult:
772 main.log.error( "Error in pushing host intents to ONOS" )
773
774 main.step( "Intent Anti-Entropy dispersion" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700775 for j in range(100):
Jon Hall5cf14d52015-07-16 12:15:19 -0700776 correct = True
777 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700778 for i in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700779 onosIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700780 ids = main.CLIs[i].getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700781 onosIds.append( ids )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700782 main.log.debug( "Intents in " + main.CLIs[i].name + ": " +
Jon Hall5cf14d52015-07-16 12:15:19 -0700783 str( sorted( onosIds ) ) )
784 if sorted( ids ) != sorted( intentIds ):
785 main.log.warn( "Set of intent IDs doesn't match" )
786 correct = False
787 break
788 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700789 intents = json.loads( main.CLIs[i].intents() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700790 for intent in intents:
791 if intent[ 'state' ] != "INSTALLED":
792 main.log.warn( "Intent " + intent[ 'id' ] +
793 " is " + intent[ 'state' ] )
794 correct = False
795 break
796 if correct:
797 break
798 else:
799 time.sleep(1)
800 if not intentStop:
801 intentStop = time.time()
802 global gossipTime
803 gossipTime = intentStop - intentStart
804 main.log.info( "It took about " + str( gossipTime ) +
805 " seconds for all intents to appear in each node" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700806 gossipPeriod = int( main.params['timers']['gossip'] )
807 maxGossipTime = gossipPeriod * len( main.activeNodes )
Jon Hall5cf14d52015-07-16 12:15:19 -0700808 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700809 expect=maxGossipTime, actual=gossipTime,
Jon Hall5cf14d52015-07-16 12:15:19 -0700810 onpass="ECM anti-entropy for intents worked within " +
811 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700812 onfail="Intent ECM anti-entropy took too long. " +
813 "Expected time:{}, Actual time:{}".format( maxGossipTime,
814 gossipTime ) )
815 if gossipTime <= maxGossipTime:
Jon Hall5cf14d52015-07-16 12:15:19 -0700816 intentAddResult = True
817
818 if not intentAddResult or "key" in pendingMap:
819 import time
820 installedCheck = True
821 main.log.info( "Sleeping 60 seconds to see if intents are found" )
822 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700823 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700824 main.log.info( "Submitted intents: " + str( intentIds ) )
825 main.log.info( "Intents in ONOS: " + str( onosIds ) )
826 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700827 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700828 intentStates = []
829 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
830 count = 0
831 try:
832 for intent in json.loads( intents ):
833 # Iter through intents of a node
834 state = intent.get( 'state', None )
835 if "INSTALLED" not in state:
836 installedCheck = False
837 intentId = intent.get( 'id', None )
838 intentStates.append( ( intentId, state ) )
839 except ( ValueError, TypeError ):
840 main.log.exception( "Error parsing intents" )
841 # add submitted intents not in the store
842 tmplist = [ i for i, s in intentStates ]
843 for i in intentIds:
844 if i not in tmplist:
845 intentStates.append( ( i, " - " ) )
846 intentStates.sort()
847 for i, s in intentStates:
848 count += 1
849 main.log.info( "%-6s%-15s%-15s" %
850 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700851 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700852 try:
853 missing = False
854 if leaders:
855 parsedLeaders = json.loads( leaders )
856 main.log.warn( json.dumps( parsedLeaders,
857 sort_keys=True,
858 indent=4,
859 separators=( ',', ': ' ) ) )
860 # check for all intent partitions
861 # check for election
862 topics = []
863 for i in range( 14 ):
864 topics.append( "intent-partition-" + str( i ) )
865 # FIXME: this should only be after we start the app
866 topics.append( "org.onosproject.election" )
867 main.log.debug( topics )
868 ONOStopics = [ j['topic'] for j in parsedLeaders ]
869 for topic in topics:
870 if topic not in ONOStopics:
871 main.log.error( "Error: " + topic +
872 " not in leaders" )
873 missing = True
874 else:
875 main.log.error( "leaders() returned None" )
876 except ( ValueError, TypeError ):
877 main.log.exception( "Error parsing leaders" )
878 main.log.error( repr( leaders ) )
879 # Check all nodes
880 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700881 for i in main.activeNodes:
882 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -0700883 response = node.leaders( jsonFormat=False)
884 main.log.warn( str( node.name ) + " leaders output: \n" +
885 str( response ) )
886
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700887 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700888 try:
889 if partitions :
890 parsedPartitions = json.loads( partitions )
891 main.log.warn( json.dumps( parsedPartitions,
892 sort_keys=True,
893 indent=4,
894 separators=( ',', ': ' ) ) )
895 # TODO check for a leader in all paritions
896 # TODO check for consistency among nodes
897 else:
898 main.log.error( "partitions() returned None" )
899 except ( ValueError, TypeError ):
900 main.log.exception( "Error parsing partitions" )
901 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700902 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700903 try:
904 if pendingMap :
905 parsedPending = json.loads( pendingMap )
906 main.log.warn( json.dumps( parsedPending,
907 sort_keys=True,
908 indent=4,
909 separators=( ',', ': ' ) ) )
910 # TODO check something here?
911 else:
912 main.log.error( "pendingMap() returned None" )
913 except ( ValueError, TypeError ):
914 main.log.exception( "Error parsing pending map" )
915 main.log.error( repr( pendingMap ) )
916
917 def CASE4( self, main ):
918 """
919 Ping across added host intents
920 """
921 import json
922 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700923 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700924 assert main, "main not defined"
925 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700926 assert main.CLIs, "main.CLIs not defined"
927 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700928 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700929 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700930 "functionality and check the state of " +\
931 "the intent"
932 main.step( "Ping across added host intents" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700933 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700934 PingResult = main.TRUE
935 for i in range( 8, 18 ):
936 ping = main.Mininet1.pingHost( src="h" + str( i ),
937 target="h" + str( i + 10 ) )
938 PingResult = PingResult and ping
939 if ping == main.FALSE:
940 main.log.warn( "Ping failed between h" + str( i ) +
941 " and h" + str( i + 10 ) )
942 elif ping == main.TRUE:
943 main.log.info( "Ping test passed!" )
944 # Don't set PingResult or you'd override failures
945 if PingResult == main.FALSE:
946 main.log.error(
947 "Intents have not been installed correctly, pings failed." )
948 # TODO: pretty print
949 main.log.warn( "ONOS1 intents: " )
950 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700951 tmpIntents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700952 main.log.warn( json.dumps( json.loads( tmpIntents ),
953 sort_keys=True,
954 indent=4,
955 separators=( ',', ': ' ) ) )
956 except ( ValueError, TypeError ):
957 main.log.warn( repr( tmpIntents ) )
958 utilities.assert_equals(
959 expect=main.TRUE,
960 actual=PingResult,
961 onpass="Intents have been installed correctly and pings work",
962 onfail="Intents have not been installed correctly, pings failed." )
963
964 main.step( "Check Intent state" )
965 installedCheck = False
966 loopCount = 0
967 while not installedCheck and loopCount < 40:
968 installedCheck = True
969 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700970 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700971 intentStates = []
972 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
973 count = 0
974 # Iter through intents of a node
975 try:
976 for intent in json.loads( intents ):
977 state = intent.get( 'state', None )
978 if "INSTALLED" not in state:
979 installedCheck = False
980 intentId = intent.get( 'id', None )
981 intentStates.append( ( intentId, state ) )
982 except ( ValueError, TypeError ):
983 main.log.exception( "Error parsing intents." )
984 # Print states
985 intentStates.sort()
986 for i, s in intentStates:
987 count += 1
988 main.log.info( "%-6s%-15s%-15s" %
989 ( str( count ), str( i ), str( s ) ) )
990 if not installedCheck:
991 time.sleep( 1 )
992 loopCount += 1
993 utilities.assert_equals( expect=True, actual=installedCheck,
994 onpass="Intents are all INSTALLED",
995 onfail="Intents are not all in " +
996 "INSTALLED state" )
997
998 main.step( "Check leadership of topics" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700999 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001000 topicCheck = main.TRUE
1001 try:
1002 if leaders:
1003 parsedLeaders = json.loads( leaders )
1004 main.log.warn( json.dumps( parsedLeaders,
1005 sort_keys=True,
1006 indent=4,
1007 separators=( ',', ': ' ) ) )
1008 # check for all intent partitions
1009 # check for election
1010 # TODO: Look at Devices as topics now that it uses this system
1011 topics = []
1012 for i in range( 14 ):
1013 topics.append( "intent-partition-" + str( i ) )
1014 # FIXME: this should only be after we start the app
1015 # FIXME: topics.append( "org.onosproject.election" )
1016 # Print leaders output
1017 main.log.debug( topics )
1018 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1019 for topic in topics:
1020 if topic not in ONOStopics:
1021 main.log.error( "Error: " + topic +
1022 " not in leaders" )
1023 topicCheck = main.FALSE
1024 else:
1025 main.log.error( "leaders() returned None" )
1026 topicCheck = main.FALSE
1027 except ( ValueError, TypeError ):
1028 topicCheck = main.FALSE
1029 main.log.exception( "Error parsing leaders" )
1030 main.log.error( repr( leaders ) )
1031 # TODO: Check for a leader of these topics
1032 # Check all nodes
1033 if topicCheck:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001034 for i in main.activeNodes:
1035 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07001036 response = node.leaders( jsonFormat=False)
1037 main.log.warn( str( node.name ) + " leaders output: \n" +
1038 str( response ) )
1039
1040 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
1041 onpass="intent Partitions is in leaders",
1042 onfail="Some topics were lost " )
1043 # Print partitions
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001044 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001045 try:
1046 if partitions :
1047 parsedPartitions = json.loads( partitions )
1048 main.log.warn( json.dumps( parsedPartitions,
1049 sort_keys=True,
1050 indent=4,
1051 separators=( ',', ': ' ) ) )
1052 # TODO check for a leader in all paritions
1053 # TODO check for consistency among nodes
1054 else:
1055 main.log.error( "partitions() returned None" )
1056 except ( ValueError, TypeError ):
1057 main.log.exception( "Error parsing partitions" )
1058 main.log.error( repr( partitions ) )
1059 # Print Pending Map
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001060 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001061 try:
1062 if pendingMap :
1063 parsedPending = json.loads( pendingMap )
1064 main.log.warn( json.dumps( parsedPending,
1065 sort_keys=True,
1066 indent=4,
1067 separators=( ',', ': ' ) ) )
1068 # TODO check something here?
1069 else:
1070 main.log.error( "pendingMap() returned None" )
1071 except ( ValueError, TypeError ):
1072 main.log.exception( "Error parsing pending map" )
1073 main.log.error( repr( pendingMap ) )
1074
1075 if not installedCheck:
1076 main.log.info( "Waiting 60 seconds to see if the state of " +
1077 "intents change" )
1078 time.sleep( 60 )
1079 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001080 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001081 intentStates = []
1082 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1083 count = 0
1084 # Iter through intents of a node
1085 try:
1086 for intent in json.loads( intents ):
1087 state = intent.get( 'state', None )
1088 if "INSTALLED" not in state:
1089 installedCheck = False
1090 intentId = intent.get( 'id', None )
1091 intentStates.append( ( intentId, state ) )
1092 except ( ValueError, TypeError ):
1093 main.log.exception( "Error parsing intents." )
1094 intentStates.sort()
1095 for i, s in intentStates:
1096 count += 1
1097 main.log.info( "%-6s%-15s%-15s" %
1098 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001099 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001100 try:
1101 missing = False
1102 if leaders:
1103 parsedLeaders = json.loads( leaders )
1104 main.log.warn( json.dumps( parsedLeaders,
1105 sort_keys=True,
1106 indent=4,
1107 separators=( ',', ': ' ) ) )
1108 # check for all intent partitions
1109 # check for election
1110 topics = []
1111 for i in range( 14 ):
1112 topics.append( "intent-partition-" + str( i ) )
1113 # FIXME: this should only be after we start the app
1114 topics.append( "org.onosproject.election" )
1115 main.log.debug( topics )
1116 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1117 for topic in topics:
1118 if topic not in ONOStopics:
1119 main.log.error( "Error: " + topic +
1120 " not in leaders" )
1121 missing = True
1122 else:
1123 main.log.error( "leaders() returned None" )
1124 except ( ValueError, TypeError ):
1125 main.log.exception( "Error parsing leaders" )
1126 main.log.error( repr( leaders ) )
1127 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001128 for i in main.activeNodes:
1129 node = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07001130 response = node.leaders( jsonFormat=False)
1131 main.log.warn( str( node.name ) + " leaders output: \n" +
1132 str( response ) )
1133
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001134 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001135 try:
1136 if partitions :
1137 parsedPartitions = json.loads( partitions )
1138 main.log.warn( json.dumps( parsedPartitions,
1139 sort_keys=True,
1140 indent=4,
1141 separators=( ',', ': ' ) ) )
1142 # TODO check for a leader in all paritions
1143 # TODO check for consistency among nodes
1144 else:
1145 main.log.error( "partitions() returned None" )
1146 except ( ValueError, TypeError ):
1147 main.log.exception( "Error parsing partitions" )
1148 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001149 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001150 try:
1151 if pendingMap :
1152 parsedPending = json.loads( pendingMap )
1153 main.log.warn( json.dumps( parsedPending,
1154 sort_keys=True,
1155 indent=4,
1156 separators=( ',', ': ' ) ) )
1157 # TODO check something here?
1158 else:
1159 main.log.error( "pendingMap() returned None" )
1160 except ( ValueError, TypeError ):
1161 main.log.exception( "Error parsing pending map" )
1162 main.log.error( repr( pendingMap ) )
1163 # Print flowrules
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001164 node = main.activeNodes[0]
1165 main.log.debug( main.CLIs[node].flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001166 main.step( "Wait a minute then ping again" )
1167 # the wait is above
1168 PingResult = main.TRUE
1169 for i in range( 8, 18 ):
1170 ping = main.Mininet1.pingHost( src="h" + str( i ),
1171 target="h" + str( i + 10 ) )
1172 PingResult = PingResult and ping
1173 if ping == main.FALSE:
1174 main.log.warn( "Ping failed between h" + str( i ) +
1175 " and h" + str( i + 10 ) )
1176 elif ping == main.TRUE:
1177 main.log.info( "Ping test passed!" )
1178 # Don't set PingResult or you'd override failures
1179 if PingResult == main.FALSE:
1180 main.log.error(
1181 "Intents have not been installed correctly, pings failed." )
1182 # TODO: pretty print
1183 main.log.warn( "ONOS1 intents: " )
1184 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001185 tmpIntents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001186 main.log.warn( json.dumps( json.loads( tmpIntents ),
1187 sort_keys=True,
1188 indent=4,
1189 separators=( ',', ': ' ) ) )
1190 except ( ValueError, TypeError ):
1191 main.log.warn( repr( tmpIntents ) )
1192 utilities.assert_equals(
1193 expect=main.TRUE,
1194 actual=PingResult,
1195 onpass="Intents have been installed correctly and pings work",
1196 onfail="Intents have not been installed correctly, pings failed." )
1197
1198 def CASE5( self, main ):
1199 """
1200 Reading state of ONOS
1201 """
1202 import json
1203 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001204 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001205 assert main, "main not defined"
1206 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001207 assert main.CLIs, "main.CLIs not defined"
1208 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001209
1210 main.case( "Setting up and gathering data for current state" )
1211 # The general idea for this test case is to pull the state of
1212 # ( intents,flows, topology,... ) from each ONOS node
1213 # We can then compare them with each other and also with past states
1214
1215 main.step( "Check that each switch has a master" )
1216 global mastershipState
1217 mastershipState = '[]'
1218
1219 # Assert that each device has a master
1220 rolesNotNull = main.TRUE
1221 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001222 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001223 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001224 name="rolesNotNull-" + str( i ),
1225 args=[] )
1226 threads.append( t )
1227 t.start()
1228
1229 for t in threads:
1230 t.join()
1231 rolesNotNull = rolesNotNull and t.result
1232 utilities.assert_equals(
1233 expect=main.TRUE,
1234 actual=rolesNotNull,
1235 onpass="Each device has a master",
1236 onfail="Some devices don't have a master assigned" )
1237
1238 main.step( "Get the Mastership of each switch from each controller" )
1239 ONOSMastership = []
1240 mastershipCheck = main.FALSE
1241 consistentMastership = True
1242 rolesResults = True
1243 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001244 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001245 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001246 name="roles-" + str( i ),
1247 args=[] )
1248 threads.append( t )
1249 t.start()
1250
1251 for t in threads:
1252 t.join()
1253 ONOSMastership.append( t.result )
1254
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001255 for i in range( len( ONOSMastership ) ):
1256 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001257 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001258 main.log.error( "Error in getting ONOS" + node + " roles" )
1259 main.log.warn( "ONOS" + node + " mastership response: " +
1260 repr( ONOSMastership[i] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001261 rolesResults = False
1262 utilities.assert_equals(
1263 expect=True,
1264 actual=rolesResults,
1265 onpass="No error in reading roles output",
1266 onfail="Error in reading roles from ONOS" )
1267
1268 main.step( "Check for consistency in roles from each controller" )
1269 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1270 main.log.info(
1271 "Switch roles are consistent across all ONOS nodes" )
1272 else:
1273 consistentMastership = False
1274 utilities.assert_equals(
1275 expect=True,
1276 actual=consistentMastership,
1277 onpass="Switch roles are consistent across all ONOS nodes",
1278 onfail="ONOS nodes have different views of switch roles" )
1279
1280 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001281 for i in range( len( main.activeNodes ) ):
1282 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001283 try:
1284 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001285 "ONOS" + node + " roles: ",
Jon Hall5cf14d52015-07-16 12:15:19 -07001286 json.dumps(
1287 json.loads( ONOSMastership[ i ] ),
1288 sort_keys=True,
1289 indent=4,
1290 separators=( ',', ': ' ) ) )
1291 except ( ValueError, TypeError ):
1292 main.log.warn( repr( ONOSMastership[ i ] ) )
1293 elif rolesResults and consistentMastership:
1294 mastershipCheck = main.TRUE
1295 mastershipState = ONOSMastership[ 0 ]
1296
1297 main.step( "Get the intents from each controller" )
1298 global intentState
1299 intentState = []
1300 ONOSIntents = []
1301 intentCheck = main.FALSE
1302 consistentIntents = True
1303 intentsResults = True
1304 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001305 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001306 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001307 name="intents-" + str( i ),
1308 args=[],
1309 kwargs={ 'jsonFormat': True } )
1310 threads.append( t )
1311 t.start()
1312
1313 for t in threads:
1314 t.join()
1315 ONOSIntents.append( t.result )
1316
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001317 for i in range( len( ONOSIntents ) ):
1318 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001319 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001320 main.log.error( "Error in getting ONOS" + node + " intents" )
1321 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001322 repr( ONOSIntents[ i ] ) )
1323 intentsResults = False
1324 utilities.assert_equals(
1325 expect=True,
1326 actual=intentsResults,
1327 onpass="No error in reading intents output",
1328 onfail="Error in reading intents from ONOS" )
1329
1330 main.step( "Check for consistency in Intents from each controller" )
1331 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
1332 main.log.info( "Intents are consistent across all ONOS " +
1333 "nodes" )
1334 else:
1335 consistentIntents = False
1336 main.log.error( "Intents not consistent" )
1337 utilities.assert_equals(
1338 expect=True,
1339 actual=consistentIntents,
1340 onpass="Intents are consistent across all ONOS nodes",
1341 onfail="ONOS nodes have different views of intents" )
1342
1343 if intentsResults:
1344 # Try to make it easy to figure out what is happening
1345 #
1346 # Intent ONOS1 ONOS2 ...
1347 # 0x01 INSTALLED INSTALLING
1348 # ... ... ...
1349 # ... ... ...
1350 title = " Id"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001351 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001352 title += " " * 10 + "ONOS" + str( n + 1 )
1353 main.log.warn( title )
1354 # get all intent keys in the cluster
1355 keys = []
Jon Halla440e872016-03-31 15:15:50 -07001356 try:
1357 # Get the set of all intent keys
Jon Hall5cf14d52015-07-16 12:15:19 -07001358 for nodeStr in ONOSIntents:
1359 node = json.loads( nodeStr )
1360 for intent in node:
Jon Halla440e872016-03-31 15:15:50 -07001361 keys.append( intent.get( 'id' ) )
1362 keys = set( keys )
1363 # For each intent key, print the state on each node
1364 for key in keys:
1365 row = "%-13s" % key
1366 for nodeStr in ONOSIntents:
1367 node = json.loads( nodeStr )
1368 for intent in node:
1369 if intent.get( 'id', "Error" ) == key:
1370 row += "%-15s" % intent.get( 'state' )
1371 main.log.warn( row )
1372 # End of intent state table
1373 except ValueError as e:
1374 main.log.exception( e )
1375 main.log.debug( "nodeStr was: " + repr( nodeStr ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001376
1377 if intentsResults and not consistentIntents:
1378 # print the json objects
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001379 n = str( main.activeNodes[-1] + 1 )
1380 main.log.debug( "ONOS" + n + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001381 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1382 sort_keys=True,
1383 indent=4,
1384 separators=( ',', ': ' ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001385 for i in range( len( ONOSIntents ) ):
1386 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001387 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001388 main.log.debug( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001389 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1390 sort_keys=True,
1391 indent=4,
1392 separators=( ',', ': ' ) ) )
1393 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001394 main.log.debug( "ONOS" + node + " intents match ONOS" +
1395 n + " intents" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001396 elif intentsResults and consistentIntents:
1397 intentCheck = main.TRUE
1398 intentState = ONOSIntents[ 0 ]
1399
1400 main.step( "Get the flows from each controller" )
1401 global flowState
1402 flowState = []
1403 ONOSFlows = []
1404 ONOSFlowsJson = []
1405 flowCheck = main.FALSE
1406 consistentFlows = True
1407 flowsResults = True
1408 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001409 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001410 t = main.Thread( target=main.CLIs[i].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001411 name="flows-" + str( i ),
1412 args=[],
1413 kwargs={ 'jsonFormat': True } )
1414 threads.append( t )
1415 t.start()
1416
1417 # NOTE: Flows command can take some time to run
1418 time.sleep(30)
1419 for t in threads:
1420 t.join()
1421 result = t.result
1422 ONOSFlows.append( result )
1423
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001424 for i in range( len( ONOSFlows ) ):
1425 num = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001426 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1427 main.log.error( "Error in getting ONOS" + num + " flows" )
1428 main.log.warn( "ONOS" + num + " flows response: " +
1429 repr( ONOSFlows[ i ] ) )
1430 flowsResults = False
1431 ONOSFlowsJson.append( None )
1432 else:
1433 try:
1434 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1435 except ( ValueError, TypeError ):
1436 # FIXME: change this to log.error?
1437 main.log.exception( "Error in parsing ONOS" + num +
1438 " response as json." )
1439 main.log.error( repr( ONOSFlows[ i ] ) )
1440 ONOSFlowsJson.append( None )
1441 flowsResults = False
1442 utilities.assert_equals(
1443 expect=True,
1444 actual=flowsResults,
1445 onpass="No error in reading flows output",
1446 onfail="Error in reading flows from ONOS" )
1447
1448 main.step( "Check for consistency in Flows from each controller" )
1449 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1450 if all( tmp ):
1451 main.log.info( "Flow count is consistent across all ONOS nodes" )
1452 else:
1453 consistentFlows = False
1454 utilities.assert_equals(
1455 expect=True,
1456 actual=consistentFlows,
1457 onpass="The flow count is consistent across all ONOS nodes",
1458 onfail="ONOS nodes have different flow counts" )
1459
1460 if flowsResults and not consistentFlows:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001461 for i in range( len( ONOSFlows ) ):
1462 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001463 try:
1464 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001465 "ONOS" + node + " flows: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001466 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1467 indent=4, separators=( ',', ': ' ) ) )
1468 except ( ValueError, TypeError ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001469 main.log.warn( "ONOS" + node + " flows: " +
1470 repr( ONOSFlows[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001471 elif flowsResults and consistentFlows:
1472 flowCheck = main.TRUE
1473 flowState = ONOSFlows[ 0 ]
1474
1475 main.step( "Get the OF Table entries" )
1476 global flows
1477 flows = []
1478 for i in range( 1, 29 ):
GlennRC68467eb2015-11-16 18:01:01 -08001479 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001480 if flowCheck == main.FALSE:
1481 for table in flows:
1482 main.log.warn( table )
1483 # TODO: Compare switch flow tables with ONOS flow tables
1484
1485 main.step( "Start continuous pings" )
1486 main.Mininet2.pingLong(
1487 src=main.params[ 'PING' ][ 'source1' ],
1488 target=main.params[ 'PING' ][ 'target1' ],
1489 pingTime=500 )
1490 main.Mininet2.pingLong(
1491 src=main.params[ 'PING' ][ 'source2' ],
1492 target=main.params[ 'PING' ][ 'target2' ],
1493 pingTime=500 )
1494 main.Mininet2.pingLong(
1495 src=main.params[ 'PING' ][ 'source3' ],
1496 target=main.params[ 'PING' ][ 'target3' ],
1497 pingTime=500 )
1498 main.Mininet2.pingLong(
1499 src=main.params[ 'PING' ][ 'source4' ],
1500 target=main.params[ 'PING' ][ 'target4' ],
1501 pingTime=500 )
1502 main.Mininet2.pingLong(
1503 src=main.params[ 'PING' ][ 'source5' ],
1504 target=main.params[ 'PING' ][ 'target5' ],
1505 pingTime=500 )
1506 main.Mininet2.pingLong(
1507 src=main.params[ 'PING' ][ 'source6' ],
1508 target=main.params[ 'PING' ][ 'target6' ],
1509 pingTime=500 )
1510 main.Mininet2.pingLong(
1511 src=main.params[ 'PING' ][ 'source7' ],
1512 target=main.params[ 'PING' ][ 'target7' ],
1513 pingTime=500 )
1514 main.Mininet2.pingLong(
1515 src=main.params[ 'PING' ][ 'source8' ],
1516 target=main.params[ 'PING' ][ 'target8' ],
1517 pingTime=500 )
1518 main.Mininet2.pingLong(
1519 src=main.params[ 'PING' ][ 'source9' ],
1520 target=main.params[ 'PING' ][ 'target9' ],
1521 pingTime=500 )
1522 main.Mininet2.pingLong(
1523 src=main.params[ 'PING' ][ 'source10' ],
1524 target=main.params[ 'PING' ][ 'target10' ],
1525 pingTime=500 )
1526
1527 main.step( "Collecting topology information from ONOS" )
1528 devices = []
1529 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001530 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001531 t = main.Thread( target=main.CLIs[i].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001532 name="devices-" + str( i ),
1533 args=[ ] )
1534 threads.append( t )
1535 t.start()
1536
1537 for t in threads:
1538 t.join()
1539 devices.append( t.result )
1540 hosts = []
1541 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001542 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001543 t = main.Thread( target=main.CLIs[i].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001544 name="hosts-" + str( i ),
1545 args=[ ] )
1546 threads.append( t )
1547 t.start()
1548
1549 for t in threads:
1550 t.join()
1551 try:
1552 hosts.append( json.loads( t.result ) )
1553 except ( ValueError, TypeError ):
1554 # FIXME: better handling of this, print which node
1555 # Maybe use thread name?
1556 main.log.exception( "Error parsing json output of hosts" )
Jon Hallf3d16e72015-12-16 17:45:08 -08001557 main.log.warn( repr( t.result ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001558 hosts.append( None )
1559
1560 ports = []
1561 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001562 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001563 t = main.Thread( target=main.CLIs[i].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001564 name="ports-" + str( i ),
1565 args=[ ] )
1566 threads.append( t )
1567 t.start()
1568
1569 for t in threads:
1570 t.join()
1571 ports.append( t.result )
1572 links = []
1573 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001574 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001575 t = main.Thread( target=main.CLIs[i].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001576 name="links-" + str( i ),
1577 args=[ ] )
1578 threads.append( t )
1579 t.start()
1580
1581 for t in threads:
1582 t.join()
1583 links.append( t.result )
1584 clusters = []
1585 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001586 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001587 t = main.Thread( target=main.CLIs[i].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001588 name="clusters-" + str( i ),
1589 args=[ ] )
1590 threads.append( t )
1591 t.start()
1592
1593 for t in threads:
1594 t.join()
1595 clusters.append( t.result )
1596 # Compare json objects for hosts and dataplane clusters
1597
1598 # hosts
1599 main.step( "Host view is consistent across ONOS nodes" )
1600 consistentHostsResult = main.TRUE
1601 for controller in range( len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001602 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001603 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001604 if hosts[ controller ] == hosts[ 0 ]:
1605 continue
1606 else: # hosts not consistent
1607 main.log.error( "hosts from ONOS" +
1608 controllerStr +
1609 " is inconsistent with ONOS1" )
1610 main.log.warn( repr( hosts[ controller ] ) )
1611 consistentHostsResult = main.FALSE
1612
1613 else:
1614 main.log.error( "Error in getting ONOS hosts from ONOS" +
1615 controllerStr )
1616 consistentHostsResult = main.FALSE
1617 main.log.warn( "ONOS" + controllerStr +
1618 " hosts response: " +
1619 repr( hosts[ controller ] ) )
1620 utilities.assert_equals(
1621 expect=main.TRUE,
1622 actual=consistentHostsResult,
1623 onpass="Hosts view is consistent across all ONOS nodes",
1624 onfail="ONOS nodes have different views of hosts" )
1625
1626 main.step( "Each host has an IP address" )
1627 ipResult = main.TRUE
1628 for controller in range( 0, len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001629 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001630 if hosts[ controller ]:
1631 for host in hosts[ controller ]:
1632 if not host.get( 'ipAddresses', [ ] ):
1633 main.log.error( "Error with host ips on controller" +
1634 controllerStr + ": " + str( host ) )
1635 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001636 utilities.assert_equals(
1637 expect=main.TRUE,
1638 actual=ipResult,
1639 onpass="The ips of the hosts aren't empty",
1640 onfail="The ip of at least one host is missing" )
1641
1642 # Strongly connected clusters of devices
1643 main.step( "Cluster view is consistent across ONOS nodes" )
1644 consistentClustersResult = main.TRUE
1645 for controller in range( len( clusters ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001646 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001647 if "Error" not in clusters[ controller ]:
1648 if clusters[ controller ] == clusters[ 0 ]:
1649 continue
1650 else: # clusters not consistent
1651 main.log.error( "clusters from ONOS" + controllerStr +
1652 " is inconsistent with ONOS1" )
1653 consistentClustersResult = main.FALSE
1654
1655 else:
1656 main.log.error( "Error in getting dataplane clusters " +
1657 "from ONOS" + controllerStr )
1658 consistentClustersResult = main.FALSE
1659 main.log.warn( "ONOS" + controllerStr +
1660 " clusters response: " +
1661 repr( clusters[ controller ] ) )
1662 utilities.assert_equals(
1663 expect=main.TRUE,
1664 actual=consistentClustersResult,
1665 onpass="Clusters view is consistent across all ONOS nodes",
1666 onfail="ONOS nodes have different views of clusters" )
1667 # there should always only be one cluster
1668 main.step( "Cluster view correct across ONOS nodes" )
1669 try:
1670 numClusters = len( json.loads( clusters[ 0 ] ) )
1671 except ( ValueError, TypeError ):
1672 main.log.exception( "Error parsing clusters[0]: " +
1673 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001674 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07001675 clusterResults = main.FALSE
1676 if numClusters == 1:
1677 clusterResults = main.TRUE
1678 utilities.assert_equals(
1679 expect=1,
1680 actual=numClusters,
1681 onpass="ONOS shows 1 SCC",
1682 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1683
1684 main.step( "Comparing ONOS topology to MN" )
1685 devicesResults = main.TRUE
1686 linksResults = main.TRUE
1687 hostsResults = main.TRUE
1688 mnSwitches = main.Mininet1.getSwitches()
1689 mnLinks = main.Mininet1.getLinks()
1690 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001691 for controller in main.activeNodes:
1692 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001693 if devices[ controller ] and ports[ controller ] and\
1694 "Error" not in devices[ controller ] and\
1695 "Error" not in ports[ controller ]:
Jon Hall6e709752016-02-01 13:38:46 -08001696 currentDevicesResult = main.Mininet1.compareSwitches(
1697 mnSwitches,
1698 json.loads( devices[ controller ] ),
1699 json.loads( ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001700 else:
1701 currentDevicesResult = main.FALSE
1702 utilities.assert_equals( expect=main.TRUE,
1703 actual=currentDevicesResult,
1704 onpass="ONOS" + controllerStr +
1705 " Switches view is correct",
1706 onfail="ONOS" + controllerStr +
1707 " Switches view is incorrect" )
1708 if links[ controller ] and "Error" not in links[ controller ]:
1709 currentLinksResult = main.Mininet1.compareLinks(
1710 mnSwitches, mnLinks,
1711 json.loads( links[ controller ] ) )
1712 else:
1713 currentLinksResult = main.FALSE
1714 utilities.assert_equals( expect=main.TRUE,
1715 actual=currentLinksResult,
1716 onpass="ONOS" + controllerStr +
1717 " links view is correct",
1718 onfail="ONOS" + controllerStr +
1719 " links view is incorrect" )
1720
Jon Hall657cdf62015-12-17 14:40:51 -08001721 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001722 currentHostsResult = main.Mininet1.compareHosts(
1723 mnHosts,
1724 hosts[ controller ] )
1725 else:
1726 currentHostsResult = main.FALSE
1727 utilities.assert_equals( expect=main.TRUE,
1728 actual=currentHostsResult,
1729 onpass="ONOS" + controllerStr +
1730 " hosts exist in Mininet",
1731 onfail="ONOS" + controllerStr +
1732 " hosts don't match Mininet" )
1733
1734 devicesResults = devicesResults and currentDevicesResult
1735 linksResults = linksResults and currentLinksResult
1736 hostsResults = hostsResults and currentHostsResult
1737
1738 main.step( "Device information is correct" )
1739 utilities.assert_equals(
1740 expect=main.TRUE,
1741 actual=devicesResults,
1742 onpass="Device information is correct",
1743 onfail="Device information is incorrect" )
1744
1745 main.step( "Links are correct" )
1746 utilities.assert_equals(
1747 expect=main.TRUE,
1748 actual=linksResults,
1749 onpass="Link are correct",
1750 onfail="Links are incorrect" )
1751
1752 main.step( "Hosts are correct" )
1753 utilities.assert_equals(
1754 expect=main.TRUE,
1755 actual=hostsResults,
1756 onpass="Hosts are correct",
1757 onfail="Hosts are incorrect" )
1758
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001759 def CASE61( self, main ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001760 """
1761 The Failure case.
1762 """
Jon Halle1a3b752015-07-22 13:02:46 -07001763 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001764 assert main, "main not defined"
1765 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001766 assert main.CLIs, "main.CLIs not defined"
1767 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001768 main.case( "Stop minority of ONOS nodes" )
Jon Hall96091e62015-09-21 17:34:17 -07001769
1770 main.step( "Checking ONOS Logs for errors" )
1771 for node in main.nodes:
1772 main.log.debug( "Checking logs for errors on " + node.name + ":" )
1773 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
1774
Jon Hall3b489db2015-10-05 14:38:37 -07001775 n = len( main.nodes ) # Number of nodes
1776 p = ( ( n + 1 ) / 2 ) + 1 # Number of partitions
1777 main.kill = [ 0 ] # ONOS node to kill, listed by index in main.nodes
1778 if n > 3:
1779 main.kill.append( p - 1 )
1780 # NOTE: This only works for cluster sizes of 3,5, or 7.
1781
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001782 main.step( "Stopping " + str( len( main.kill ) ) + " ONOS nodes" )
Jon Hall3b489db2015-10-05 14:38:37 -07001783 killResults = main.TRUE
1784 for i in main.kill:
1785 killResults = killResults and\
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001786 main.ONOSbench.onosStop( main.nodes[i].ip_address )
1787 main.activeNodes.remove( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001788 utilities.assert_equals( expect=main.TRUE, actual=killResults,
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001789 onpass="ONOS nodes stopped successfully",
1790 onfail="ONOS nodes NOT successfully stopped" )
1791
1792 def CASE62( self, main ):
1793 """
1794 The bring up stopped nodes
1795 """
1796 import time
1797 assert main.numCtrls, "main.numCtrls not defined"
1798 assert main, "main not defined"
1799 assert utilities.assert_equals, "utilities.assert_equals not defined"
1800 assert main.CLIs, "main.CLIs not defined"
1801 assert main.nodes, "main.nodes not defined"
1802 assert main.kill, "main.kill not defined"
1803 main.case( "Restart minority of ONOS nodes" )
1804
1805 main.step( "Restarting " + str( len( main.kill ) ) + " ONOS nodes" )
1806 startResults = main.TRUE
1807 restartTime = time.time()
1808 for i in main.kill:
1809 startResults = startResults and\
1810 main.ONOSbench.onosStart( main.nodes[i].ip_address )
1811 utilities.assert_equals( expect=main.TRUE, actual=startResults,
1812 onpass="ONOS nodes started successfully",
1813 onfail="ONOS nodes NOT successfully started" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001814
1815 main.step( "Checking if ONOS is up yet" )
1816 count = 0
1817 onosIsupResult = main.FALSE
1818 while onosIsupResult == main.FALSE and count < 10:
Jon Hall3b489db2015-10-05 14:38:37 -07001819 onosIsupResult = main.TRUE
1820 for i in main.kill:
1821 onosIsupResult = onosIsupResult and\
1822 main.ONOSbench.isup( main.nodes[i].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001823 count = count + 1
Jon Hall5cf14d52015-07-16 12:15:19 -07001824 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1825 onpass="ONOS restarted successfully",
1826 onfail="ONOS restart NOT successful" )
1827
Jon Halle1a3b752015-07-22 13:02:46 -07001828 main.step( "Restarting ONOS main.CLIs" )
Jon Hall3b489db2015-10-05 14:38:37 -07001829 cliResults = main.TRUE
1830 for i in main.kill:
1831 cliResults = cliResults and\
1832 main.CLIs[i].startOnosCli( main.nodes[i].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001833 main.activeNodes.append( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001834 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1835 onpass="ONOS cli restarted",
1836 onfail="ONOS cli did not restart" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001837 main.activeNodes.sort()
1838 try:
1839 assert list( set( main.activeNodes ) ) == main.activeNodes,\
1840 "List of active nodes has duplicates, this likely indicates something was run out of order"
1841 except AssertionError:
1842 main.log.exception( "" )
1843 main.cleanup()
1844 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -07001845
1846 # Grab the time of restart so we chan check how long the gossip
1847 # protocol has had time to work
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001848 main.restartTime = time.time() - restartTime
Jon Hall5cf14d52015-07-16 12:15:19 -07001849 main.log.debug( "Restart time: " + str( main.restartTime ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001850 # TODO: MAke this configurable. Also, we are breaking the above timer
1851 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001852 node = main.activeNodes[0]
1853 main.log.debug( main.CLIs[node].nodes( jsonFormat=False ) )
1854 main.log.debug( main.CLIs[node].leaders( jsonFormat=False ) )
1855 main.log.debug( main.CLIs[node].partitions( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001856
Jon Halla440e872016-03-31 15:15:50 -07001857 main.step( "Rerun for election on the node(s) that were killed" )
1858 runResults = main.TRUE
1859 for i in main.kill:
1860 runResults = runResults and\
1861 main.CLIs[i].electionTestRun()
1862 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1863 onpass="ONOS nodes reran for election topic",
1864 onfail="Errror rerunning for election" )
1865
Jon Hall5cf14d52015-07-16 12:15:19 -07001866 def CASE7( self, main ):
1867 """
1868 Check state after ONOS failure
1869 """
1870 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001871 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001872 assert main, "main not defined"
1873 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001874 assert main.CLIs, "main.CLIs not defined"
1875 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001876 try:
1877 main.kill
1878 except AttributeError:
1879 main.kill = []
1880
Jon Hall5cf14d52015-07-16 12:15:19 -07001881 main.case( "Running ONOS Constant State Tests" )
1882
1883 main.step( "Check that each switch has a master" )
1884 # Assert that each device has a master
1885 rolesNotNull = main.TRUE
1886 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001887 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001888 t = main.Thread( target=main.CLIs[i].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001889 name="rolesNotNull-" + str( i ),
1890 args=[ ] )
1891 threads.append( t )
1892 t.start()
1893
1894 for t in threads:
1895 t.join()
1896 rolesNotNull = rolesNotNull and t.result
1897 utilities.assert_equals(
1898 expect=main.TRUE,
1899 actual=rolesNotNull,
1900 onpass="Each device has a master",
1901 onfail="Some devices don't have a master assigned" )
1902
1903 main.step( "Read device roles from ONOS" )
1904 ONOSMastership = []
Jon Halla440e872016-03-31 15:15:50 -07001905 mastershipCheck = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001906 consistentMastership = True
1907 rolesResults = True
1908 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001909 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001910 t = main.Thread( target=main.CLIs[i].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001911 name="roles-" + str( i ),
1912 args=[] )
1913 threads.append( t )
1914 t.start()
1915
1916 for t in threads:
1917 t.join()
1918 ONOSMastership.append( t.result )
1919
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001920 for i in range( len( ONOSMastership ) ):
1921 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001922 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001923 main.log.error( "Error in getting ONOS" + node + " roles" )
1924 main.log.warn( "ONOS" + node + " mastership response: " +
1925 repr( ONOSMastership[i] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001926 rolesResults = False
1927 utilities.assert_equals(
1928 expect=True,
1929 actual=rolesResults,
1930 onpass="No error in reading roles output",
1931 onfail="Error in reading roles from ONOS" )
1932
1933 main.step( "Check for consistency in roles from each controller" )
1934 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
1935 main.log.info(
1936 "Switch roles are consistent across all ONOS nodes" )
1937 else:
1938 consistentMastership = False
1939 utilities.assert_equals(
1940 expect=True,
1941 actual=consistentMastership,
1942 onpass="Switch roles are consistent across all ONOS nodes",
1943 onfail="ONOS nodes have different views of switch roles" )
1944
1945 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001946 for i in range( len( ONOSMastership ) ):
1947 node = str( main.activeNodes[i] + 1 )
1948 main.log.warn( "ONOS" + node + " roles: ",
1949 json.dumps( json.loads( ONOSMastership[ i ] ),
1950 sort_keys=True,
1951 indent=4,
1952 separators=( ',', ': ' ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001953
1954 # NOTE: we expect mastership to change on controller failure
Jon Hall5cf14d52015-07-16 12:15:19 -07001955
1956 main.step( "Get the intents and compare across all nodes" )
1957 ONOSIntents = []
1958 intentCheck = main.FALSE
1959 consistentIntents = True
1960 intentsResults = True
1961 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001962 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07001963 t = main.Thread( target=main.CLIs[i].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001964 name="intents-" + str( i ),
1965 args=[],
1966 kwargs={ 'jsonFormat': True } )
1967 threads.append( t )
1968 t.start()
1969
1970 for t in threads:
1971 t.join()
1972 ONOSIntents.append( t.result )
1973
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001974 for i in range( len( ONOSIntents) ):
1975 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001976 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001977 main.log.error( "Error in getting ONOS" + node + " intents" )
1978 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001979 repr( ONOSIntents[ i ] ) )
1980 intentsResults = False
1981 utilities.assert_equals(
1982 expect=True,
1983 actual=intentsResults,
1984 onpass="No error in reading intents output",
1985 onfail="Error in reading intents from ONOS" )
1986
1987 main.step( "Check for consistency in Intents from each controller" )
1988 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
1989 main.log.info( "Intents are consistent across all ONOS " +
1990 "nodes" )
1991 else:
1992 consistentIntents = False
1993
1994 # Try to make it easy to figure out what is happening
1995 #
1996 # Intent ONOS1 ONOS2 ...
1997 # 0x01 INSTALLED INSTALLING
1998 # ... ... ...
1999 # ... ... ...
2000 title = " ID"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002001 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002002 title += " " * 10 + "ONOS" + str( n + 1 )
2003 main.log.warn( title )
2004 # get all intent keys in the cluster
2005 keys = []
2006 for nodeStr in ONOSIntents:
2007 node = json.loads( nodeStr )
2008 for intent in node:
2009 keys.append( intent.get( 'id' ) )
2010 keys = set( keys )
2011 for key in keys:
2012 row = "%-13s" % key
2013 for nodeStr in ONOSIntents:
2014 node = json.loads( nodeStr )
2015 for intent in node:
2016 if intent.get( 'id' ) == key:
2017 row += "%-15s" % intent.get( 'state' )
2018 main.log.warn( row )
2019 # End table view
2020
2021 utilities.assert_equals(
2022 expect=True,
2023 actual=consistentIntents,
2024 onpass="Intents are consistent across all ONOS nodes",
2025 onfail="ONOS nodes have different views of intents" )
2026 intentStates = []
2027 for node in ONOSIntents: # Iter through ONOS nodes
2028 nodeStates = []
2029 # Iter through intents of a node
2030 try:
2031 for intent in json.loads( node ):
2032 nodeStates.append( intent[ 'state' ] )
2033 except ( ValueError, TypeError ):
2034 main.log.exception( "Error in parsing intents" )
2035 main.log.error( repr( node ) )
2036 intentStates.append( nodeStates )
2037 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
2038 main.log.info( dict( out ) )
2039
2040 if intentsResults and not consistentIntents:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002041 for i in range( len( main.activeNodes ) ):
2042 node = str( main.activeNodes[i] + 1 )
2043 main.log.warn( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07002044 main.log.warn( json.dumps(
2045 json.loads( ONOSIntents[ i ] ),
2046 sort_keys=True,
2047 indent=4,
2048 separators=( ',', ': ' ) ) )
2049 elif intentsResults and consistentIntents:
2050 intentCheck = main.TRUE
2051
2052 # NOTE: Store has no durability, so intents are lost across system
2053 # restarts
2054 main.step( "Compare current intents with intents before the failure" )
2055 # NOTE: this requires case 5 to pass for intentState to be set.
2056 # maybe we should stop the test if that fails?
2057 sameIntents = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002058 try:
2059 intentState
2060 except NameError:
2061 main.log.warn( "No previous intent state was saved" )
2062 else:
2063 if intentState and intentState == ONOSIntents[ 0 ]:
2064 sameIntents = main.TRUE
2065 main.log.info( "Intents are consistent with before failure" )
2066 # TODO: possibly the states have changed? we may need to figure out
2067 # what the acceptable states are
2068 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
2069 sameIntents = main.TRUE
2070 try:
2071 before = json.loads( intentState )
2072 after = json.loads( ONOSIntents[ 0 ] )
2073 for intent in before:
2074 if intent not in after:
2075 sameIntents = main.FALSE
2076 main.log.debug( "Intent is not currently in ONOS " +
2077 "(at least in the same form):" )
2078 main.log.debug( json.dumps( intent ) )
2079 except ( ValueError, TypeError ):
2080 main.log.exception( "Exception printing intents" )
2081 main.log.debug( repr( ONOSIntents[0] ) )
2082 main.log.debug( repr( intentState ) )
2083 if sameIntents == main.FALSE:
2084 try:
2085 main.log.debug( "ONOS intents before: " )
2086 main.log.debug( json.dumps( json.loads( intentState ),
2087 sort_keys=True, indent=4,
2088 separators=( ',', ': ' ) ) )
2089 main.log.debug( "Current ONOS intents: " )
2090 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2091 sort_keys=True, indent=4,
2092 separators=( ',', ': ' ) ) )
2093 except ( ValueError, TypeError ):
2094 main.log.exception( "Exception printing intents" )
2095 main.log.debug( repr( ONOSIntents[0] ) )
2096 main.log.debug( repr( intentState ) )
2097 utilities.assert_equals(
2098 expect=main.TRUE,
2099 actual=sameIntents,
2100 onpass="Intents are consistent with before failure",
2101 onfail="The Intents changed during failure" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002102 intentCheck = intentCheck and sameIntents
2103
2104 main.step( "Get the OF Table entries and compare to before " +
2105 "component failure" )
2106 FlowTables = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002107 for i in range( 28 ):
2108 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08002109 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
2110 FlowTables = FlowTables and main.Mininet1.flowTableComp( flows[i], tmpFlows )
Jon Hall5cf14d52015-07-16 12:15:19 -07002111 if FlowTables == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08002112 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002113 utilities.assert_equals(
2114 expect=main.TRUE,
2115 actual=FlowTables,
2116 onpass="No changes were found in the flow tables",
2117 onfail="Changes were found in the flow tables" )
2118
2119 main.Mininet2.pingLongKill()
2120 '''
2121 main.step( "Check the continuous pings to ensure that no packets " +
2122 "were dropped during component failure" )
2123 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2124 main.params[ 'TESTONIP' ] )
2125 LossInPings = main.FALSE
2126 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2127 for i in range( 8, 18 ):
2128 main.log.info(
2129 "Checking for a loss in pings along flow from s" +
2130 str( i ) )
2131 LossInPings = main.Mininet2.checkForLoss(
2132 "/tmp/ping.h" +
2133 str( i ) ) or LossInPings
2134 if LossInPings == main.TRUE:
2135 main.log.info( "Loss in ping detected" )
2136 elif LossInPings == main.ERROR:
2137 main.log.info( "There are multiple mininet process running" )
2138 elif LossInPings == main.FALSE:
2139 main.log.info( "No Loss in the pings" )
2140 main.log.info( "No loss of dataplane connectivity" )
2141 utilities.assert_equals(
2142 expect=main.FALSE,
2143 actual=LossInPings,
2144 onpass="No Loss of connectivity",
2145 onfail="Loss of dataplane connectivity detected" )
2146 '''
2147
2148 main.step( "Leadership Election is still functional" )
2149 # Test of LeadershipElection
2150 leaderList = []
Jon Hall5cf14d52015-07-16 12:15:19 -07002151
Jon Hall3b489db2015-10-05 14:38:37 -07002152 restarted = []
2153 for i in main.kill:
2154 restarted.append( main.nodes[i].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07002155 leaderResult = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -07002156
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002157 for i in main.activeNodes:
2158 cli = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07002159 leaderN = cli.electionTestLeader()
2160 leaderList.append( leaderN )
2161 if leaderN == main.FALSE:
2162 # error in response
2163 main.log.error( "Something is wrong with " +
2164 "electionTestLeader function, check the" +
2165 " error logs" )
2166 leaderResult = main.FALSE
2167 elif leaderN is None:
2168 main.log.error( cli.name +
2169 " shows no leader for the election-app was" +
2170 " elected after the old one died" )
2171 leaderResult = main.FALSE
2172 elif leaderN in restarted:
2173 main.log.error( cli.name + " shows " + str( leaderN ) +
2174 " as leader for the election-app, but it " +
2175 "was restarted" )
2176 leaderResult = main.FALSE
2177 if len( set( leaderList ) ) != 1:
2178 leaderResult = main.FALSE
2179 main.log.error(
2180 "Inconsistent view of leader for the election test app" )
2181 # TODO: print the list
2182 utilities.assert_equals(
2183 expect=main.TRUE,
2184 actual=leaderResult,
2185 onpass="Leadership election passed",
2186 onfail="Something went wrong with Leadership election" )
2187
2188 def CASE8( self, main ):
2189 """
2190 Compare topo
2191 """
2192 import json
2193 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002194 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002195 assert main, "main not defined"
2196 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002197 assert main.CLIs, "main.CLIs not defined"
2198 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002199
2200 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002201 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002202 " and ONOS"
Jon Hall5cf14d52015-07-16 12:15:19 -07002203 topoResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002204 topoFailMsg = "ONOS topology don't match Mininet"
Jon Hall5cf14d52015-07-16 12:15:19 -07002205 elapsed = 0
2206 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08002207 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002208 startTime = time.time()
2209 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08002210 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hall96091e62015-09-21 17:34:17 -07002211 devicesResults = main.TRUE
2212 linksResults = main.TRUE
2213 hostsResults = main.TRUE
2214 hostAttachmentResults = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002215 count += 1
2216 cliStart = time.time()
2217 devices = []
2218 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002219 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002220 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002221 name="devices-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002222 args=[ main.CLIs[i].devices, [ None ] ],
2223 kwargs= { 'sleep': 5, 'attempts': 5,
2224 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002225 threads.append( t )
2226 t.start()
2227
2228 for t in threads:
2229 t.join()
2230 devices.append( t.result )
2231 hosts = []
2232 ipResult = main.TRUE
2233 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002234 for i in main.activeNodes:
Jon Halld8f6de82015-12-17 17:04:34 -08002235 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002236 name="hosts-" + str( i ),
Jon Halld8f6de82015-12-17 17:04:34 -08002237 args=[ main.CLIs[i].hosts, [ None ] ],
2238 kwargs= { 'sleep': 5, 'attempts': 5,
2239 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002240 threads.append( t )
2241 t.start()
2242
2243 for t in threads:
2244 t.join()
2245 try:
2246 hosts.append( json.loads( t.result ) )
2247 except ( ValueError, TypeError ):
2248 main.log.exception( "Error parsing hosts results" )
2249 main.log.error( repr( t.result ) )
Jon Hallf3d16e72015-12-16 17:45:08 -08002250 hosts.append( None )
Jon Hall5cf14d52015-07-16 12:15:19 -07002251 for controller in range( 0, len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002252 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hallacd1b182015-12-17 11:43:20 -08002253 if hosts[ controller ]:
2254 for host in hosts[ controller ]:
2255 if host is None or host.get( 'ipAddresses', [] ) == []:
2256 main.log.error(
2257 "Error with host ipAddresses on controller" +
2258 controllerStr + ": " + str( host ) )
2259 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002260 ports = []
2261 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002262 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002263 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002264 name="ports-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002265 args=[ main.CLIs[i].ports, [ None ] ],
2266 kwargs= { 'sleep': 5, 'attempts': 5,
2267 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002268 threads.append( t )
2269 t.start()
2270
2271 for t in threads:
2272 t.join()
2273 ports.append( t.result )
2274 links = []
2275 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002276 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002277 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002278 name="links-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002279 args=[ main.CLIs[i].links, [ None ] ],
2280 kwargs= { 'sleep': 5, 'attempts': 5,
2281 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002282 threads.append( t )
2283 t.start()
2284
2285 for t in threads:
2286 t.join()
2287 links.append( t.result )
2288 clusters = []
2289 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002290 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002291 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002292 name="clusters-" + str( i ),
Jon Hall6e709752016-02-01 13:38:46 -08002293 args=[ main.CLIs[i].clusters, [ None ] ],
2294 kwargs= { 'sleep': 5, 'attempts': 5,
2295 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002296 threads.append( t )
2297 t.start()
2298
2299 for t in threads:
2300 t.join()
2301 clusters.append( t.result )
2302
2303 elapsed = time.time() - startTime
2304 cliTime = time.time() - cliStart
2305 print "Elapsed time: " + str( elapsed )
2306 print "CLI time: " + str( cliTime )
2307
Jon Hall6e709752016-02-01 13:38:46 -08002308 if all( e is None for e in devices ) and\
2309 all( e is None for e in hosts ) and\
2310 all( e is None for e in ports ) and\
2311 all( e is None for e in links ) and\
2312 all( e is None for e in clusters ):
2313 topoFailMsg = "Could not get topology from ONOS"
2314 main.log.error( topoFailMsg )
2315 continue # Try again, No use trying to compare
2316
Jon Hall5cf14d52015-07-16 12:15:19 -07002317 mnSwitches = main.Mininet1.getSwitches()
2318 mnLinks = main.Mininet1.getLinks()
2319 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002320 for controller in range( len( main.activeNodes ) ):
2321 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002322 if devices[ controller ] and ports[ controller ] and\
2323 "Error" not in devices[ controller ] and\
2324 "Error" not in ports[ controller ]:
2325
Jon Hallc6793552016-01-19 14:18:37 -08002326 try:
2327 currentDevicesResult = main.Mininet1.compareSwitches(
2328 mnSwitches,
2329 json.loads( devices[ controller ] ),
2330 json.loads( ports[ controller ] ) )
2331 except ( TypeError, ValueError ) as e:
2332 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
2333 devices[ controller ], ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002334 else:
2335 currentDevicesResult = main.FALSE
2336 utilities.assert_equals( expect=main.TRUE,
2337 actual=currentDevicesResult,
2338 onpass="ONOS" + controllerStr +
2339 " Switches view is correct",
2340 onfail="ONOS" + controllerStr +
2341 " Switches view is incorrect" )
2342
2343 if links[ controller ] and "Error" not in links[ controller ]:
2344 currentLinksResult = main.Mininet1.compareLinks(
2345 mnSwitches, mnLinks,
2346 json.loads( links[ controller ] ) )
2347 else:
2348 currentLinksResult = main.FALSE
2349 utilities.assert_equals( expect=main.TRUE,
2350 actual=currentLinksResult,
2351 onpass="ONOS" + controllerStr +
2352 " links view is correct",
2353 onfail="ONOS" + controllerStr +
2354 " links view is incorrect" )
Jon Hall657cdf62015-12-17 14:40:51 -08002355 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002356 currentHostsResult = main.Mininet1.compareHosts(
2357 mnHosts,
2358 hosts[ controller ] )
Jon Hall13b446e2016-01-05 12:17:01 -08002359 elif hosts[ controller ] == []:
2360 currentHostsResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002361 else:
2362 currentHostsResult = main.FALSE
2363 utilities.assert_equals( expect=main.TRUE,
2364 actual=currentHostsResult,
2365 onpass="ONOS" + controllerStr +
2366 " hosts exist in Mininet",
2367 onfail="ONOS" + controllerStr +
2368 " hosts don't match Mininet" )
2369 # CHECKING HOST ATTACHMENT POINTS
2370 hostAttachment = True
2371 zeroHosts = False
2372 # FIXME: topo-HA/obelisk specific mappings:
2373 # key is mac and value is dpid
2374 mappings = {}
2375 for i in range( 1, 29 ): # hosts 1 through 28
2376 # set up correct variables:
2377 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2378 if i == 1:
2379 deviceId = "1000".zfill(16)
2380 elif i == 2:
2381 deviceId = "2000".zfill(16)
2382 elif i == 3:
2383 deviceId = "3000".zfill(16)
2384 elif i == 4:
2385 deviceId = "3004".zfill(16)
2386 elif i == 5:
2387 deviceId = "5000".zfill(16)
2388 elif i == 6:
2389 deviceId = "6000".zfill(16)
2390 elif i == 7:
2391 deviceId = "6007".zfill(16)
2392 elif i >= 8 and i <= 17:
2393 dpid = '3' + str( i ).zfill( 3 )
2394 deviceId = dpid.zfill(16)
2395 elif i >= 18 and i <= 27:
2396 dpid = '6' + str( i ).zfill( 3 )
2397 deviceId = dpid.zfill(16)
2398 elif i == 28:
2399 deviceId = "2800".zfill(16)
2400 mappings[ macId ] = deviceId
Jon Halld8f6de82015-12-17 17:04:34 -08002401 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002402 if hosts[ controller ] == []:
2403 main.log.warn( "There are no hosts discovered" )
2404 zeroHosts = True
2405 else:
2406 for host in hosts[ controller ]:
2407 mac = None
2408 location = None
2409 device = None
2410 port = None
2411 try:
2412 mac = host.get( 'mac' )
2413 assert mac, "mac field could not be found for this host object"
2414
2415 location = host.get( 'location' )
2416 assert location, "location field could not be found for this host object"
2417
2418 # Trim the protocol identifier off deviceId
2419 device = str( location.get( 'elementId' ) ).split(':')[1]
2420 assert device, "elementId field could not be found for this host location object"
2421
2422 port = location.get( 'port' )
2423 assert port, "port field could not be found for this host location object"
2424
2425 # Now check if this matches where they should be
2426 if mac and device and port:
2427 if str( port ) != "1":
2428 main.log.error( "The attachment port is incorrect for " +
2429 "host " + str( mac ) +
2430 ". Expected: 1 Actual: " + str( port) )
2431 hostAttachment = False
2432 if device != mappings[ str( mac ) ]:
2433 main.log.error( "The attachment device is incorrect for " +
2434 "host " + str( mac ) +
2435 ". Expected: " + mappings[ str( mac ) ] +
2436 " Actual: " + device )
2437 hostAttachment = False
2438 else:
2439 hostAttachment = False
2440 except AssertionError:
2441 main.log.exception( "Json object not as expected" )
2442 main.log.error( repr( host ) )
2443 hostAttachment = False
2444 else:
2445 main.log.error( "No hosts json output or \"Error\"" +
2446 " in output. hosts = " +
2447 repr( hosts[ controller ] ) )
2448 if zeroHosts is False:
2449 hostAttachment = True
2450
2451 # END CHECKING HOST ATTACHMENT POINTS
2452 devicesResults = devicesResults and currentDevicesResult
2453 linksResults = linksResults and currentLinksResult
2454 hostsResults = hostsResults and currentHostsResult
2455 hostAttachmentResults = hostAttachmentResults and\
2456 hostAttachment
Jon Halla440e872016-03-31 15:15:50 -07002457 topoResult = ( devicesResults and linksResults
2458 and hostsResults and ipResult and
2459 hostAttachmentResults )
Jon Halle9b1fa32015-12-08 15:32:21 -08002460 utilities.assert_equals( expect=True,
2461 actual=topoResult,
2462 onpass="ONOS topology matches Mininet",
Jon Hall6e709752016-02-01 13:38:46 -08002463 onfail=topoFailMsg )
Jon Halle9b1fa32015-12-08 15:32:21 -08002464 # End of While loop to pull ONOS state
Jon Hall5cf14d52015-07-16 12:15:19 -07002465
2466 # Compare json objects for hosts and dataplane clusters
2467
2468 # hosts
2469 main.step( "Hosts view is consistent across all ONOS nodes" )
2470 consistentHostsResult = main.TRUE
2471 for controller in range( len( hosts ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002472 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall13b446e2016-01-05 12:17:01 -08002473 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002474 if hosts[ controller ] == hosts[ 0 ]:
2475 continue
2476 else: # hosts not consistent
2477 main.log.error( "hosts from ONOS" + controllerStr +
2478 " is inconsistent with ONOS1" )
2479 main.log.warn( repr( hosts[ controller ] ) )
2480 consistentHostsResult = main.FALSE
2481
2482 else:
2483 main.log.error( "Error in getting ONOS hosts from ONOS" +
2484 controllerStr )
2485 consistentHostsResult = main.FALSE
2486 main.log.warn( "ONOS" + controllerStr +
2487 " hosts response: " +
2488 repr( hosts[ controller ] ) )
2489 utilities.assert_equals(
2490 expect=main.TRUE,
2491 actual=consistentHostsResult,
2492 onpass="Hosts view is consistent across all ONOS nodes",
2493 onfail="ONOS nodes have different views of hosts" )
2494
2495 main.step( "Hosts information is correct" )
2496 hostsResults = hostsResults and ipResult
2497 utilities.assert_equals(
2498 expect=main.TRUE,
2499 actual=hostsResults,
2500 onpass="Host information is correct",
2501 onfail="Host information is incorrect" )
2502
2503 main.step( "Host attachment points to the network" )
2504 utilities.assert_equals(
2505 expect=True,
2506 actual=hostAttachmentResults,
2507 onpass="Hosts are correctly attached to the network",
2508 onfail="ONOS did not correctly attach hosts to the network" )
2509
2510 # Strongly connected clusters of devices
2511 main.step( "Clusters view is consistent across all ONOS nodes" )
2512 consistentClustersResult = main.TRUE
2513 for controller in range( len( clusters ) ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002514 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002515 if "Error" not in clusters[ controller ]:
2516 if clusters[ controller ] == clusters[ 0 ]:
2517 continue
2518 else: # clusters not consistent
2519 main.log.error( "clusters from ONOS" +
2520 controllerStr +
2521 " is inconsistent with ONOS1" )
2522 consistentClustersResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002523 else:
2524 main.log.error( "Error in getting dataplane clusters " +
2525 "from ONOS" + controllerStr )
2526 consistentClustersResult = main.FALSE
2527 main.log.warn( "ONOS" + controllerStr +
2528 " clusters response: " +
2529 repr( clusters[ controller ] ) )
2530 utilities.assert_equals(
2531 expect=main.TRUE,
2532 actual=consistentClustersResult,
2533 onpass="Clusters view is consistent across all ONOS nodes",
2534 onfail="ONOS nodes have different views of clusters" )
2535
2536 main.step( "There is only one SCC" )
2537 # there should always only be one cluster
2538 try:
2539 numClusters = len( json.loads( clusters[ 0 ] ) )
2540 except ( ValueError, TypeError ):
2541 main.log.exception( "Error parsing clusters[0]: " +
2542 repr( clusters[0] ) )
Jon Halla440e872016-03-31 15:15:50 -07002543 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07002544 clusterResults = main.FALSE
2545 if numClusters == 1:
2546 clusterResults = main.TRUE
2547 utilities.assert_equals(
2548 expect=1,
2549 actual=numClusters,
2550 onpass="ONOS shows 1 SCC",
2551 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2552
2553 topoResult = ( devicesResults and linksResults
2554 and hostsResults and consistentHostsResult
2555 and consistentClustersResult and clusterResults
2556 and ipResult and hostAttachmentResults )
2557
2558 topoResult = topoResult and int( count <= 2 )
2559 note = "note it takes about " + str( int( cliTime ) ) + \
2560 " seconds for the test to make all the cli calls to fetch " +\
2561 "the topology from each ONOS instance"
2562 main.log.info(
2563 "Very crass estimate for topology discovery/convergence( " +
2564 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2565 str( count ) + " tries" )
2566
2567 main.step( "Device information is correct" )
2568 utilities.assert_equals(
2569 expect=main.TRUE,
2570 actual=devicesResults,
2571 onpass="Device information is correct",
2572 onfail="Device information is incorrect" )
2573
2574 main.step( "Links are correct" )
2575 utilities.assert_equals(
2576 expect=main.TRUE,
2577 actual=linksResults,
2578 onpass="Link are correct",
2579 onfail="Links are incorrect" )
2580
Jon Halla440e872016-03-31 15:15:50 -07002581 main.step( "Hosts are correct" )
2582 utilities.assert_equals(
2583 expect=main.TRUE,
2584 actual=hostsResults,
2585 onpass="Hosts are correct",
2586 onfail="Hosts are incorrect" )
2587
Jon Hall5cf14d52015-07-16 12:15:19 -07002588 # FIXME: move this to an ONOS state case
2589 main.step( "Checking ONOS nodes" )
2590 nodesOutput = []
2591 nodeResults = main.TRUE
2592 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002593 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07002594 t = main.Thread( target=main.CLIs[i].nodes,
Jon Hall5cf14d52015-07-16 12:15:19 -07002595 name="nodes-" + str( i ),
2596 args=[ ] )
2597 threads.append( t )
2598 t.start()
2599
2600 for t in threads:
2601 t.join()
2602 nodesOutput.append( t.result )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002603 ips = [ main.nodes[node].ip_address for node in main.activeNodes ]
Jon Halle9b1fa32015-12-08 15:32:21 -08002604 ips.sort()
Jon Hall5cf14d52015-07-16 12:15:19 -07002605 for i in nodesOutput:
2606 try:
2607 current = json.loads( i )
Jon Halle9b1fa32015-12-08 15:32:21 -08002608 activeIps = []
2609 currentResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002610 for node in current:
Jon Hallbd182782016-03-28 16:42:22 -07002611 if node['state'] == 'READY':
Jon Halle9b1fa32015-12-08 15:32:21 -08002612 activeIps.append( node['ip'] )
2613 activeIps.sort()
2614 if ips == activeIps:
2615 currentResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002616 except ( ValueError, TypeError ):
2617 main.log.error( "Error parsing nodes output" )
2618 main.log.warn( repr( i ) )
Jon Halle9b1fa32015-12-08 15:32:21 -08002619 currentResult = main.FALSE
2620 nodeResults = nodeResults and currentResult
Jon Hall5cf14d52015-07-16 12:15:19 -07002621 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
2622 onpass="Nodes check successful",
2623 onfail="Nodes check NOT successful" )
Jon Halla440e872016-03-31 15:15:50 -07002624 if not nodeResults:
2625 for cli in main.CLIs:
2626 main.log.debug( "{} components not ACTIVE: \n{}".format(
2627 cli.name,
2628 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002629
2630 def CASE9( self, main ):
2631 """
2632 Link s3-s28 down
2633 """
2634 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002635 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002636 assert main, "main not defined"
2637 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002638 assert main.CLIs, "main.CLIs not defined"
2639 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002640 # NOTE: You should probably run a topology check after this
2641
2642 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2643
2644 description = "Turn off a link to ensure that Link Discovery " +\
2645 "is working properly"
2646 main.case( description )
2647
2648 main.step( "Kill Link between s3 and s28" )
2649 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2650 main.log.info( "Waiting " + str( linkSleep ) +
2651 " seconds for link down to be discovered" )
2652 time.sleep( linkSleep )
2653 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2654 onpass="Link down successful",
2655 onfail="Failed to bring link down" )
2656 # TODO do some sort of check here
2657
2658 def CASE10( self, main ):
2659 """
2660 Link s3-s28 up
2661 """
2662 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002663 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002664 assert main, "main not defined"
2665 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002666 assert main.CLIs, "main.CLIs not defined"
2667 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002668 # NOTE: You should probably run a topology check after this
2669
2670 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2671
2672 description = "Restore a link to ensure that Link Discovery is " + \
2673 "working properly"
2674 main.case( description )
2675
2676 main.step( "Bring link between s3 and s28 back up" )
2677 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2678 main.log.info( "Waiting " + str( linkSleep ) +
2679 " seconds for link up to be discovered" )
2680 time.sleep( linkSleep )
2681 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2682 onpass="Link up successful",
2683 onfail="Failed to bring link up" )
2684 # TODO do some sort of check here
2685
2686 def CASE11( self, main ):
2687 """
2688 Switch Down
2689 """
2690 # NOTE: You should probably run a topology check after this
2691 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002692 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002693 assert main, "main not defined"
2694 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002695 assert main.CLIs, "main.CLIs not defined"
2696 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002697
2698 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2699
2700 description = "Killing a switch to ensure it is discovered correctly"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002701 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002702 main.case( description )
2703 switch = main.params[ 'kill' ][ 'switch' ]
2704 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2705
2706 # TODO: Make this switch parameterizable
2707 main.step( "Kill " + switch )
2708 main.log.info( "Deleting " + switch )
2709 main.Mininet1.delSwitch( switch )
2710 main.log.info( "Waiting " + str( switchSleep ) +
2711 " seconds for switch down to be discovered" )
2712 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002713 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002714 # Peek at the deleted switch
2715 main.log.warn( str( device ) )
2716 result = main.FALSE
2717 if device and device[ 'available' ] is False:
2718 result = main.TRUE
2719 utilities.assert_equals( expect=main.TRUE, actual=result,
2720 onpass="Kill switch successful",
2721 onfail="Failed to kill switch?" )
2722
2723 def CASE12( self, main ):
2724 """
2725 Switch Up
2726 """
2727 # NOTE: You should probably run a topology check after this
2728 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002729 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002730 assert main, "main not defined"
2731 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002732 assert main.CLIs, "main.CLIs not defined"
2733 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002734 assert ONOS1Port, "ONOS1Port not defined"
2735 assert ONOS2Port, "ONOS2Port not defined"
2736 assert ONOS3Port, "ONOS3Port not defined"
2737 assert ONOS4Port, "ONOS4Port not defined"
2738 assert ONOS5Port, "ONOS5Port not defined"
2739 assert ONOS6Port, "ONOS6Port not defined"
2740 assert ONOS7Port, "ONOS7Port not defined"
2741
2742 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2743 switch = main.params[ 'kill' ][ 'switch' ]
2744 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2745 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002746 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002747 description = "Adding a switch to ensure it is discovered correctly"
2748 main.case( description )
2749
2750 main.step( "Add back " + switch )
2751 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2752 for peer in links:
2753 main.Mininet1.addLink( switch, peer )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002754 ipList = [ node.ip_address for node in main.nodes ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002755 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2756 main.log.info( "Waiting " + str( switchSleep ) +
2757 " seconds for switch up to be discovered" )
2758 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002759 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002760 # Peek at the deleted switch
2761 main.log.warn( str( device ) )
2762 result = main.FALSE
2763 if device and device[ 'available' ]:
2764 result = main.TRUE
2765 utilities.assert_equals( expect=main.TRUE, actual=result,
2766 onpass="add switch successful",
2767 onfail="Failed to add switch?" )
2768
2769 def CASE13( self, main ):
2770 """
2771 Clean up
2772 """
2773 import os
2774 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002775 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002776 assert main, "main not defined"
2777 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002778 assert main.CLIs, "main.CLIs not defined"
2779 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002780
2781 # printing colors to terminal
2782 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2783 'blue': '\033[94m', 'green': '\033[92m',
2784 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2785 main.case( "Test Cleanup" )
2786 main.step( "Killing tcpdumps" )
2787 main.Mininet2.stopTcpdump()
2788
2789 testname = main.TEST
Jon Hall96091e62015-09-21 17:34:17 -07002790 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall5cf14d52015-07-16 12:15:19 -07002791 main.step( "Copying MN pcap and ONOS log files to test station" )
2792 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2793 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002794 # NOTE: MN Pcap file is being saved to logdir.
2795 # We scp this file as MN and TestON aren't necessarily the same vm
2796
2797 # FIXME: To be replaced with a Jenkin's post script
Jon Hall5cf14d52015-07-16 12:15:19 -07002798 # TODO: Load these from params
2799 # NOTE: must end in /
2800 logFolder = "/opt/onos/log/"
2801 logFiles = [ "karaf.log", "karaf.log.1" ]
2802 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002803 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002804 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002805 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002806 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2807 logFolder + f, dstName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002808 # std*.log's
2809 # NOTE: must end in /
2810 logFolder = "/opt/onos/var/"
2811 logFiles = [ "stderr.log", "stdout.log" ]
2812 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002813 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002814 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002815 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002816 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2817 logFolder + f, dstName )
2818 else:
2819 main.log.debug( "skipping saving log files" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002820
2821 main.step( "Stopping Mininet" )
2822 mnResult = main.Mininet1.stopNet()
2823 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2824 onpass="Mininet stopped",
2825 onfail="MN cleanup NOT successful" )
2826
2827 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002828 for node in main.nodes:
Jon Hall96091e62015-09-21 17:34:17 -07002829 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2830 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002831
2832 try:
2833 timerLog = open( main.logdir + "/Timers.csv", 'w')
2834 # Overwrite with empty line and close
2835 labels = "Gossip Intents, Restart"
2836 data = str( gossipTime ) + ", " + str( main.restartTime )
2837 timerLog.write( labels + "\n" + data )
2838 timerLog.close()
2839 except NameError, e:
2840 main.log.exception(e)
2841
2842 def CASE14( self, main ):
2843 """
2844 start election app on all onos nodes
2845 """
Jon Halle1a3b752015-07-22 13:02:46 -07002846 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002847 assert main, "main not defined"
2848 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002849 assert main.CLIs, "main.CLIs not defined"
2850 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002851
2852 main.case("Start Leadership Election app")
2853 main.step( "Install leadership election app" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002854 onosCli = main.CLIs[ main.activeNodes[0] ]
2855 appResult = onosCli.activateApp( "org.onosproject.election" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002856 utilities.assert_equals(
2857 expect=main.TRUE,
2858 actual=appResult,
2859 onpass="Election app installed",
2860 onfail="Something went wrong with installing Leadership election" )
2861
2862 main.step( "Run for election on each node" )
2863 leaderResult = main.TRUE
2864 leaders = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002865 for i in main.activeNodes:
2866 main.CLIs[i].electionTestRun()
2867 for i in main.activeNodes:
2868 cli = main.CLIs[i]
Jon Hall5cf14d52015-07-16 12:15:19 -07002869 leader = cli.electionTestLeader()
2870 if leader is None or leader == main.FALSE:
2871 main.log.error( cli.name + ": Leader for the election app " +
2872 "should be an ONOS node, instead got '" +
2873 str( leader ) + "'" )
2874 leaderResult = main.FALSE
2875 leaders.append( leader )
2876 utilities.assert_equals(
2877 expect=main.TRUE,
2878 actual=leaderResult,
2879 onpass="Successfully ran for leadership",
2880 onfail="Failed to run for leadership" )
2881
2882 main.step( "Check that each node shows the same leader" )
2883 sameLeader = main.TRUE
2884 if len( set( leaders ) ) != 1:
2885 sameLeader = main.FALSE
Jon Halle1a3b752015-07-22 13:02:46 -07002886 main.log.error( "Results of electionTestLeader is order of main.CLIs:" +
Jon Hall5cf14d52015-07-16 12:15:19 -07002887 str( leaders ) )
2888 utilities.assert_equals(
2889 expect=main.TRUE,
2890 actual=sameLeader,
2891 onpass="Leadership is consistent for the election topic",
2892 onfail="Nodes have different leaders" )
2893
2894 def CASE15( self, main ):
2895 """
2896 Check that Leadership Election is still functional
acsmars71adceb2015-08-31 15:09:26 -07002897 15.1 Run election on each node
2898 15.2 Check that each node has the same leaders and candidates
2899 15.3 Find current leader and withdraw
2900 15.4 Check that a new node was elected leader
2901 15.5 Check that that new leader was the candidate of old leader
2902 15.6 Run for election on old leader
2903 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2904 15.8 Make sure that the old leader was added to the candidate list
2905
2906 old and new variable prefixes refer to data from before vs after
2907 withdrawl and later before withdrawl vs after re-election
Jon Hall5cf14d52015-07-16 12:15:19 -07002908 """
2909 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002910 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002911 assert main, "main not defined"
2912 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002913 assert main.CLIs, "main.CLIs not defined"
2914 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002915
Jon Hall5cf14d52015-07-16 12:15:19 -07002916 description = "Check that Leadership Election is still functional"
2917 main.case( description )
Jon Halla440e872016-03-31 15:15:50 -07002918 # NOTE: Need to re-run after restarts since being a canidate is not persistant
Jon Hall5cf14d52015-07-16 12:15:19 -07002919
Jon Halla440e872016-03-31 15:15:50 -07002920 oldLeaders = [] # list of lists of each nodes' candidates before
2921 newLeaders = [] # list of lists of each nodes' candidates after
acsmars71adceb2015-08-31 15:09:26 -07002922 oldLeader = '' # the old leader from oldLeaders, None if not same
2923 newLeader = '' # the new leaders fron newLoeaders, None if not same
2924 oldLeaderCLI = None # the CLI of the old leader used for re-electing
2925 expectNoLeader = False # True when there is only one leader
2926 if main.numCtrls == 1:
2927 expectNoLeader = True
2928
2929 main.step( "Run for election on each node" )
2930 electionResult = main.TRUE
2931
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002932 for i in main.activeNodes: # run test election on each node
2933 if main.CLIs[i].electionTestRun() == main.FALSE:
acsmars71adceb2015-08-31 15:09:26 -07002934 electionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002935 utilities.assert_equals(
2936 expect=main.TRUE,
acsmars71adceb2015-08-31 15:09:26 -07002937 actual=electionResult,
2938 onpass="All nodes successfully ran for leadership",
2939 onfail="At least one node failed to run for leadership" )
2940
acsmars3a72bde2015-09-02 14:16:22 -07002941 if electionResult == main.FALSE:
2942 main.log.error(
2943 "Skipping Test Case because Election Test App isn't loaded" )
2944 main.skipCase()
2945
acsmars71adceb2015-08-31 15:09:26 -07002946 main.step( "Check that each node shows the same leader and candidates" )
Jon Halla440e872016-03-31 15:15:50 -07002947 failMessage = "Nodes have different leaderboards"
2948 def consistentLeaderboards( nodes ):
2949 TOPIC = 'org.onosproject.election'
2950 # FIXME: use threads
2951 #FIXME: should we retry outside the function?
2952 for n in range( 5 ): # Retry in case election is still happening
2953 leaderList = []
2954 # Get all leaderboards
2955 for cli in nodes:
2956 leaderList.append( cli.specificLeaderCandidate( TOPIC ) )
2957 # Compare leaderboards
2958 result = all( i == leaderList[0] for i in leaderList ) and\
2959 leaderList is not None
2960 main.log.debug( leaderList )
2961 main.log.warn( result )
2962 if result:
2963 return ( result, leaderList )
2964 time.sleep(5) #TODO: paramerterize
2965 main.log.error( "Inconsistent leaderboards:" + str( leaderList ) )
2966 activeCLIs = [ main.CLIs[i] for i in main.activeNodes ]
2967 sameResult, oldLeaders = consistentLeaderboards( activeCLIs )
2968 if sameResult:
2969 oldLeader = oldLeaders[ 0 ][ 0 ]
2970 main.log.warn( oldLeader )
acsmars71adceb2015-08-31 15:09:26 -07002971 else:
Jon Halla440e872016-03-31 15:15:50 -07002972 oldLeader = None
acsmars71adceb2015-08-31 15:09:26 -07002973 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002974 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002975 actual=sameResult,
Jon Halla440e872016-03-31 15:15:50 -07002976 onpass="Leaderboards are consistent for the election topic",
acsmars71adceb2015-08-31 15:09:26 -07002977 onfail=failMessage )
Jon Hall5cf14d52015-07-16 12:15:19 -07002978
2979 main.step( "Find current leader and withdraw" )
acsmars71adceb2015-08-31 15:09:26 -07002980 withdrawResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002981 # do some sanity checking on leader before using it
acsmars71adceb2015-08-31 15:09:26 -07002982 if oldLeader is None:
2983 main.log.error( "Leadership isn't consistent." )
2984 withdrawResult = main.FALSE
2985 # Get the CLI of the oldLeader
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002986 for i in main.activeNodes:
acsmars71adceb2015-08-31 15:09:26 -07002987 if oldLeader == main.nodes[ i ].ip_address:
2988 oldLeaderCLI = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002989 break
2990 else: # FOR/ELSE statement
2991 main.log.error( "Leader election, could not find current leader" )
2992 if oldLeader:
acsmars71adceb2015-08-31 15:09:26 -07002993 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall5cf14d52015-07-16 12:15:19 -07002994 utilities.assert_equals(
2995 expect=main.TRUE,
2996 actual=withdrawResult,
2997 onpass="Node was withdrawn from election",
2998 onfail="Node was not withdrawn from election" )
2999
acsmars71adceb2015-08-31 15:09:26 -07003000 main.step( "Check that a new node was elected leader" )
acsmars71adceb2015-08-31 15:09:26 -07003001 failMessage = "Nodes have different leaders"
acsmars71adceb2015-08-31 15:09:26 -07003002 # Get new leaders and candidates
Jon Halla440e872016-03-31 15:15:50 -07003003 newLeaderResult, newLeaders = consistentLeaderboards( activeCLIs )
3004 if newLeaders[ 0 ][ 0 ] == 'none':
3005 main.log.error( "No leader was elected on at least 1 node" )
3006 if not expectNoLeader:
3007 newLeaderResult = False
3008 if newLeaderResult:
3009 newLeader = newLeaders[ 0 ][ 0 ]
Jon Hall5cf14d52015-07-16 12:15:19 -07003010 else:
Jon Halla440e872016-03-31 15:15:50 -07003011 newLeader = None
acsmars71adceb2015-08-31 15:09:26 -07003012
3013 # Check that the new leader is not the older leader, which was withdrawn
3014 if newLeader == oldLeader:
Jon Halla440e872016-03-31 15:15:50 -07003015 newLeaderResult = False
Jon Hall6e709752016-02-01 13:38:46 -08003016 main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
acsmars71adceb2015-08-31 15:09:26 -07003017 " as the current leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003018 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003019 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003020 actual=newLeaderResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003021 onpass="Leadership election passed",
3022 onfail="Something went wrong with Leadership election" )
3023
Jon Halla440e872016-03-31 15:15:50 -07003024 main.step( "Check that that new leader was the candidate of old leader" )
Jon Hall6e709752016-02-01 13:38:46 -08003025 # candidates[ 2 ] should become the top candidate after withdrawl
acsmars71adceb2015-08-31 15:09:26 -07003026 correctCandidateResult = main.TRUE
3027 if expectNoLeader:
3028 if newLeader == 'none':
3029 main.log.info( "No leader expected. None found. Pass" )
3030 correctCandidateResult = main.TRUE
3031 else:
3032 main.log.info( "Expected no leader, got: " + str( newLeader ) )
3033 correctCandidateResult = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07003034 elif len( oldLeaders[0] ) >= 3:
3035 if newLeader == oldLeaders[ 0 ][ 2 ]:
3036 # correct leader was elected
3037 correctCandidateResult = main.TRUE
3038 else:
3039 correctCandidateResult = main.FALSE
3040 main.log.error( "Candidate {} was elected. {} should have had priority.".format(
3041 newLeader, oldLeaders[ 0 ][ 2 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08003042 else:
3043 main.log.warn( "Could not determine who should be the correct leader" )
Jon Halla440e872016-03-31 15:15:50 -07003044 main.log.debug( oldLeaders[ 0 ] )
Jon Hall6e709752016-02-01 13:38:46 -08003045 correctCandidateResult = main.FALSE
acsmars71adceb2015-08-31 15:09:26 -07003046 utilities.assert_equals(
3047 expect=main.TRUE,
3048 actual=correctCandidateResult,
3049 onpass="Correct Candidate Elected",
3050 onfail="Incorrect Candidate Elected" )
3051
Jon Hall5cf14d52015-07-16 12:15:19 -07003052 main.step( "Run for election on old leader( just so everyone " +
3053 "is in the hat )" )
acsmars71adceb2015-08-31 15:09:26 -07003054 if oldLeaderCLI is not None:
3055 runResult = oldLeaderCLI.electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07003056 else:
acsmars71adceb2015-08-31 15:09:26 -07003057 main.log.error( "No old leader to re-elect" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003058 runResult = main.FALSE
3059 utilities.assert_equals(
3060 expect=main.TRUE,
3061 actual=runResult,
3062 onpass="App re-ran for election",
3063 onfail="App failed to run for election" )
Jon Halla440e872016-03-31 15:15:50 -07003064
acsmars71adceb2015-08-31 15:09:26 -07003065 main.step(
3066 "Check that oldLeader is a candidate, and leader if only 1 node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003067 # verify leader didn't just change
Jon Halla440e872016-03-31 15:15:50 -07003068 # Get new leaders and candidates
3069 reRunLeaders = []
3070 time.sleep( 5 ) # Paremterize
3071 positionResult, reRunLeaders = consistentLeaderboards( activeCLIs )
acsmars71adceb2015-08-31 15:09:26 -07003072
3073 # Check that the re-elected node is last on the candidate List
Jon Halla440e872016-03-31 15:15:50 -07003074 if oldLeader != reRunLeaders[ 0 ][ -1 ]:
3075 main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader),
3076 str( reRunLeaders[ 0 ] ) ) )
acsmars71adceb2015-08-31 15:09:26 -07003077 positionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07003078
3079 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003080 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003081 actual=positionResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003082 onpass="Old leader successfully re-ran for election",
3083 onfail="Something went wrong with Leadership election after " +
3084 "the old leader re-ran for election" )
3085
3086 def CASE16( self, main ):
3087 """
3088 Install Distributed Primitives app
3089 """
3090 import time
Jon Halle1a3b752015-07-22 13:02:46 -07003091 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003092 assert main, "main not defined"
3093 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003094 assert main.CLIs, "main.CLIs not defined"
3095 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003096
3097 # Variables for the distributed primitives tests
3098 global pCounterName
Jon Hall5cf14d52015-07-16 12:15:19 -07003099 global pCounterValue
Jon Hall5cf14d52015-07-16 12:15:19 -07003100 global onosSet
3101 global onosSetName
3102 pCounterName = "TestON-Partitions"
Jon Hall5cf14d52015-07-16 12:15:19 -07003103 pCounterValue = 0
Jon Hall5cf14d52015-07-16 12:15:19 -07003104 onosSet = set([])
3105 onosSetName = "TestON-set"
3106
3107 description = "Install Primitives app"
3108 main.case( description )
3109 main.step( "Install Primitives app" )
3110 appName = "org.onosproject.distributedprimitives"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003111 node = main.activeNodes[0]
3112 appResults = main.CLIs[node].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07003113 utilities.assert_equals( expect=main.TRUE,
3114 actual=appResults,
3115 onpass="Primitives app activated",
3116 onfail="Primitives app not activated" )
3117 time.sleep( 5 ) # To allow all nodes to activate
3118
3119 def CASE17( self, main ):
3120 """
3121 Check for basic functionality with distributed primitives
3122 """
Jon Hall5cf14d52015-07-16 12:15:19 -07003123 # Make sure variables are defined/set
Jon Halle1a3b752015-07-22 13:02:46 -07003124 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003125 assert main, "main not defined"
3126 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003127 assert main.CLIs, "main.CLIs not defined"
3128 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003129 assert pCounterName, "pCounterName not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003130 assert onosSetName, "onosSetName not defined"
3131 # NOTE: assert fails if value is 0/None/Empty/False
3132 try:
3133 pCounterValue
3134 except NameError:
3135 main.log.error( "pCounterValue not defined, setting to 0" )
3136 pCounterValue = 0
3137 try:
Jon Hall5cf14d52015-07-16 12:15:19 -07003138 onosSet
3139 except NameError:
3140 main.log.error( "onosSet not defined, setting to empty Set" )
3141 onosSet = set([])
3142 # Variables for the distributed primitives tests. These are local only
3143 addValue = "a"
3144 addAllValue = "a b c d e f"
3145 retainValue = "c d e f"
3146
3147 description = "Check for basic functionality with distributed " +\
3148 "primitives"
3149 main.case( description )
Jon Halle1a3b752015-07-22 13:02:46 -07003150 main.caseExplanation = "Test the methods of the distributed " +\
3151 "primitives (counters and sets) throught the cli"
Jon Hall5cf14d52015-07-16 12:15:19 -07003152 # DISTRIBUTED ATOMIC COUNTERS
Jon Halle1a3b752015-07-22 13:02:46 -07003153 # Partitioned counters
3154 main.step( "Increment then get a default counter on each node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003155 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].counterTestAddAndGet,
3160 name="counterAddAndGet-" + str( i ),
Jon Hall5cf14d52015-07-16 12:15:19 -07003161 args=[ pCounterName ] )
3162 pCounterValue += 1
3163 addedPValues.append( pCounterValue )
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
Jon Halle1a3b752015-07-22 13:02:46 -07003184 main.step( "Get then Increment a default counter on each node" )
3185 pCounters = []
3186 threads = []
3187 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003188 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003189 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3190 name="counterGetAndAdd-" + str( i ),
3191 args=[ pCounterName ] )
3192 addedPValues.append( pCounterValue )
3193 pCounterValue += 1
3194 threads.append( t )
3195 t.start()
3196
3197 for t in threads:
3198 t.join()
3199 pCounters.append( t.result )
3200 # Check that counter incremented numController times
3201 pCounterResults = True
3202 for i in addedPValues:
3203 tmpResult = i in pCounters
3204 pCounterResults = pCounterResults and tmpResult
3205 if not tmpResult:
3206 main.log.error( str( i ) + " is not in partitioned "
3207 "counter incremented results" )
3208 utilities.assert_equals( expect=True,
3209 actual=pCounterResults,
3210 onpass="Default counter incremented",
3211 onfail="Error incrementing default" +
3212 " counter" )
3213
3214 main.step( "Counters we added have the correct values" )
3215 incrementCheck = main.Counters.counterCheck( pCounterName, pCounterValue )
3216 utilities.assert_equals( expect=main.TRUE,
3217 actual=incrementCheck,
3218 onpass="Added counters are correct",
3219 onfail="Added counters are incorrect" )
3220
3221 main.step( "Add -8 to then get a default counter on each node" )
3222 pCounters = []
3223 threads = []
3224 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003225 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003226 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3227 name="counterIncrement-" + str( i ),
3228 args=[ pCounterName ],
3229 kwargs={ "delta": -8 } )
3230 pCounterValue += -8
3231 addedPValues.append( pCounterValue )
3232 threads.append( t )
3233 t.start()
3234
3235 for t in threads:
3236 t.join()
3237 pCounters.append( t.result )
3238 # Check that counter incremented numController times
3239 pCounterResults = True
3240 for i in addedPValues:
3241 tmpResult = i in pCounters
3242 pCounterResults = pCounterResults and tmpResult
3243 if not tmpResult:
3244 main.log.error( str( i ) + " is not in partitioned "
3245 "counter incremented results" )
3246 utilities.assert_equals( expect=True,
3247 actual=pCounterResults,
3248 onpass="Default counter incremented",
3249 onfail="Error incrementing default" +
3250 " counter" )
3251
3252 main.step( "Add 5 to then get a default counter on each node" )
3253 pCounters = []
3254 threads = []
3255 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003256 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003257 t = main.Thread( target=main.CLIs[i].counterTestAddAndGet,
3258 name="counterIncrement-" + str( i ),
3259 args=[ pCounterName ],
3260 kwargs={ "delta": 5 } )
3261 pCounterValue += 5
3262 addedPValues.append( pCounterValue )
3263 threads.append( t )
3264 t.start()
3265
3266 for t in threads:
3267 t.join()
3268 pCounters.append( t.result )
3269 # Check that counter incremented numController times
3270 pCounterResults = True
3271 for i in addedPValues:
3272 tmpResult = i in pCounters
3273 pCounterResults = pCounterResults and tmpResult
3274 if not tmpResult:
3275 main.log.error( str( i ) + " is not in partitioned "
3276 "counter incremented results" )
3277 utilities.assert_equals( expect=True,
3278 actual=pCounterResults,
3279 onpass="Default counter incremented",
3280 onfail="Error incrementing default" +
3281 " counter" )
3282
3283 main.step( "Get then add 5 to a default counter on each node" )
3284 pCounters = []
3285 threads = []
3286 addedPValues = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003287 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003288 t = main.Thread( target=main.CLIs[i].counterTestGetAndAdd,
3289 name="counterIncrement-" + str( i ),
3290 args=[ pCounterName ],
3291 kwargs={ "delta": 5 } )
3292 addedPValues.append( pCounterValue )
3293 pCounterValue += 5
3294 threads.append( t )
3295 t.start()
3296
3297 for t in threads:
3298 t.join()
3299 pCounters.append( t.result )
3300 # Check that counter incremented numController times
3301 pCounterResults = True
3302 for i in addedPValues:
3303 tmpResult = i in pCounters
3304 pCounterResults = pCounterResults and tmpResult
3305 if not tmpResult:
3306 main.log.error( str( i ) + " is not in partitioned "
3307 "counter incremented results" )
3308 utilities.assert_equals( expect=True,
3309 actual=pCounterResults,
3310 onpass="Default counter incremented",
3311 onfail="Error incrementing default" +
3312 " counter" )
3313
3314 main.step( "Counters we added have the correct values" )
3315 incrementCheck = main.Counters.counterCheck( pCounterName, pCounterValue )
3316 utilities.assert_equals( expect=main.TRUE,
3317 actual=incrementCheck,
3318 onpass="Added counters are correct",
3319 onfail="Added counters are incorrect" )
3320
Jon Hall5cf14d52015-07-16 12:15:19 -07003321 # DISTRIBUTED SETS
3322 main.step( "Distributed Set get" )
3323 size = len( onosSet )
3324 getResponses = []
3325 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003326 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003327 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003328 name="setTestGet-" + str( i ),
3329 args=[ onosSetName ] )
3330 threads.append( t )
3331 t.start()
3332 for t in threads:
3333 t.join()
3334 getResponses.append( t.result )
3335
3336 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003337 for i in range( len( main.activeNodes ) ):
3338 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003339 if isinstance( getResponses[ i ], list):
3340 current = set( getResponses[ i ] )
3341 if len( current ) == len( getResponses[ i ] ):
3342 # no repeats
3343 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003344 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003345 " has incorrect view" +
3346 " of set " + onosSetName + ":\n" +
3347 str( getResponses[ i ] ) )
3348 main.log.debug( "Expected: " + str( onosSet ) )
3349 main.log.debug( "Actual: " + str( current ) )
3350 getResults = main.FALSE
3351 else:
3352 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003353 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003354 " has repeat elements in" +
3355 " set " + onosSetName + ":\n" +
3356 str( getResponses[ i ] ) )
3357 getResults = main.FALSE
3358 elif getResponses[ i ] == main.ERROR:
3359 getResults = main.FALSE
3360 utilities.assert_equals( expect=main.TRUE,
3361 actual=getResults,
3362 onpass="Set elements are correct",
3363 onfail="Set elements are incorrect" )
3364
3365 main.step( "Distributed Set size" )
3366 sizeResponses = []
3367 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003368 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003369 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003370 name="setTestSize-" + str( i ),
3371 args=[ onosSetName ] )
3372 threads.append( t )
3373 t.start()
3374 for t in threads:
3375 t.join()
3376 sizeResponses.append( t.result )
3377
3378 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003379 for i in range( len( main.activeNodes ) ):
3380 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003381 if size != sizeResponses[ i ]:
3382 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003383 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003384 " expected a size of " + str( size ) +
3385 " for set " + onosSetName +
3386 " but got " + str( sizeResponses[ i ] ) )
3387 utilities.assert_equals( expect=main.TRUE,
3388 actual=sizeResults,
3389 onpass="Set sizes are correct",
3390 onfail="Set sizes are incorrect" )
3391
3392 main.step( "Distributed Set add()" )
3393 onosSet.add( addValue )
3394 addResponses = []
3395 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003396 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003397 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003398 name="setTestAdd-" + str( i ),
3399 args=[ onosSetName, addValue ] )
3400 threads.append( t )
3401 t.start()
3402 for t in threads:
3403 t.join()
3404 addResponses.append( t.result )
3405
3406 # main.TRUE = successfully changed the set
3407 # main.FALSE = action resulted in no change in set
3408 # main.ERROR - Some error in executing the function
3409 addResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003410 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003411 if addResponses[ i ] == main.TRUE:
3412 # All is well
3413 pass
3414 elif addResponses[ i ] == main.FALSE:
3415 # Already in set, probably fine
3416 pass
3417 elif addResponses[ i ] == main.ERROR:
3418 # Error in execution
3419 addResults = main.FALSE
3420 else:
3421 # unexpected result
3422 addResults = main.FALSE
3423 if addResults != main.TRUE:
3424 main.log.error( "Error executing set add" )
3425
3426 # Check if set is still correct
3427 size = len( onosSet )
3428 getResponses = []
3429 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003430 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003431 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003432 name="setTestGet-" + str( i ),
3433 args=[ onosSetName ] )
3434 threads.append( t )
3435 t.start()
3436 for t in threads:
3437 t.join()
3438 getResponses.append( t.result )
3439 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003440 for i in range( len( main.activeNodes ) ):
3441 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003442 if isinstance( getResponses[ i ], list):
3443 current = set( getResponses[ i ] )
3444 if len( current ) == len( getResponses[ i ] ):
3445 # no repeats
3446 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003447 main.log.error( "ONOS" + node + " has incorrect view" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003448 " of set " + onosSetName + ":\n" +
3449 str( getResponses[ i ] ) )
3450 main.log.debug( "Expected: " + str( onosSet ) )
3451 main.log.debug( "Actual: " + str( current ) )
3452 getResults = main.FALSE
3453 else:
3454 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003455 main.log.error( "ONOS" + node + " has repeat elements in" +
Jon Hall5cf14d52015-07-16 12:15:19 -07003456 " set " + onosSetName + ":\n" +
3457 str( getResponses[ i ] ) )
3458 getResults = main.FALSE
3459 elif getResponses[ i ] == main.ERROR:
3460 getResults = main.FALSE
3461 sizeResponses = []
3462 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003463 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003464 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003465 name="setTestSize-" + str( i ),
3466 args=[ onosSetName ] )
3467 threads.append( t )
3468 t.start()
3469 for t in threads:
3470 t.join()
3471 sizeResponses.append( t.result )
3472 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003473 for i in range( len( main.activeNodes ) ):
3474 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003475 if size != sizeResponses[ i ]:
3476 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003477 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003478 " expected a size of " + str( size ) +
3479 " for set " + onosSetName +
3480 " but got " + str( sizeResponses[ i ] ) )
3481 addResults = addResults and getResults and sizeResults
3482 utilities.assert_equals( expect=main.TRUE,
3483 actual=addResults,
3484 onpass="Set add correct",
3485 onfail="Set add was incorrect" )
3486
3487 main.step( "Distributed Set addAll()" )
3488 onosSet.update( addAllValue.split() )
3489 addResponses = []
3490 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003491 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003492 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003493 name="setTestAddAll-" + str( i ),
3494 args=[ onosSetName, addAllValue ] )
3495 threads.append( t )
3496 t.start()
3497 for t in threads:
3498 t.join()
3499 addResponses.append( t.result )
3500
3501 # main.TRUE = successfully changed the set
3502 # main.FALSE = action resulted in no change in set
3503 # main.ERROR - Some error in executing the function
3504 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003505 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003506 if addResponses[ i ] == main.TRUE:
3507 # All is well
3508 pass
3509 elif addResponses[ i ] == main.FALSE:
3510 # Already in set, probably fine
3511 pass
3512 elif addResponses[ i ] == main.ERROR:
3513 # Error in execution
3514 addAllResults = main.FALSE
3515 else:
3516 # unexpected result
3517 addAllResults = main.FALSE
3518 if addAllResults != main.TRUE:
3519 main.log.error( "Error executing set addAll" )
3520
3521 # Check if set is still correct
3522 size = len( onosSet )
3523 getResponses = []
3524 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003525 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003526 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003527 name="setTestGet-" + str( i ),
3528 args=[ onosSetName ] )
3529 threads.append( t )
3530 t.start()
3531 for t in threads:
3532 t.join()
3533 getResponses.append( t.result )
3534 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003535 for i in range( len( main.activeNodes ) ):
3536 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003537 if isinstance( getResponses[ i ], list):
3538 current = set( getResponses[ i ] )
3539 if len( current ) == len( getResponses[ i ] ):
3540 # no repeats
3541 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003542 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003543 " has incorrect view" +
3544 " of set " + onosSetName + ":\n" +
3545 str( getResponses[ i ] ) )
3546 main.log.debug( "Expected: " + str( onosSet ) )
3547 main.log.debug( "Actual: " + str( current ) )
3548 getResults = main.FALSE
3549 else:
3550 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003551 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003552 " has repeat elements in" +
3553 " set " + onosSetName + ":\n" +
3554 str( getResponses[ i ] ) )
3555 getResults = main.FALSE
3556 elif getResponses[ i ] == main.ERROR:
3557 getResults = main.FALSE
3558 sizeResponses = []
3559 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003560 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003561 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003562 name="setTestSize-" + str( i ),
3563 args=[ onosSetName ] )
3564 threads.append( t )
3565 t.start()
3566 for t in threads:
3567 t.join()
3568 sizeResponses.append( t.result )
3569 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003570 for i in range( len( main.activeNodes ) ):
3571 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003572 if size != sizeResponses[ i ]:
3573 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003574 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003575 " expected a size of " + str( size ) +
3576 " for set " + onosSetName +
3577 " but got " + str( sizeResponses[ i ] ) )
3578 addAllResults = addAllResults and getResults and sizeResults
3579 utilities.assert_equals( expect=main.TRUE,
3580 actual=addAllResults,
3581 onpass="Set addAll correct",
3582 onfail="Set addAll was incorrect" )
3583
3584 main.step( "Distributed Set contains()" )
3585 containsResponses = []
3586 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003587 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003588 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003589 name="setContains-" + str( i ),
3590 args=[ onosSetName ],
3591 kwargs={ "values": addValue } )
3592 threads.append( t )
3593 t.start()
3594 for t in threads:
3595 t.join()
3596 # NOTE: This is the tuple
3597 containsResponses.append( t.result )
3598
3599 containsResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003600 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003601 if containsResponses[ i ] == main.ERROR:
3602 containsResults = main.FALSE
3603 else:
3604 containsResults = containsResults and\
3605 containsResponses[ i ][ 1 ]
3606 utilities.assert_equals( expect=main.TRUE,
3607 actual=containsResults,
3608 onpass="Set contains is functional",
3609 onfail="Set contains failed" )
3610
3611 main.step( "Distributed Set containsAll()" )
3612 containsAllResponses = []
3613 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003614 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003615 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003616 name="setContainsAll-" + str( i ),
3617 args=[ onosSetName ],
3618 kwargs={ "values": addAllValue } )
3619 threads.append( t )
3620 t.start()
3621 for t in threads:
3622 t.join()
3623 # NOTE: This is the tuple
3624 containsAllResponses.append( t.result )
3625
3626 containsAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003627 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003628 if containsResponses[ i ] == main.ERROR:
3629 containsResults = main.FALSE
3630 else:
3631 containsResults = containsResults and\
3632 containsResponses[ i ][ 1 ]
3633 utilities.assert_equals( expect=main.TRUE,
3634 actual=containsAllResults,
3635 onpass="Set containsAll is functional",
3636 onfail="Set containsAll failed" )
3637
3638 main.step( "Distributed Set remove()" )
3639 onosSet.remove( addValue )
3640 removeResponses = []
3641 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003642 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003643 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003644 name="setTestRemove-" + str( i ),
3645 args=[ onosSetName, addValue ] )
3646 threads.append( t )
3647 t.start()
3648 for t in threads:
3649 t.join()
3650 removeResponses.append( t.result )
3651
3652 # main.TRUE = successfully changed the set
3653 # main.FALSE = action resulted in no change in set
3654 # main.ERROR - Some error in executing the function
3655 removeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003656 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003657 if removeResponses[ i ] == main.TRUE:
3658 # All is well
3659 pass
3660 elif removeResponses[ i ] == main.FALSE:
3661 # not in set, probably fine
3662 pass
3663 elif removeResponses[ i ] == main.ERROR:
3664 # Error in execution
3665 removeResults = main.FALSE
3666 else:
3667 # unexpected result
3668 removeResults = main.FALSE
3669 if removeResults != main.TRUE:
3670 main.log.error( "Error executing set remove" )
3671
3672 # Check if set is still correct
3673 size = len( onosSet )
3674 getResponses = []
3675 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003676 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003677 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003678 name="setTestGet-" + str( i ),
3679 args=[ onosSetName ] )
3680 threads.append( t )
3681 t.start()
3682 for t in threads:
3683 t.join()
3684 getResponses.append( t.result )
3685 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003686 for i in range( len( main.activeNodes ) ):
3687 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003688 if isinstance( getResponses[ i ], list):
3689 current = set( getResponses[ i ] )
3690 if len( current ) == len( getResponses[ i ] ):
3691 # no repeats
3692 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003693 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003694 " has incorrect view" +
3695 " of set " + onosSetName + ":\n" +
3696 str( getResponses[ i ] ) )
3697 main.log.debug( "Expected: " + str( onosSet ) )
3698 main.log.debug( "Actual: " + str( current ) )
3699 getResults = main.FALSE
3700 else:
3701 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003702 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003703 " has repeat elements in" +
3704 " set " + onosSetName + ":\n" +
3705 str( getResponses[ i ] ) )
3706 getResults = main.FALSE
3707 elif getResponses[ i ] == main.ERROR:
3708 getResults = main.FALSE
3709 sizeResponses = []
3710 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003711 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003712 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003713 name="setTestSize-" + str( i ),
3714 args=[ onosSetName ] )
3715 threads.append( t )
3716 t.start()
3717 for t in threads:
3718 t.join()
3719 sizeResponses.append( t.result )
3720 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003721 for i in range( len( main.activeNodes ) ):
3722 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003723 if size != sizeResponses[ i ]:
3724 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003725 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003726 " expected a size of " + str( size ) +
3727 " for set " + onosSetName +
3728 " but got " + str( sizeResponses[ i ] ) )
3729 removeResults = removeResults and getResults and sizeResults
3730 utilities.assert_equals( expect=main.TRUE,
3731 actual=removeResults,
3732 onpass="Set remove correct",
3733 onfail="Set remove was incorrect" )
3734
3735 main.step( "Distributed Set removeAll()" )
3736 onosSet.difference_update( addAllValue.split() )
3737 removeAllResponses = []
3738 threads = []
3739 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003740 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003741 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003742 name="setTestRemoveAll-" + str( i ),
3743 args=[ onosSetName, addAllValue ] )
3744 threads.append( t )
3745 t.start()
3746 for t in threads:
3747 t.join()
3748 removeAllResponses.append( t.result )
3749 except Exception, e:
3750 main.log.exception(e)
3751
3752 # main.TRUE = successfully changed the set
3753 # main.FALSE = action resulted in no change in set
3754 # main.ERROR - Some error in executing the function
3755 removeAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003756 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003757 if removeAllResponses[ i ] == main.TRUE:
3758 # All is well
3759 pass
3760 elif removeAllResponses[ i ] == main.FALSE:
3761 # not in set, probably fine
3762 pass
3763 elif removeAllResponses[ i ] == main.ERROR:
3764 # Error in execution
3765 removeAllResults = main.FALSE
3766 else:
3767 # unexpected result
3768 removeAllResults = main.FALSE
3769 if removeAllResults != main.TRUE:
3770 main.log.error( "Error executing set removeAll" )
3771
3772 # Check if set is still correct
3773 size = len( onosSet )
3774 getResponses = []
3775 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003776 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003777 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003778 name="setTestGet-" + str( i ),
3779 args=[ onosSetName ] )
3780 threads.append( t )
3781 t.start()
3782 for t in threads:
3783 t.join()
3784 getResponses.append( t.result )
3785 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003786 for i in range( len( main.activeNodes ) ):
3787 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003788 if isinstance( getResponses[ i ], list):
3789 current = set( getResponses[ i ] )
3790 if len( current ) == len( getResponses[ i ] ):
3791 # no repeats
3792 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003793 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003794 " has incorrect view" +
3795 " of set " + onosSetName + ":\n" +
3796 str( getResponses[ i ] ) )
3797 main.log.debug( "Expected: " + str( onosSet ) )
3798 main.log.debug( "Actual: " + str( current ) )
3799 getResults = main.FALSE
3800 else:
3801 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003802 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003803 " has repeat elements in" +
3804 " set " + onosSetName + ":\n" +
3805 str( getResponses[ i ] ) )
3806 getResults = main.FALSE
3807 elif getResponses[ i ] == main.ERROR:
3808 getResults = main.FALSE
3809 sizeResponses = []
3810 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003811 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003812 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003813 name="setTestSize-" + str( i ),
3814 args=[ onosSetName ] )
3815 threads.append( t )
3816 t.start()
3817 for t in threads:
3818 t.join()
3819 sizeResponses.append( t.result )
3820 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003821 for i in range( len( main.activeNodes ) ):
3822 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003823 if size != sizeResponses[ i ]:
3824 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003825 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003826 " expected a size of " + str( size ) +
3827 " for set " + onosSetName +
3828 " but got " + str( sizeResponses[ i ] ) )
3829 removeAllResults = removeAllResults and getResults and sizeResults
3830 utilities.assert_equals( expect=main.TRUE,
3831 actual=removeAllResults,
3832 onpass="Set removeAll correct",
3833 onfail="Set removeAll was incorrect" )
3834
3835 main.step( "Distributed Set addAll()" )
3836 onosSet.update( addAllValue.split() )
3837 addResponses = []
3838 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003839 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003840 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07003841 name="setTestAddAll-" + str( i ),
3842 args=[ onosSetName, addAllValue ] )
3843 threads.append( t )
3844 t.start()
3845 for t in threads:
3846 t.join()
3847 addResponses.append( t.result )
3848
3849 # main.TRUE = successfully changed the set
3850 # main.FALSE = action resulted in no change in set
3851 # main.ERROR - Some error in executing the function
3852 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003853 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003854 if addResponses[ i ] == main.TRUE:
3855 # All is well
3856 pass
3857 elif addResponses[ i ] == main.FALSE:
3858 # Already in set, probably fine
3859 pass
3860 elif addResponses[ i ] == main.ERROR:
3861 # Error in execution
3862 addAllResults = main.FALSE
3863 else:
3864 # unexpected result
3865 addAllResults = main.FALSE
3866 if addAllResults != main.TRUE:
3867 main.log.error( "Error executing set addAll" )
3868
3869 # Check if set is still correct
3870 size = len( onosSet )
3871 getResponses = []
3872 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003873 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003874 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003875 name="setTestGet-" + str( i ),
3876 args=[ onosSetName ] )
3877 threads.append( t )
3878 t.start()
3879 for t in threads:
3880 t.join()
3881 getResponses.append( t.result )
3882 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003883 for i in range( len( main.activeNodes ) ):
3884 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003885 if isinstance( getResponses[ i ], list):
3886 current = set( getResponses[ i ] )
3887 if len( current ) == len( getResponses[ i ] ):
3888 # no repeats
3889 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003890 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003891 " has incorrect view" +
3892 " of set " + onosSetName + ":\n" +
3893 str( getResponses[ i ] ) )
3894 main.log.debug( "Expected: " + str( onosSet ) )
3895 main.log.debug( "Actual: " + str( current ) )
3896 getResults = main.FALSE
3897 else:
3898 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003899 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003900 " has repeat elements in" +
3901 " set " + onosSetName + ":\n" +
3902 str( getResponses[ i ] ) )
3903 getResults = main.FALSE
3904 elif getResponses[ i ] == main.ERROR:
3905 getResults = main.FALSE
3906 sizeResponses = []
3907 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003908 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003909 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07003910 name="setTestSize-" + str( i ),
3911 args=[ onosSetName ] )
3912 threads.append( t )
3913 t.start()
3914 for t in threads:
3915 t.join()
3916 sizeResponses.append( t.result )
3917 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003918 for i in range( len( main.activeNodes ) ):
3919 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003920 if size != sizeResponses[ i ]:
3921 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003922 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003923 " expected a size of " + str( size ) +
3924 " for set " + onosSetName +
3925 " but got " + str( sizeResponses[ i ] ) )
3926 addAllResults = addAllResults and getResults and sizeResults
3927 utilities.assert_equals( expect=main.TRUE,
3928 actual=addAllResults,
3929 onpass="Set addAll correct",
3930 onfail="Set addAll was incorrect" )
3931
3932 main.step( "Distributed Set clear()" )
3933 onosSet.clear()
3934 clearResponses = []
3935 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003936 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003937 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07003938 name="setTestClear-" + str( i ),
3939 args=[ onosSetName, " "], # Values doesn't matter
3940 kwargs={ "clear": True } )
3941 threads.append( t )
3942 t.start()
3943 for t in threads:
3944 t.join()
3945 clearResponses.append( t.result )
3946
3947 # main.TRUE = successfully changed the set
3948 # main.FALSE = action resulted in no change in set
3949 # main.ERROR - Some error in executing the function
3950 clearResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003951 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07003952 if clearResponses[ i ] == main.TRUE:
3953 # All is well
3954 pass
3955 elif clearResponses[ i ] == main.FALSE:
3956 # Nothing set, probably fine
3957 pass
3958 elif clearResponses[ i ] == main.ERROR:
3959 # Error in execution
3960 clearResults = main.FALSE
3961 else:
3962 # unexpected result
3963 clearResults = main.FALSE
3964 if clearResults != main.TRUE:
3965 main.log.error( "Error executing set clear" )
3966
3967 # Check if set is still correct
3968 size = len( onosSet )
3969 getResponses = []
3970 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003971 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07003972 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07003973 name="setTestGet-" + str( i ),
3974 args=[ onosSetName ] )
3975 threads.append( t )
3976 t.start()
3977 for t in threads:
3978 t.join()
3979 getResponses.append( t.result )
3980 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003981 for i in range( len( main.activeNodes ) ):
3982 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07003983 if isinstance( getResponses[ i ], list):
3984 current = set( getResponses[ i ] )
3985 if len( current ) == len( getResponses[ i ] ):
3986 # no repeats
3987 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003988 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003989 " has incorrect view" +
3990 " of set " + onosSetName + ":\n" +
3991 str( getResponses[ i ] ) )
3992 main.log.debug( "Expected: " + str( onosSet ) )
3993 main.log.debug( "Actual: " + str( current ) )
3994 getResults = main.FALSE
3995 else:
3996 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07003997 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07003998 " has repeat elements in" +
3999 " set " + onosSetName + ":\n" +
4000 str( getResponses[ i ] ) )
4001 getResults = main.FALSE
4002 elif getResponses[ i ] == main.ERROR:
4003 getResults = main.FALSE
4004 sizeResponses = []
4005 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004006 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004007 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004008 name="setTestSize-" + str( i ),
4009 args=[ onosSetName ] )
4010 threads.append( t )
4011 t.start()
4012 for t in threads:
4013 t.join()
4014 sizeResponses.append( t.result )
4015 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004016 for i in range( len( main.activeNodes ) ):
4017 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004018 if size != sizeResponses[ i ]:
4019 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004020 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004021 " expected a size of " + str( size ) +
4022 " for set " + onosSetName +
4023 " but got " + str( sizeResponses[ i ] ) )
4024 clearResults = clearResults and getResults and sizeResults
4025 utilities.assert_equals( expect=main.TRUE,
4026 actual=clearResults,
4027 onpass="Set clear correct",
4028 onfail="Set clear was incorrect" )
4029
4030 main.step( "Distributed Set addAll()" )
4031 onosSet.update( addAllValue.split() )
4032 addResponses = []
4033 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004034 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004035 t = main.Thread( target=main.CLIs[i].setTestAdd,
Jon Hall5cf14d52015-07-16 12:15:19 -07004036 name="setTestAddAll-" + str( i ),
4037 args=[ onosSetName, addAllValue ] )
4038 threads.append( t )
4039 t.start()
4040 for t in threads:
4041 t.join()
4042 addResponses.append( t.result )
4043
4044 # main.TRUE = successfully changed the set
4045 # main.FALSE = action resulted in no change in set
4046 # main.ERROR - Some error in executing the function
4047 addAllResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004048 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004049 if addResponses[ i ] == main.TRUE:
4050 # All is well
4051 pass
4052 elif addResponses[ i ] == main.FALSE:
4053 # Already in set, probably fine
4054 pass
4055 elif addResponses[ i ] == main.ERROR:
4056 # Error in execution
4057 addAllResults = main.FALSE
4058 else:
4059 # unexpected result
4060 addAllResults = main.FALSE
4061 if addAllResults != main.TRUE:
4062 main.log.error( "Error executing set addAll" )
4063
4064 # Check if set is still correct
4065 size = len( onosSet )
4066 getResponses = []
4067 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004068 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004069 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004070 name="setTestGet-" + str( i ),
4071 args=[ onosSetName ] )
4072 threads.append( t )
4073 t.start()
4074 for t in threads:
4075 t.join()
4076 getResponses.append( t.result )
4077 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004078 for i in range( len( main.activeNodes ) ):
4079 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004080 if isinstance( getResponses[ i ], list):
4081 current = set( getResponses[ i ] )
4082 if len( current ) == len( getResponses[ i ] ):
4083 # no repeats
4084 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004085 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004086 " has incorrect view" +
4087 " of set " + onosSetName + ":\n" +
4088 str( getResponses[ i ] ) )
4089 main.log.debug( "Expected: " + str( onosSet ) )
4090 main.log.debug( "Actual: " + str( current ) )
4091 getResults = main.FALSE
4092 else:
4093 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004094 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004095 " has repeat elements in" +
4096 " set " + onosSetName + ":\n" +
4097 str( getResponses[ i ] ) )
4098 getResults = main.FALSE
4099 elif getResponses[ i ] == main.ERROR:
4100 getResults = main.FALSE
4101 sizeResponses = []
4102 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004103 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004104 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004105 name="setTestSize-" + str( i ),
4106 args=[ onosSetName ] )
4107 threads.append( t )
4108 t.start()
4109 for t in threads:
4110 t.join()
4111 sizeResponses.append( t.result )
4112 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004113 for i in range( len( main.activeNodes ) ):
4114 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004115 if size != sizeResponses[ i ]:
4116 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004117 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004118 " expected a size of " + str( size ) +
4119 " for set " + onosSetName +
4120 " but got " + str( sizeResponses[ i ] ) )
4121 addAllResults = addAllResults and getResults and sizeResults
4122 utilities.assert_equals( expect=main.TRUE,
4123 actual=addAllResults,
4124 onpass="Set addAll correct",
4125 onfail="Set addAll was incorrect" )
4126
4127 main.step( "Distributed Set retain()" )
4128 onosSet.intersection_update( retainValue.split() )
4129 retainResponses = []
4130 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004131 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004132 t = main.Thread( target=main.CLIs[i].setTestRemove,
Jon Hall5cf14d52015-07-16 12:15:19 -07004133 name="setTestRetain-" + str( i ),
4134 args=[ onosSetName, retainValue ],
4135 kwargs={ "retain": True } )
4136 threads.append( t )
4137 t.start()
4138 for t in threads:
4139 t.join()
4140 retainResponses.append( t.result )
4141
4142 # main.TRUE = successfully changed the set
4143 # main.FALSE = action resulted in no change in set
4144 # main.ERROR - Some error in executing the function
4145 retainResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004146 for i in range( len( main.activeNodes ) ):
Jon Hall5cf14d52015-07-16 12:15:19 -07004147 if retainResponses[ i ] == main.TRUE:
4148 # All is well
4149 pass
4150 elif retainResponses[ i ] == main.FALSE:
4151 # Already in set, probably fine
4152 pass
4153 elif retainResponses[ i ] == main.ERROR:
4154 # Error in execution
4155 retainResults = main.FALSE
4156 else:
4157 # unexpected result
4158 retainResults = main.FALSE
4159 if retainResults != main.TRUE:
4160 main.log.error( "Error executing set retain" )
4161
4162 # Check if set is still correct
4163 size = len( onosSet )
4164 getResponses = []
4165 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004166 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004167 t = main.Thread( target=main.CLIs[i].setTestGet,
Jon Hall5cf14d52015-07-16 12:15:19 -07004168 name="setTestGet-" + str( i ),
4169 args=[ onosSetName ] )
4170 threads.append( t )
4171 t.start()
4172 for t in threads:
4173 t.join()
4174 getResponses.append( t.result )
4175 getResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004176 for i in range( len( main.activeNodes ) ):
4177 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004178 if isinstance( getResponses[ i ], list):
4179 current = set( getResponses[ i ] )
4180 if len( current ) == len( getResponses[ i ] ):
4181 # no repeats
4182 if onosSet != current:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004183 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004184 " has incorrect view" +
4185 " of set " + onosSetName + ":\n" +
4186 str( getResponses[ i ] ) )
4187 main.log.debug( "Expected: " + str( onosSet ) )
4188 main.log.debug( "Actual: " + str( current ) )
4189 getResults = main.FALSE
4190 else:
4191 # error, set is not a set
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004192 main.log.error( "ONOS" + node +
Jon Hall5cf14d52015-07-16 12:15:19 -07004193 " has repeat elements in" +
4194 " set " + onosSetName + ":\n" +
4195 str( getResponses[ i ] ) )
4196 getResults = main.FALSE
4197 elif getResponses[ i ] == main.ERROR:
4198 getResults = main.FALSE
4199 sizeResponses = []
4200 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004201 for i in main.activeNodes:
Jon Halle1a3b752015-07-22 13:02:46 -07004202 t = main.Thread( target=main.CLIs[i].setTestSize,
Jon Hall5cf14d52015-07-16 12:15:19 -07004203 name="setTestSize-" + str( i ),
4204 args=[ onosSetName ] )
4205 threads.append( t )
4206 t.start()
4207 for t in threads:
4208 t.join()
4209 sizeResponses.append( t.result )
4210 sizeResults = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004211 for i in range( len( main.activeNodes ) ):
4212 node = str( main.activeNodes[i] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07004213 if size != sizeResponses[ i ]:
4214 sizeResults = main.FALSE
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004215 main.log.error( "ONOS" + node + " expected a size of " +
Jon Hall5cf14d52015-07-16 12:15:19 -07004216 str( size ) + " for set " + onosSetName +
4217 " but got " + str( sizeResponses[ i ] ) )
4218 retainResults = retainResults and getResults and sizeResults
4219 utilities.assert_equals( expect=main.TRUE,
4220 actual=retainResults,
4221 onpass="Set retain correct",
4222 onfail="Set retain was incorrect" )
4223
Jon Hall2a5002c2015-08-21 16:49:11 -07004224 # Transactional maps
4225 main.step( "Partitioned Transactional maps put" )
4226 tMapValue = "Testing"
4227 numKeys = 100
4228 putResult = True
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004229 node = main.activeNodes[0]
4230 putResponses = main.CLIs[node].transactionalMapPut( numKeys, tMapValue )
Jon Hall6e709752016-02-01 13:38:46 -08004231 if putResponses and len( putResponses ) == 100:
Jon Hall2a5002c2015-08-21 16:49:11 -07004232 for i in putResponses:
4233 if putResponses[ i ][ 'value' ] != tMapValue:
4234 putResult = False
4235 else:
4236 putResult = False
4237 if not putResult:
4238 main.log.debug( "Put response values: " + str( putResponses ) )
4239 utilities.assert_equals( expect=True,
4240 actual=putResult,
4241 onpass="Partitioned Transactional Map put successful",
4242 onfail="Partitioned Transactional Map put values are incorrect" )
4243
4244 main.step( "Partitioned Transactional maps get" )
4245 getCheck = True
4246 for n in range( 1, numKeys + 1 ):
4247 getResponses = []
4248 threads = []
4249 valueCheck = True
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004250 for i in main.activeNodes:
Jon Hall2a5002c2015-08-21 16:49:11 -07004251 t = main.Thread( target=main.CLIs[i].transactionalMapGet,
4252 name="TMap-get-" + str( i ),
Jon Hallb3ed8ed2015-10-28 16:43:55 -07004253 args=[ "Key" + str( n ) ] )
Jon Hall2a5002c2015-08-21 16:49:11 -07004254 threads.append( t )
4255 t.start()
4256 for t in threads:
4257 t.join()
4258 getResponses.append( t.result )
4259 for node in getResponses:
4260 if node != tMapValue:
4261 valueCheck = False
4262 if not valueCheck:
4263 main.log.warn( "Values for key 'Key" + str( n ) + "' do not match:" )
4264 main.log.warn( getResponses )
4265 getCheck = getCheck and valueCheck
4266 utilities.assert_equals( expect=True,
4267 actual=getCheck,
4268 onpass="Partitioned Transactional Map get values were correct",
4269 onfail="Partitioned Transactional Map values incorrect" )