blob: d2a2ec1cdb5fd61490f2c0785f9b6d1568d36a72 [file] [log] [blame]
Jon Hall63604932015-02-26 17:09:50 -08001"""
2Description: This test is to determine how ONOS behaves in a control network
3 partion. ONOS 1,2,3 will be split into a sub cluster and ONOS
4 4,5,6,7 will be in another sub-cluster.
5
6List of test cases:
7CASE1: Compile ONOS and push it to the test machines
8CASE2: Assign mastership to controllers
9CASE3: Assign intents
10CASE4: Ping across added host intents
11CASE5: Reading state of ONOS
12CASE6: The Failure case. We will create IPTables rules here.
13CASE7: Check state after control plane partition.
14CASE8: Compare topo
15CASE9: Link s3-s28 down
16CASE10: Link s3-s28 up
17CASE11: Switch down
18CASE12: Switch up
19CASE13: Clean up
20CASE14: start election app on all onos nodes
21CASE15: Check that Leadership Election is still functional
22CASE16: Repair network partition
23"""
24# FIXME: Add new comparison case for during the failure?
25class HATestNetworkPartition:
26
27 def __init__( self ):
28 self.default = ''
29
30 def CASE1( self, main ):
31 """
32 CASE1 is to compile ONOS and push it to the test machines
33
34 Startup sequence:
35 cell <name>
36 onos-verify-cell
37 NOTE: temporary - onos-remove-raft-logs
38 onos-uninstall
39 start mininet
40 git pull
41 mvn clean install
42 onos-package
43 onos-install -f
44 onos-wait-for-start
45 start cli sessions
46 start tcpdump
47 """
48 main.log.report( "ONOS HA test: Network partition - initialization" )
49 main.log.report( "This test will partition a 7 node cluster into " +
50 "3 node and 4 node sub clusters by blocking " +
51 "communication between nodes." )
52 main.case( "Setting up test environment" )
53 # TODO: save all the timers and output them for plotting
54
55 # load some vairables from the params file
56 PULLCODE = False
57 if main.params[ 'Git' ] == 'True':
58 PULLCODE = True
59 gitBranch = main.params[ 'branch' ]
60 cellName = main.params[ 'ENV' ][ 'cellName' ]
61
62 # set global variables
63 global ONOS1Ip
64 global ONOS1Port
65 global ONOS2Ip
66 global ONOS2Port
67 global ONOS3Ip
68 global ONOS3Port
69 global ONOS4Ip
70 global ONOS4Port
71 global ONOS5Ip
72 global ONOS5Port
73 global ONOS6Ip
74 global ONOS6Port
75 global ONOS7Ip
76 global ONOS7Port
77 global numControllers
78
79 ONOS1Ip = main.params[ 'CTRL' ][ 'ip1' ]
80 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
81 ONOS2Ip = main.params[ 'CTRL' ][ 'ip2' ]
82 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
83 ONOS3Ip = main.params[ 'CTRL' ][ 'ip3' ]
84 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
85 ONOS4Ip = main.params[ 'CTRL' ][ 'ip4' ]
86 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
87 ONOS5Ip = main.params[ 'CTRL' ][ 'ip5' ]
88 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
89 ONOS6Ip = main.params[ 'CTRL' ][ 'ip6' ]
90 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
91 ONOS7Ip = main.params[ 'CTRL' ][ 'ip7' ]
92 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
93 numControllers = int( main.params[ 'num_controllers' ] )
94
95 main.step( "Applying cell variable to environment" )
96 cellResult = main.ONOSbench.setCell( cellName )
97 verifyResult = main.ONOSbench.verifyCell()
98
99 # FIXME:this is short term fix
100 main.log.report( "Removing raft logs" )
101 main.ONOSbench.onosRemoveRaftLogs()
102 main.log.report( "Uninstalling ONOS" )
103 main.ONOSbench.onosUninstall( ONOS1Ip )
104 main.ONOSbench.onosUninstall( ONOS2Ip )
105 main.ONOSbench.onosUninstall( ONOS3Ip )
106 main.ONOSbench.onosUninstall( ONOS4Ip )
107 main.ONOSbench.onosUninstall( ONOS5Ip )
108 main.ONOSbench.onosUninstall( ONOS6Ip )
109 main.ONOSbench.onosUninstall( ONOS7Ip )
110
111 cleanInstallResult = main.TRUE
112 gitPullResult = main.TRUE
113
114 main.step( "Starting Mininet" )
115 main.Mininet1.startNet( )
116
117 main.step( "Compiling the latest version of ONOS" )
118 if PULLCODE:
119 main.step( "Git checkout and pull " + gitBranch )
120 main.ONOSbench.gitCheckout( gitBranch )
121 gitPullResult = main.ONOSbench.gitPull()
122
Jon Hallfeff3082015-05-19 10:23:26 -0700123 main.step( "Using mvn clean and install" )
Jon Hall63604932015-02-26 17:09:50 -0800124 cleanInstallResult = main.ONOSbench.cleanInstall()
125 else:
126 main.log.warn( "Did not pull new code so skipping mvn " +
127 "clean install" )
128 main.ONOSbench.getVersion( report=True )
Jon Hallfeff3082015-05-19 10:23:26 -0700129 # GRAPHS
130 # NOTE: important params here:
131 # job = name of Jenkins job
132 # Plot Name = Plot-HA, only can be used if multiple plots
133 # index = The number of the graph under plot name
134 job = "HANetworkPartition"
135 graphs = '<ac:structured-macro ac:name="html">\n'
136 graphs += '<ac:plain-text-body><![CDATA[\n'
137 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
138 '/plot/getPlot?index=0&width=500&height=300"' +\
139 'noborder="0" width="500" height="300" scrolling="yes" '+\
140 'seamless="seamless"></iframe>\n'
141 graphs += ']]></ac:plain-text-body>\n'
142 graphs += '</ac:structured-macro>\n'
143 main.log.wiki(graphs)
Jon Hall63604932015-02-26 17:09:50 -0800144
145 main.step( "Creating ONOS package" )
146 packageResult = main.ONOSbench.onosPackage()
147
148 main.step( "Installing ONOS package" )
149 onos1InstallResult = main.ONOSbench.onosInstall( options="-f",
150 node=ONOS1Ip )
151 onos2InstallResult = main.ONOSbench.onosInstall( options="-f",
152 node=ONOS2Ip )
153 onos3InstallResult = main.ONOSbench.onosInstall( options="-f",
154 node=ONOS3Ip )
155 onos4InstallResult = main.ONOSbench.onosInstall( options="-f",
156 node=ONOS4Ip )
157 onos5InstallResult = main.ONOSbench.onosInstall( options="-f",
158 node=ONOS5Ip )
159 onos6InstallResult = main.ONOSbench.onosInstall( options="-f",
160 node=ONOS6Ip )
161 onos7InstallResult = main.ONOSbench.onosInstall( options="-f",
162 node=ONOS7Ip )
163 onosInstallResult = onos1InstallResult and onos2InstallResult\
164 and onos3InstallResult and onos4InstallResult\
165 and onos5InstallResult and onos6InstallResult\
166 and onos7InstallResult
167
168 main.step( "Checking if ONOS is up yet" )
169 for i in range( 2 ):
170 onos1Isup = main.ONOSbench.isup( ONOS1Ip )
171 if not onos1Isup:
172 main.log.report( "ONOS1 didn't start!" )
173 main.ONOSbench.onosStop( ONOS1Ip )
174 main.ONOSbench.onosStart( ONOS1Ip )
175 onos2Isup = main.ONOSbench.isup( ONOS2Ip )
176 if not onos2Isup:
177 main.log.report( "ONOS2 didn't start!" )
178 main.ONOSbench.onosStop( ONOS2Ip )
179 main.ONOSbench.onosStart( ONOS2Ip )
180 onos3Isup = main.ONOSbench.isup( ONOS3Ip )
181 if not onos3Isup:
182 main.log.report( "ONOS3 didn't start!" )
183 main.ONOSbench.onosStop( ONOS3Ip )
184 main.ONOSbench.onosStart( ONOS3Ip )
185 onos4Isup = main.ONOSbench.isup( ONOS4Ip )
186 if not onos4Isup:
187 main.log.report( "ONOS4 didn't start!" )
188 main.ONOSbench.onosStop( ONOS4Ip )
189 main.ONOSbench.onosStart( ONOS4Ip )
190 onos5Isup = main.ONOSbench.isup( ONOS5Ip )
191 if not onos5Isup:
192 main.log.report( "ONOS5 didn't start!" )
193 main.ONOSbench.onosStop( ONOS5Ip )
194 main.ONOSbench.onosStart( ONOS5Ip )
195 onos6Isup = main.ONOSbench.isup( ONOS6Ip )
196 if not onos6Isup:
197 main.log.report( "ONOS6 didn't start!" )
198 main.ONOSbench.onosStop( ONOS6Ip )
199 main.ONOSbench.onosStart( ONOS6Ip )
200 onos7Isup = main.ONOSbench.isup( ONOS7Ip )
201 if not onos7Isup:
202 main.log.report( "ONOS7 didn't start!" )
203 main.ONOSbench.onosStop( ONOS7Ip )
204 main.ONOSbench.onosStart( ONOS7Ip )
205 onosIsupResult = onos1Isup and onos2Isup and onos3Isup\
206 and onos4Isup and onos5Isup and onos6Isup and onos7Isup
207 if onosIsupResult == main.TRUE:
208 break
209
210 cliResult1 = main.ONOScli1.startOnosCli( ONOS1Ip )
211 cliResult2 = main.ONOScli2.startOnosCli( ONOS2Ip )
212 cliResult3 = main.ONOScli3.startOnosCli( ONOS3Ip )
213 cliResult4 = main.ONOScli4.startOnosCli( ONOS4Ip )
214 cliResult5 = main.ONOScli5.startOnosCli( ONOS5Ip )
215 cliResult6 = main.ONOScli6.startOnosCli( ONOS6Ip )
216 cliResult7 = main.ONOScli7.startOnosCli( ONOS7Ip )
217 cliResults = cliResult1 and cliResult2 and cliResult3 and\
218 cliResult4 and cliResult5 and cliResult6 and cliResult7
219
Jon Hall40d2cbd2015-06-03 16:24:29 -0700220 if main.params[ 'tcpdump' ].lower() == "true":
221 main.step( "Start Packet Capture MN" )
222 main.Mininet2.startTcpdump(
223 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
224 + "-MN.pcap",
225 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
226 port=main.params[ 'MNtcpdump' ][ 'port' ] )
Jon Hall63604932015-02-26 17:09:50 -0800227
228 case1Result = ( cleanInstallResult and packageResult and
229 cellResult and verifyResult and onosInstallResult
230 and onosIsupResult and cliResults )
231
232 utilities.assert_equals( expect=main.TRUE, actual=case1Result,
233 onpass="Test startup successful",
234 onfail="Test startup NOT successful" )
235
236 if case1Result == main.FALSE:
Jon Hallfeff3082015-05-19 10:23:26 -0700237 main.log.error( "Failed to start ONOS, stopping test" )
Jon Hall63604932015-02-26 17:09:50 -0800238 main.cleanup()
239 main.exit()
240
241 def CASE2( self, main ):
242 """
243 Assign mastership to controllers
244 """
245 import re
246
247 main.log.report( "Assigning switches to controllers" )
248 main.case( "Assigning Controllers" )
249 main.step( "Assign switches to controllers" )
250
251 for i in range( 1, 29 ):
252 main.Mininet1.assignSwController(
253 sw=str( i ),
254 count=numControllers,
255 ip1=ONOS1Ip, port1=ONOS1Port,
256 ip2=ONOS2Ip, port2=ONOS2Port,
257 ip3=ONOS3Ip, port3=ONOS3Port,
258 ip4=ONOS4Ip, port4=ONOS4Port,
259 ip5=ONOS5Ip, port5=ONOS5Port,
260 ip6=ONOS6Ip, port6=ONOS6Port,
261 ip7=ONOS7Ip, port7=ONOS7Port )
262
263 mastershipCheck = main.TRUE
264 for i in range( 1, 29 ):
265 response = main.Mininet1.getSwController( "s" + str( i ) )
266 try:
267 main.log.info( str( response ) )
268 except:
269 main.log.info( repr( response ) )
270 if re.search( "tcp:" + ONOS1Ip, response )\
271 and re.search( "tcp:" + ONOS2Ip, response )\
272 and re.search( "tcp:" + ONOS3Ip, response )\
273 and re.search( "tcp:" + ONOS4Ip, response )\
274 and re.search( "tcp:" + ONOS5Ip, response )\
275 and re.search( "tcp:" + ONOS6Ip, response )\
276 and re.search( "tcp:" + ONOS7Ip, response ):
277 mastershipCheck = mastershipCheck and main.TRUE
278 else:
279 mastershipCheck = main.FALSE
280 if mastershipCheck == main.TRUE:
281 main.log.report( "Switch mastership assigned correctly" )
282 utilities.assert_equals(
283 expect=main.TRUE,
284 actual=mastershipCheck,
285 onpass="Switch mastership assigned correctly",
286 onfail="Switches not assigned correctly to controllers" )
287
288 # Manually assign mastership to the controller we want
289 roleCall = main.TRUE
290 roleCheck = main.TRUE
291
292 # Assign switch
293 deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
294 roleCall = roleCall and main.ONOScli1.deviceRole(
295 deviceId,
296 ONOS1Ip )
297 # Check assignment
298 if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
299 roleCheck = roleCheck and main.TRUE
300 else:
301 roleCheck = roleCheck and main.FALSE
302
303 # Assign switch
304 deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
305 roleCall = roleCall and main.ONOScli1.deviceRole(
306 deviceId,
307 ONOS1Ip )
308 # Check assignment
309 if ONOS1Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
310 roleCheck = roleCheck and main.TRUE
311 else:
312 roleCheck = roleCheck and main.FALSE
313
314 # Assign switch
315 deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
316 roleCall = roleCall and main.ONOScli1.deviceRole(
317 deviceId,
318 ONOS2Ip )
319 # Check assignment
320 if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
321 roleCheck = roleCheck and main.TRUE
322 else:
323 roleCheck = roleCheck and main.FALSE
324
325 # Assign switch
326 deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
327 roleCall = roleCall and main.ONOScli1.deviceRole(
328 deviceId,
329 ONOS2Ip )
330 # Check assignment
331 if ONOS2Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
332 roleCheck = roleCheck and main.TRUE
333 else:
334 roleCheck = roleCheck and main.FALSE
335
336 # Assign switch
337 deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
338 roleCall = roleCall and main.ONOScli1.deviceRole(
339 deviceId,
340 ONOS3Ip )
341 # Check assignment
342 if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
343 roleCheck = roleCheck and main.TRUE
344 else:
345 roleCheck = roleCheck and main.FALSE
346
347 # Assign switch
348 deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
349 roleCall = roleCall and main.ONOScli1.deviceRole(
350 deviceId,
351 ONOS3Ip )
352 # Check assignment
353 if ONOS3Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
354 roleCheck = roleCheck and main.TRUE
355 else:
356 roleCheck = roleCheck and main.FALSE
357
358 # Assign switch
359 deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
360 roleCall = roleCall and main.ONOScli1.deviceRole(
361 deviceId,
362 ONOS4Ip )
363 # Check assignment
364 if ONOS4Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
365 roleCheck = roleCheck and main.TRUE
366 else:
367 roleCheck = roleCheck and main.FALSE
368
369 for i in range( 8, 18 ):
370 dpid = '3' + str( i ).zfill( 3 )
371 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
372 roleCall = roleCall and main.ONOScli1.deviceRole(
373 deviceId,
374 ONOS5Ip )
375 # Check assignment
376 if ONOS5Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
377 roleCheck = roleCheck and main.TRUE
378 else:
379 roleCheck = roleCheck and main.FALSE
380
381 deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
382 roleCall = roleCall and main.ONOScli1.deviceRole(
383 deviceId,
384 ONOS6Ip )
385 # Check assignment
386 if ONOS6Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
387 roleCheck = roleCheck and main.TRUE
388 else:
389 roleCheck = roleCheck and main.FALSE
390
391 for i in range( 18, 28 ):
392 dpid = '6' + str( i ).zfill( 3 )
393 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
394 roleCall = roleCall and main.ONOScli1.deviceRole(
395 deviceId,
396 ONOS7Ip )
397 # Check assignment
398 if ONOS7Ip in main.ONOScli1.getRole( deviceId ).get( 'master' ):
399 roleCheck = roleCheck and main.TRUE
400 else:
401 roleCheck = roleCheck and main.FALSE
402
403 utilities.assert_equals(
404 expect=main.TRUE,
405 actual=roleCall,
406 onpass="Re-assigned switch mastership to designated controller",
407 onfail="Something wrong with deviceRole calls" )
408
409 utilities.assert_equals(
410 expect=main.TRUE,
411 actual=roleCheck,
412 onpass="Switches were successfully reassigned to designated " +
413 "controller",
414 onfail="Switches were not successfully reassigned" )
415 mastershipCheck = mastershipCheck and roleCall and roleCheck
416 utilities.assert_equals( expect=main.TRUE, actual=mastershipCheck,
417 onpass="Switch mastership correctly assigned",
418 onfail="Error in (re)assigning switch" +
419 " mastership" )
420
421 def CASE3( self, main ):
422 """
423 Assign intents
424 """
425 import time
426 import json
427 main.log.report( "Adding host intents" )
428 main.case( "Adding host Intents" )
429
430 main.step( "Discovering Hosts( Via pingall for now )" )
431 # FIXME: Once we have a host discovery mechanism, use that instead
432
433 # install onos-app-fwd
434 main.log.info( "Install reactive forwarding app" )
Jon Halla9d26da2015-03-30 16:45:32 -0700435 appResults = CLIs[0].activateApp( "org.onosproject.fwd" )
436 '''
Jon Hall63604932015-02-26 17:09:50 -0800437 main.ONOScli1.featureInstall( "onos-app-fwd" )
438 main.ONOScli2.featureInstall( "onos-app-fwd" )
439 main.ONOScli3.featureInstall( "onos-app-fwd" )
440 main.ONOScli4.featureInstall( "onos-app-fwd" )
441 main.ONOScli5.featureInstall( "onos-app-fwd" )
442 main.ONOScli6.featureInstall( "onos-app-fwd" )
443 main.ONOScli7.featureInstall( "onos-app-fwd" )
Jon Halla9d26da2015-03-30 16:45:32 -0700444 '''
Jon Hall63604932015-02-26 17:09:50 -0800445
446 # REACTIVE FWD test
447 pingResult = main.FALSE
448 time1 = time.time()
449 pingResult = main.Mininet1.pingall()
450 utilities.assert_equals(
451 expect=main.TRUE,
452 actual=pingResult,
453 onpass="Reactive Pingall test passed",
454 onfail="Reactive Pingall failed, one or more ping pairs failed" )
455 time2 = time.time()
456 main.log.info( "Time for pingall: %2f seconds" % ( time2 - time1 ) )
457
458 # uninstall onos-app-fwd
459 main.log.info( "Uninstall reactive forwarding app" )
Jon Halla9d26da2015-03-30 16:45:32 -0700460 appResults = appResults and CLIs[0].deactivateApp( "org.onosproject.fwd" )
461 '''
Jon Hall63604932015-02-26 17:09:50 -0800462 main.ONOScli1.featureUninstall( "onos-app-fwd" )
463 main.ONOScli2.featureUninstall( "onos-app-fwd" )
464 main.ONOScli3.featureUninstall( "onos-app-fwd" )
465 main.ONOScli4.featureUninstall( "onos-app-fwd" )
466 main.ONOScli5.featureUninstall( "onos-app-fwd" )
467 main.ONOScli6.featureUninstall( "onos-app-fwd" )
468 main.ONOScli7.featureUninstall( "onos-app-fwd" )
Jon Halla9d26da2015-03-30 16:45:32 -0700469 '''
Jon Hall63604932015-02-26 17:09:50 -0800470 # timeout for fwd flows
471 time.sleep( 10 )
472
473 main.step( "Add host intents" )
474 # TODO: move the host numbers to params
475 # Maybe look at all the paths we ping?
476 intentAddResult = True
477 for i in range( 8, 18 ):
478 main.log.info( "Adding host intent between h" + str( i ) +
479 " and h" + str( i + 10 ) )
480 host1 = "00:00:00:00:00:" + \
481 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
482 host2 = "00:00:00:00:00:" + \
483 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
484 # NOTE: getHost can return None
485 host1Dict = main.ONOScli1.getHost( host1 )
486 host2Dict = main.ONOScli1.getHost( host2 )
487 host1Id = None
488 host2Id = None
489 if host1Dict and host2Dict:
490 host1Id = host1Dict.get( 'id', None )
491 host2Id = host2Dict.get( 'id', None )
492 if host1Id and host2Id:
493 # distribute the intents across ONOS nodes
494 nodeNum = ( i % 7 ) + 1
495 node = getattr( main, ( 'ONOScli' + str( nodeNum ) ) )
496 tmpResult = node.addHostIntent(
497 host1Id,
498 host2Id )
499 else:
500 main.log.error( "Error, getHost() failed" )
501 main.log.warn( json.dumps( json.loads( main.ONOScli1.hosts() ),
502 sort_keys=True,
503 indent=4,
504 separators=( ',', ': ' ) ) )
505 tmpResult = main.FALSE
506 intentAddResult = bool( pingResult and intentAddResult
507 and tmpResult )
508 # FIXME Check that intents were added?
509 # TODO Use the new return from add host command and look at each
510 # intent individually
511 #
512 #
513 #
514 #
515 #
516 #
517 # End of for loop to add intents
518 # Print the intent states
519 intents = main.ONOScli1.intents( )
520 intentStates = []
521 for intent in json.loads( intents ): # Iter through intents of a node
522 intentStates.append( intent.get( 'state', None ) )
523 out = [ (i, intentStates.count( i ) ) for i in set( intentStates ) ]
524 main.log.info( dict( out ) )
525
526 utilities.assert_equals(
527 expect=True,
528 actual=intentAddResult,
529 onpass="Pushed host intents to ONOS",
530 onfail="Error in pushing host intents to ONOS" )
531 # TODO Check if intents all exist in datastore
532
533 def CASE4( self, main ):
534 """
535 Ping across added host intents
536 """
537 import json
538 description = " Ping across added host intents"
539 main.log.report( description )
540 main.case( description )
541 PingResult = main.TRUE
542 for i in range( 8, 18 ):
543 ping = main.Mininet1.pingHost(
544 src="h" + str( i ), target="h" + str( i + 10 ) )
545 PingResult = PingResult and ping
546 if ping == main.FALSE:
547 main.log.warn( "Ping failed between h" + str( i ) +
548 " and h" + str( i + 10 ) )
549 elif ping == main.TRUE:
550 main.log.info( "Ping test passed!" )
551 # Don't set PingResult or you'd override failures
552 if PingResult == main.FALSE:
553 main.log.report(
554 "Intents have not been installed correctly, pings failed." )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700555 main.log.warn( "ONOS1 intents: " )
Jon Hall63604932015-02-26 17:09:50 -0800556 main.log.warn( json.dumps( json.loads( main.ONOScli1.intents() ),
557 sort_keys=True,
558 indent=4,
559 separators=( ',', ': ' ) ) )
560 if PingResult == main.TRUE:
561 main.log.report(
562 "Intents have been installed correctly and verified by pings" )
563 utilities.assert_equals(
564 expect=main.TRUE,
565 actual=PingResult,
566 onpass="Intents have been installed correctly and pings work",
567 onfail="Intents have not been installed correctly, pings failed." )
568
569 def CASE5( self, main ):
570 """
571 Reading state of ONOS
572 """
573 import json
574 # assumes that sts is already in you PYTHONPATH
575 from sts.topology.teston_topology import TestONTopology
576
577 main.log.report( "Setting up and gathering data for current state" )
578 main.case( "Setting up and gathering data for current state" )
579 # The general idea for this test case is to pull the state of
580 # ( intents,flows, topology,... ) from each ONOS node
581 # We can then compare them with eachother and also with past states
582
583 main.step( "Get the Mastership of each switch from each controller" )
584 global mastershipState
585 mastershipState = []
586
587 # Assert that each device has a master
588 ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
589 ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
590 ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
591 ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
592 ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
593 ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
594 ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
595 rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
596 ONOS3MasterNotNull and ONOS4MasterNotNull and\
597 ONOS5MasterNotNull and ONOS6MasterNotNull and\
598 ONOS7MasterNotNull
599 utilities.assert_equals(
600 expect=main.TRUE,
601 actual=rolesNotNull,
602 onpass="Each device has a master",
603 onfail="Some devices don't have a master assigned" )
604
605 ONOS1Mastership = main.ONOScli1.roles()
606 ONOS2Mastership = main.ONOScli2.roles()
607 ONOS3Mastership = main.ONOScli3.roles()
608 ONOS4Mastership = main.ONOScli4.roles()
609 ONOS5Mastership = main.ONOScli5.roles()
610 ONOS6Mastership = main.ONOScli6.roles()
611 ONOS7Mastership = main.ONOScli7.roles()
612 if "Error" in ONOS1Mastership or not ONOS1Mastership\
613 or "Error" in ONOS2Mastership or not ONOS2Mastership\
614 or "Error" in ONOS3Mastership or not ONOS3Mastership\
615 or "Error" in ONOS4Mastership or not ONOS4Mastership\
616 or "Error" in ONOS5Mastership or not ONOS5Mastership\
617 or "Error" in ONOS6Mastership or not ONOS6Mastership\
618 or "Error" in ONOS7Mastership or not ONOS7Mastership:
619 main.log.report( "Error in getting ONOS roles" )
620 for i in range( 1, numControllers + 1 ):
621 mastership = eval( "ONOS" + str( i ) + "Mastership" )
622 main.log.warn(
623 "ONOS" + str( i ) + " mastership response: " +
624 repr( mastership ) )
625 consistentMastership = main.FALSE
626 elif ONOS1Mastership == ONOS2Mastership\
627 and ONOS1Mastership == ONOS3Mastership\
628 and ONOS1Mastership == ONOS4Mastership\
629 and ONOS1Mastership == ONOS5Mastership\
630 and ONOS1Mastership == ONOS6Mastership\
631 and ONOS1Mastership == ONOS7Mastership:
632 mastershipState = ONOS1Mastership
633 consistentMastership = main.TRUE
634 main.log.report(
635 "Switch roles are consistent across all ONOS nodes" )
636 else:
637 for i in range( 1, numControllers + 1 ):
638 mastership = eval( "ONOS" + str( i ) + "Mastership" )
639 main.log.warn( "ONOS" + str( i ) + " roles: " +
640 json.dumps( json.loads( mastership ),
641 sort_keys=True,
642 indent=4,
643 separators=( ',', ': ' ) ) )
644 consistentMastership = main.FALSE
645 utilities.assert_equals(
646 expect=main.TRUE,
647 actual=consistentMastership,
648 onpass="Switch roles are consistent across all ONOS nodes",
649 onfail="ONOS nodes have different views of switch roles" )
650
651 main.step( "Get the intents from each controller" )
652 global intentState
653 intentState = []
654 ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
655 ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
656 ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
657 ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
658 ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
659 ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
660 ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
661 intentCheck = main.FALSE
662 if "Error" in ONOS1Intents or not ONOS1Intents\
663 or "Error" in ONOS2Intents or not ONOS2Intents\
664 or "Error" in ONOS3Intents or not ONOS3Intents\
665 or "Error" in ONOS4Intents or not ONOS4Intents\
666 or "Error" in ONOS5Intents or not ONOS5Intents\
667 or "Error" in ONOS6Intents or not ONOS6Intents\
668 or "Error" in ONOS7Intents or not ONOS7Intents:
669 main.log.report( "Error in getting ONOS intents" )
670 for i in range( 1, numControllers + 1 ):
671 intents = eval( "ONOS" + str( i ) + "Intents" )
672 main.log.warn(
673 "ONOS" + str( i ) + " intents response: " +
674 repr( intents ) )
675 elif ONOS1Intents == ONOS2Intents\
676 and ONOS1Intents == ONOS3Intents\
677 and ONOS1Intents == ONOS4Intents\
678 and ONOS1Intents == ONOS5Intents\
679 and ONOS1Intents == ONOS6Intents\
680 and ONOS1Intents == ONOS7Intents:
681 intentState = ONOS1Intents
682 intentCheck = main.TRUE
683 main.log.report( "Intents are consistent across all ONOS nodes" )
684 else:
685 for i in range( 1, numControllers + 1 ):
686 intents = eval( "ONOS" + str( i ) + "Intents" )
687 main.log.warn( "ONOS" + str( i ) + " intents: " +
688 json.dumps( json.loads( intents ),
689 sort_keys=True,
690 indent=4,
691 separators=( ',', ': ' ) ) )
692 utilities.assert_equals(
693 expect=main.TRUE,
694 actual=intentCheck,
695 onpass="Intents are consistent across all ONOS nodes",
696 onfail="ONOS nodes have different views of intents" )
697
698 main.step( "Get the flows from each controller" )
699 global flowState
700 flowState = []
701 ONOS1Flows = main.ONOScli1.flows( jsonFormat=True )
702 ONOS2Flows = main.ONOScli2.flows( jsonFormat=True )
703 ONOS3Flows = main.ONOScli3.flows( jsonFormat=True )
704 ONOS4Flows = main.ONOScli4.flows( jsonFormat=True )
705 ONOS5Flows = main.ONOScli5.flows( jsonFormat=True )
706 ONOS6Flows = main.ONOScli6.flows( jsonFormat=True )
707 ONOS7Flows = main.ONOScli7.flows( jsonFormat=True )
708 ONOS1FlowsJson = json.loads( ONOS1Flows )
709 ONOS2FlowsJson = json.loads( ONOS2Flows )
710 ONOS3FlowsJson = json.loads( ONOS3Flows )
711 ONOS4FlowsJson = json.loads( ONOS4Flows )
712 ONOS5FlowsJson = json.loads( ONOS5Flows )
713 ONOS6FlowsJson = json.loads( ONOS6Flows )
714 ONOS7FlowsJson = json.loads( ONOS7Flows )
715 flowCheck = main.FALSE
716 if "Error" in ONOS1Flows or not ONOS1Flows\
717 or "Error" in ONOS2Flows or not ONOS2Flows\
718 or "Error" in ONOS3Flows or not ONOS3Flows\
719 or "Error" in ONOS4Flows or not ONOS4Flows\
720 or "Error" in ONOS5Flows or not ONOS5Flows\
721 or "Error" in ONOS6Flows or not ONOS6Flows\
722 or "Error" in ONOS7Flows or not ONOS7Flows:
723 main.log.report( "Error in getting ONOS intents" )
724 for i in range( 1, numControllers + 1 ):
725 flowsIter = eval( "ONOS" + str( i ) + "Flows" )
726 main.log.warn( "ONOS" + str( i ) + " flows repsponse: " +
727 flowsIter )
728 elif len( ONOS1FlowsJson ) == len( ONOS2FlowsJson )\
729 and len( ONOS1FlowsJson ) == len( ONOS3FlowsJson )\
730 and len( ONOS1FlowsJson ) == len( ONOS4FlowsJson )\
731 and len( ONOS1FlowsJson ) == len( ONOS5FlowsJson )\
732 and len( ONOS1FlowsJson ) == len( ONOS6FlowsJson )\
733 and len( ONOS1FlowsJson ) == len( ONOS7FlowsJson ):
734 # TODO: Do a better check, maybe compare flows on switches?
735 flowState = ONOS1Flows
736 flowCheck = main.TRUE
737 main.log.report( "Flow count is consistent across all ONOS nodes" )
738 else:
739 for i in range( 1, numControllers + 1 ):
740 flowsJson = eval( "ONOS" + str( i ) + "FlowsJson" )
741 main.log.warn( "ONOS" + str( i ) + " flows repsponse: " +
742 json.dumps( flowsJson,
743 sort_keys=True,
744 indent=4,
745 separators=( ',', ': ' ) ) )
746 utilities.assert_equals(
747 expect=main.TRUE,
748 actual=flowCheck,
749 onpass="The flow count is consistent across all ONOS nodes",
750 onfail="ONOS nodes have different flow counts" )
751
752 main.step( "Get the OF Table entries" )
753 global flows
754 flows = []
755 for i in range( 1, 29 ):
756 flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
757
758 # TODO: Compare switch flow tables with ONOS flow tables
759
760 main.step( "Start continuous pings" )
761 for i in range( 1, 11 ):
762 source = main.params[ 'PING' ][ 'source' + str( i ) ]
763 target = main.params[ 'PING' ][ 'target' + str( i ) ]
764 main.Mininet2.pingLong(
765 src=source,
766 target=target,
767 pingTime=500 )
768 main.step( "Create TestONTopology object" )
769 ctrls = []
770 count = 1
771 while True:
772 temp = ()
773 if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
774 temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
775 temp = temp + ( "ONOS" + str( count ), )
776 temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
777 temp = temp + \
778 ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
779 ctrls.append( temp )
780 count = count + 1
781 else:
782 break
783 MNTopo = TestONTopology(
784 main.Mininet1,
785 ctrls ) # can also add Intent API info for intent operations
786
787 main.step( "Collecting topology information from ONOS" )
788 # TODO Refactor to a loop? We want all similar calls together?
789 # So get all "devices" as close together as possible
790 devices = []
791 print "ONOS1"
792 devices.append( main.ONOScli1.devices() )
793 print "ONOS2"
794 devices.append( main.ONOScli2.devices() )
795 print "ONOS3"
796 devices.append( main.ONOScli3.devices() )
797 print "ONOS4"
798 devices.append( main.ONOScli4.devices() )
799 print "ONOS5"
800 devices.append( main.ONOScli5.devices() )
801 print "ONOS6"
802 devices.append( main.ONOScli6.devices() )
803 print "ONOS7"
804 devices.append( main.ONOScli7.devices() )
805 hosts = []
806 hosts.append( main.ONOScli1.hosts() )
807 hosts.append( main.ONOScli2.hosts() )
808 hosts.append( main.ONOScli3.hosts() )
809 hosts.append( main.ONOScli4.hosts() )
810 hosts.append( main.ONOScli5.hosts() )
811 hosts.append( main.ONOScli6.hosts() )
812 hosts.append( main.ONOScli7.hosts() )
813 ports = []
814 ports.append( main.ONOScli1.ports() )
815 ports.append( main.ONOScli2.ports() )
816 ports.append( main.ONOScli3.ports() )
817 ports.append( main.ONOScli4.ports() )
818 ports.append( main.ONOScli5.ports() )
819 ports.append( main.ONOScli6.ports() )
820 ports.append( main.ONOScli7.ports() )
821 links = []
822 links.append( main.ONOScli1.links() )
823 links.append( main.ONOScli2.links() )
824 links.append( main.ONOScli3.links() )
825 links.append( main.ONOScli4.links() )
826 links.append( main.ONOScli5.links() )
827 links.append( main.ONOScli6.links() )
828 links.append( main.ONOScli7.links() )
829 clusters = []
830 clusters.append( main.ONOScli1.clusters() )
831 clusters.append( main.ONOScli2.clusters() )
832 clusters.append( main.ONOScli3.clusters() )
833 clusters.append( main.ONOScli4.clusters() )
834 clusters.append( main.ONOScli5.clusters() )
835 clusters.append( main.ONOScli6.clusters() )
836 clusters.append( main.ONOScli7.clusters() )
837 # Compare json objects for hosts and dataplane clusters
838
839 # hosts
840 consistentHostsResult = main.TRUE
841 for controller in range( len( hosts ) ):
842 controllerStr = str( controller + 1 )
843 if "Error" not in hosts[ controller ]:
844 if hosts[ controller ] == hosts[ 0 ]:
845 continue
846 else: # hosts not consistent
847 main.log.report( "hosts from ONOS" +
848 controllerStr +
849 " is inconsistent with ONOS1" )
850 main.log.warn( repr( hosts[ controller ] ) )
851 consistentHostsResult = main.FALSE
852
853 else:
854 main.log.report( "Error in getting ONOS hosts from ONOS" +
855 controllerStr )
856 consistentHostsResult = main.FALSE
857 main.log.warn( "ONOS" + controllerStr +
858 " hosts response: " +
859 repr( hosts[ controller ] ) )
860 utilities.assert_equals(
861 expect=main.TRUE,
862 actual=consistentHostsResult,
863 onpass="Hosts view is consistent across all ONOS nodes",
864 onfail="ONOS nodes have different views of hosts" )
865
866 # Strongly connected clusters of devices
867 consistentClustersResult = main.TRUE
868 for controller in range( len( clusters ) ):
869 if "Error" not in clusters[ controller ]:
870 if clusters[ controller ] == clusters[ 0 ]:
871 continue
872 else: # clusters not consistent
873 main.log.report( "clusters from ONOS" +
874 controllerStr +
875 " is inconsistent with ONOS1" )
876 consistentClustersResult = main.FALSE
877
878 else:
879 main.log.report( "Error in getting dataplane clusters " +
880 "from ONOS" + controllerStr )
881 consistentClustersResult = main.FALSE
882 main.log.warn( "ONOS" + controllerStr +
883 " clusters response: " +
884 repr( clusters[ controller ] ) )
885 utilities.assert_equals(
886 expect=main.TRUE,
887 actual=consistentClustersResult,
888 onpass="Clusters view is consistent across all ONOS nodes",
889 onfail="ONOS nodes have different views of clusters" )
890 # there should always only be one cluster
891 numClusters = len( json.loads( clusters[ 0 ] ) )
892 utilities.assert_equals(
893 expect=1,
894 actual=numClusters,
895 onpass="ONOS shows 1 SCC",
896 onfail="ONOS shows " +
897 str( numClusters ) +
898 " SCCs" )
899
900 main.step( "Comparing ONOS topology to MN" )
901 devicesResults = main.TRUE
902 portsResults = main.TRUE
903 linksResults = main.TRUE
904 for controller in range( numControllers ):
905 controllerStr = str( controller + 1 )
906 if devices[ controller ] or "Error" not in devices[ controller ]:
907 currentDevicesResult = main.Mininet1.compareSwitches(
908 MNTopo,
909 json.loads(
910 devices[ controller ] ) )
911 else:
912 currentDevicesResult = main.FALSE
913 utilities.assert_equals( expect=main.TRUE,
914 actual=currentDevicesResult,
915 onpass="ONOS" + controllerStr +
916 " Switches view is correct",
917 onfail="ONOS" + controllerStr +
918 " Switches view is incorrect" )
919
920 if ports[ controller ] or "Error" not in ports[ controller ]:
921 currentPortsResult = main.Mininet1.comparePorts(
922 MNTopo,
923 json.loads(
924 ports[ controller ] ) )
925 else:
926 currentPortsResult = main.FALSE
927 utilities.assert_equals( expect=main.TRUE,
928 actual=currentPortsResult,
929 onpass="ONOS" + controllerStr +
930 " ports view is correct",
931 onfail="ONOS" + controllerStr +
932 " ports view is incorrect" )
933
934 if links[ controller ] or "Error" not in links[ controller ]:
935 currentLinksResult = main.Mininet1.compareLinks(
936 MNTopo,
937 json.loads(
938 links[ controller ] ) )
939 else:
940 currentLinksResult = main.FALSE
941 utilities.assert_equals( expect=main.TRUE,
942 actual=currentLinksResult,
943 onpass="ONOS" + controllerStr +
944 " links view is correct",
945 onfail="ONOS" + controllerStr +
946 " links view is incorrect" )
947
948 devicesResults = devicesResults and currentDevicesResult
949 portsResults = portsResults and currentPortsResult
950 linksResults = linksResults and currentLinksResult
951
952 topoResult = devicesResults and portsResults and linksResults\
953 and consistentHostsResult and consistentClustersResult
954 utilities.assert_equals( expect=main.TRUE, actual=topoResult,
955 onpass="Topology Check Test successful",
956 onfail="Topology Check Test NOT successful" )
957
958 finalAssert = main.TRUE
959 finalAssert = finalAssert and topoResult and flowCheck \
960 and intentCheck and consistentMastership and rolesNotNull
961 utilities.assert_equals( expect=main.TRUE, actual=finalAssert,
962 onpass="State check successful",
963 onfail="State check NOT successful" )
964
965 def CASE6( self, main ):
966 """
967 The Failure case. We will create IPTables rules here.
968 """
969 import time
970 main.log.report( "Wait 30 seconds instead of inducing a failure" )
971 time.sleep( 30 )
972
973 # 1 blocks 4,5,6,7, mn
974 # 2 blocks 4,5,6,7, mn
975 # 3 blocks 4,5,6,7, mn
976 # 4 block 1,2,3
977 # 5 blocks 1,2,3
978 # 6 blocks 1,2,3
979 # 7 blocks 1,2,3
980
981 # TODO: use new log command
982 logcmd = "log:log \" About to partition the ONOS nodes\""
983 main.ONOScli1.handle.sendline( logcmd )
984 main.ONOScli1.handle.expect( "onos>" )
985 print main.ONOScli1.handle.before
986 main.ONOScli2.handle.sendline( logcmd )
987 main.ONOScli2.handle.expect( "onos>" )
988 print main.ONOScli2.handle.before
989 main.ONOScli3.handle.sendline( logcmd )
990 main.ONOScli3.handle.expect( "onos>" )
991 print main.ONOScli3.handle.before
992 main.ONOScli4.handle.sendline( logcmd )
993 main.ONOScli4.handle.expect( "onos>" )
994 print main.ONOScli4.handle.before
995 main.ONOScli5.handle.sendline( logcmd )
996 main.ONOScli5.handle.expect( "onos>" )
997 print main.ONOScli5.handle.before
998 main.ONOScli6.handle.sendline( logcmd )
999 main.ONOScli6.handle.expect( "onos>" )
1000 print main.ONOScli6.handle.before
1001 main.ONOScli7.handle.sendline( logcmd )
1002 main.ONOScli7.handle.expect( "onos>" )
1003 print main.ONOScli7.handle.before
1004
1005 nodes = []
1006 #create list of ONOS components
1007 for controller in range( 1, numControllers + 1 ):
1008 # loop through ONOS handlers
1009 node = getattr( main, ( 'ONOS' + str( controller ) ) )
1010 nodes.append( node )
1011 for node in nodes:
1012 # if node is in first half (rounded down )
1013 # ( 0 through 2 ) < ( 3.5 - 1)
1014 if nodes.index( node ) < ( numControllers / 2.0 - 1 ):
1015 # blocked nodes are the last half ( rounded up )
1016 # // is forced integer division
1017 for blockNode in nodes[ (numControllers // 2 + 1) * -1: ]:
1018 # block all traffic between these ONOS nodes
1019 # NOTE: ONOS 1 and 2 don't support state tracking
1020 node.setIpTables( blockNode.ip_address, states=False )
1021 node.setIpTables( blockNode.ip_address,
1022 direction="OUTPUT" , states=False )
1023 # block traffic between smaller subcluster and Mininet
1024 # TODO make OF controller port confgigurable
1025 # FIXME Remove this once ONOS can deal with the conflicting
1026 # device mastership
1027 node.setIpTables( main.Mininet1.ip_address, 6633,
1028 packet_type="tcp", states=False )
1029 else: # the larger subcluster
1030 # blocked nodes are the first half
1031 for blockNode in nodes[ :(numControllers // 2 ) ]:
1032 # block all traffic between these ONOS nodes
1033 node.setIpTables( blockNode.ip_address )
1034 node.setIpTables( blockNode.ip_address,
1035 direction="OUTPUT" )
1036 #FIXME update this
1037 utilities.assert_equals(
1038 expect=main.TRUE,
1039 actual=main.TRUE,
1040 onpass="Sleeping 30 seconds",
1041 onfail="Something is terribly wrong with my math" )
1042 main.ONOScli1.handle.sendline( "devices -j" )
1043 main.ONOScli1.handle.expect( ["onos>", "\$"] )
1044 print main.ONOScli1.handle.before
1045 main.ONOScli2.handle.sendline( "devices -j" )
1046 main.ONOScli2.handle.expect( ["onos>", "\$"] )
1047 print main.ONOScli2.handle.before
1048 main.ONOScli3.handle.sendline( "devices -j" )
1049 main.ONOScli3.handle.expect( ["onos>", "\$"] )
1050 print main.ONOScli3.handle.before
1051 main.ONOScli4.handle.sendline( "devices -j" )
1052 main.ONOScli4.handle.expect( ["onos>", "\$"] )
1053 print main.ONOScli4.handle.before
1054 main.ONOScli5.handle.sendline( "devices -j" )
1055 main.ONOScli5.handle.expect( ["onos>", "\$"] )
1056 print main.ONOScli5.handle.before
1057 main.ONOScli6.handle.sendline( "devices -j" )
1058 main.ONOScli6.handle.expect( ["onos>", "\$"] )
1059 print main.ONOScli6.handle.before
1060 main.ONOScli7.handle.sendline( "devices -j" )
1061 main.ONOScli7.handle.expect( ["onos>", "\$"] )
1062 print main.ONOScli7.handle.before
1063 time.sleep(100000)
1064
1065
1066 def CASE7( self, main ):
1067 """
1068 Check state after ONOS failure
1069 """
1070 import json
1071 main.case( "Running ONOS Constant State Tests" )
1072
1073 # Assert that each device has a master
1074 ONOS1MasterNotNull = main.ONOScli1.rolesNotNull()
1075 ONOS2MasterNotNull = main.ONOScli2.rolesNotNull()
1076 ONOS3MasterNotNull = main.ONOScli3.rolesNotNull()
1077 ONOS4MasterNotNull = main.ONOScli4.rolesNotNull()
1078 ONOS5MasterNotNull = main.ONOScli5.rolesNotNull()
1079 ONOS6MasterNotNull = main.ONOScli6.rolesNotNull()
1080 ONOS7MasterNotNull = main.ONOScli7.rolesNotNull()
1081 rolesNotNull = ONOS1MasterNotNull and ONOS2MasterNotNull and\
1082 ONOS3MasterNotNull and ONOS4MasterNotNull and\
1083 ONOS5MasterNotNull and ONOS6MasterNotNull and\
1084 ONOS7MasterNotNull
1085 utilities.assert_equals(
1086 expect=main.TRUE,
1087 actual=rolesNotNull,
1088 onpass="Each device has a master",
1089 onfail="Some devices don't have a master assigned" )
1090
1091 main.step( "Check if switch roles are consistent across all nodes" )
1092 ONOS1Mastership = main.ONOScli1.roles()
1093 ONOS2Mastership = main.ONOScli2.roles()
1094 ONOS3Mastership = main.ONOScli3.roles()
1095 ONOS4Mastership = main.ONOScli4.roles()
1096 ONOS5Mastership = main.ONOScli5.roles()
1097 ONOS6Mastership = main.ONOScli6.roles()
1098 ONOS7Mastership = main.ONOScli7.roles()
1099 if "Error" in ONOS1Mastership or not ONOS1Mastership\
1100 or "Error" in ONOS2Mastership or not ONOS2Mastership\
1101 or "Error" in ONOS3Mastership or not ONOS3Mastership\
1102 or "Error" in ONOS4Mastership or not ONOS4Mastership\
1103 or "Error" in ONOS5Mastership or not ONOS5Mastership\
1104 or "Error" in ONOS6Mastership or not ONOS6Mastership\
1105 or "Error" in ONOS7Mastership or not ONOS7Mastership:
1106 main.log.error( "Error in getting ONOS mastership" )
1107 main.log.warn( "ONOS1 mastership response: " +
1108 repr( ONOS1Mastership ) )
1109 main.log.warn( "ONOS2 mastership response: " +
1110 repr( ONOS2Mastership ) )
1111 main.log.warn( "ONOS3 mastership response: " +
1112 repr( ONOS3Mastership ) )
1113 main.log.warn( "ONOS4 mastership response: " +
1114 repr( ONOS4Mastership ) )
1115 main.log.warn( "ONOS5 mastership response: " +
1116 repr( ONOS5Mastership ) )
1117 main.log.warn( "ONOS6 mastership response: " +
1118 repr( ONOS6Mastership ) )
1119 main.log.warn( "ONOS7 mastership response: " +
1120 repr( ONOS7Mastership ) )
1121 consistentMastership = main.FALSE
1122 elif ONOS1Mastership == ONOS2Mastership\
1123 and ONOS1Mastership == ONOS3Mastership\
1124 and ONOS1Mastership == ONOS4Mastership\
1125 and ONOS1Mastership == ONOS5Mastership\
1126 and ONOS1Mastership == ONOS6Mastership\
1127 and ONOS1Mastership == ONOS7Mastership:
1128 consistentMastership = main.TRUE
1129 main.log.report(
1130 "Switch roles are consistent across all ONOS nodes" )
1131 else:
1132 for i in range( 1, numControllers + 1 ):
1133 mastership = eval( "ONOS" + str( i ) + "Mastership" )
1134 main.log.warn( "ONOS" + str( i ) + " roles: " +
1135 json.dumps( json.loads( mastership ),
1136 sort_keys=True,
1137 indent=4,
1138 separators=( ',', ': ' ) ) )
1139 consistentMastership = main.FALSE
1140 utilities.assert_equals(
1141 expect=main.TRUE,
1142 actual=consistentMastership,
1143 onpass="Switch roles are consistent across all ONOS nodes",
1144 onfail="ONOS nodes have different views of switch roles" )
1145
1146 description2 = "Compare switch roles from before failure"
1147 main.step( description2 )
1148
1149 currentJson = json.loads( ONOS1Mastership )
1150 oldJson = json.loads( mastershipState )
1151 mastershipCheck = main.TRUE
1152 for i in range( 1, 29 ):
1153 switchDPID = str(
1154 main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
1155
1156 current = [ switch[ 'master' ] for switch in currentJson
1157 if switchDPID in switch[ 'id' ] ]
1158 old = [ switch[ 'master' ] for switch in oldJson
1159 if switchDPID in switch[ 'id' ] ]
1160 if current == old:
1161 mastershipCheck = mastershipCheck and main.TRUE
1162 else:
1163 main.log.warn( "Mastership of switch %s changed" % switchDPID )
1164 mastershipCheck = main.FALSE
1165 if mastershipCheck == main.TRUE:
1166 main.log.report( "Mastership of Switches was not changed" )
1167 utilities.assert_equals(
1168 expect=main.TRUE,
1169 actual=mastershipCheck,
1170 onpass="Mastership of Switches was not changed",
1171 onfail="Mastership of some switches changed" )
1172 mastershipCheck = mastershipCheck and consistentMastership
1173
1174 main.step( "Get the intents and compare across all nodes" )
1175 ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
1176 ONOS2Intents = main.ONOScli2.intents( jsonFormat=True )
1177 ONOS3Intents = main.ONOScli3.intents( jsonFormat=True )
1178 ONOS4Intents = main.ONOScli4.intents( jsonFormat=True )
1179 ONOS5Intents = main.ONOScli5.intents( jsonFormat=True )
1180 ONOS6Intents = main.ONOScli6.intents( jsonFormat=True )
1181 ONOS7Intents = main.ONOScli7.intents( jsonFormat=True )
1182 intentCheck = main.FALSE
1183 if "Error" in ONOS1Intents or not ONOS1Intents\
1184 or "Error" in ONOS2Intents or not ONOS2Intents\
1185 or "Error" in ONOS3Intents or not ONOS3Intents\
1186 or "Error" in ONOS4Intents or not ONOS4Intents\
1187 or "Error" in ONOS5Intents or not ONOS5Intents\
1188 or "Error" in ONOS6Intents or not ONOS6Intents\
1189 or "Error" in ONOS7Intents or not ONOS7Intents:
1190 main.log.report( "Error in getting ONOS intents" )
1191 main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
1192 main.log.warn( "ONOS2 intents response: " + repr( ONOS2Intents ) )
1193 main.log.warn( "ONOS3 intents response: " + repr( ONOS3Intents ) )
1194 main.log.warn( "ONOS4 intents response: " + repr( ONOS4Intents ) )
1195 main.log.warn( "ONOS5 intents response: " + repr( ONOS5Intents ) )
1196 main.log.warn( "ONOS6 intents response: " + repr( ONOS6Intents ) )
1197 main.log.warn( "ONOS7 intents response: " + repr( ONOS7Intents ) )
1198 elif ONOS1Intents == ONOS2Intents\
1199 and ONOS1Intents == ONOS3Intents\
1200 and ONOS1Intents == ONOS4Intents\
1201 and ONOS1Intents == ONOS5Intents\
1202 and ONOS1Intents == ONOS6Intents\
1203 and ONOS1Intents == ONOS7Intents:
1204 intentCheck = main.TRUE
1205 main.log.report( "Intents are consistent across all ONOS nodes" )
1206 else:
1207 for i in range( 1, numControllers + 1 ):
1208 intents = eval( "ONOS" + str( i ) + "Intents" )
1209 main.log.warn( "ONOS" + str( i ) + " intents: " +
1210 json.dumps( json.loads( ONOS1Intents ),
1211 sort_keys=True,
1212 indent=4,
1213 separators=( ',', ': ' ) ) )
1214 utilities.assert_equals(
1215 expect=main.TRUE,
1216 actual=intentCheck,
1217 onpass="Intents are consistent across all ONOS nodes",
1218 onfail="ONOS nodes have different views of intents" )
1219 # Print the intent states
1220 intents = []
1221 intents.append( ONOS1Intents )
1222 intents.append( ONOS2Intents )
1223 intents.append( ONOS3Intents )
1224 intents.append( ONOS4Intents )
1225 intents.append( ONOS5Intents )
1226 intents.append( ONOS6Intents )
1227 intents.append( ONOS7Intents )
1228 intentStates = []
1229 for node in intents: # Iter through ONOS nodes
1230 nodeStates = []
1231 for intent in json.loads( node ): # Iter through intents of a node
1232 nodeStates.append( intent[ 'state' ] )
1233 intentStates.append( nodeStates )
1234 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
1235 main.log.info( dict( out ) )
1236 # NOTE: Hazelcast has no durability, so intents are lost across system
1237 # restarts
1238 main.step( "Compare current intents with intents before the failure" )
1239 # NOTE: this requires case 5 to pass for intentState to be set.
1240 # maybe we should stop the test if that fails?
1241 sameIntents = main.TRUE
1242 if intentState and intentState == ONOS1Intents:
1243 sameIntents = main.TRUE
1244 main.log.report( "Intents are consistent with before failure" )
1245 # TODO: possibly the states have changed? we may need to figure out
1246 # what the aceptable states are
1247 else:
1248 try:
1249 main.log.warn( "ONOS1 intents: " )
1250 print json.dumps( json.loads( ONOS1Intents ),
1251 sort_keys=True, indent=4,
1252 separators=( ',', ': ' ) )
1253 except:
1254 pass
1255 sameIntents = main.FALSE
1256 utilities.assert_equals(
1257 expect=main.TRUE,
1258 actual=sameIntents,
1259 onpass="Intents are consistent with before failure",
1260 onfail="The Intents changed during failure" )
1261 intentCheck = intentCheck and sameIntents
1262
1263 main.step( "Get the OF Table entries and compare to before " +
1264 "component failure" )
1265 FlowTables = main.TRUE
1266 flows2 = []
1267 for i in range( 28 ):
1268 main.log.info( "Checking flow table on s" + str( i + 1 ) )
1269 tmpFlows = main.Mininet2.getFlowTable( 1.3, "s" + str( i + 1 ) )
1270 flows2.append( tmpFlows )
1271 tempResult = main.Mininet2.flowComp(
1272 flow1=flows[ i ],
1273 flow2=tmpFlows )
1274 FlowTables = FlowTables and tempResult
1275 if FlowTables == main.FALSE:
1276 main.log.info( "Differences in flow table for switch: s" +
1277 str( i + 1 ) )
1278 if FlowTables == main.TRUE:
1279 main.log.report( "No changes were found in the flow tables" )
1280 utilities.assert_equals(
1281 expect=main.TRUE,
1282 actual=FlowTables,
1283 onpass="No changes were found in the flow tables",
1284 onfail="Changes were found in the flow tables" )
1285
1286 main.step( "Check the continuous pings to ensure that no packets " +
1287 "were dropped during component failure" )
1288 # FIXME: This check is always failing. Investigate cause
1289 # NOTE: this may be something to do with file permsissions
1290 # or slight change in format
1291 main.Mininet2.pingKill(
1292 main.params[ 'TESTONUSER' ],
1293 main.params[ 'TESTONIP' ] )
1294 LossInPings = main.FALSE
1295 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
1296 for i in range( 8, 18 ):
1297 main.log.info(
1298 "Checking for a loss in pings along flow from s" +
1299 str( i ) )
1300 LossInPings = main.Mininet2.checkForLoss(
1301 "/tmp/ping.h" +
1302 str( i ) ) or LossInPings
1303 if LossInPings == main.TRUE:
1304 main.log.info( "Loss in ping detected" )
1305 elif LossInPings == main.ERROR:
1306 main.log.info( "There are multiple mininet process running" )
1307 elif LossInPings == main.FALSE:
1308 main.log.info( "No Loss in the pings" )
1309 main.log.report( "No loss of dataplane connectivity" )
1310 utilities.assert_equals(
1311 expect=main.FALSE,
1312 actual=LossInPings,
1313 onpass="No Loss of connectivity",
1314 onfail="Loss of dataplane connectivity detected" )
1315
1316 # Test of LeadershipElection
1317 # FIXME Update this for network partition case
1318 # NOTE: this only works for the sanity test. In case of failures,
1319 # leader will likely change
1320 leader = ONOS1Ip
1321 leaderResult = main.TRUE
1322 for controller in range( 1, numControllers + 1 ):
1323 # loop through ONOScli handlers
1324 node = getattr( main, ( 'ONOScli' + str( controller ) ) )
1325 leaderN = node.electionTestLeader()
1326 # verify leader is ONOS1
1327 if leaderN == leader:
1328 # all is well
1329 # NOTE: In failure scenario, this could be a new node, maybe
1330 # check != ONOS1
1331 pass
1332 elif leaderN == main.FALSE:
1333 # error in response
1334 main.log.report( "Something is wrong with " +
1335 "electionTestLeader function," +
1336 " check the error logs" )
1337 leaderResult = main.FALSE
1338 elif leader != leaderN:
1339 leaderResult = main.FALSE
1340 main.log.report( "ONOS" + str( controller ) + " sees " +
1341 str( leaderN ) +
1342 " as the leader of the election app. " +
1343 "Leader should be " + str( leader ) )
1344 if leaderResult:
1345 main.log.report( "Leadership election tests passed( consistent " +
1346 "view of leader across listeners and a new " +
1347 "leader was re-elected if applicable )" )
1348 utilities.assert_equals(
1349 expect=main.TRUE,
1350 actual=leaderResult,
1351 onpass="Leadership election passed",
1352 onfail="Something went wrong with Leadership election" )
1353
1354 result = mastershipCheck and intentCheck and FlowTables and\
1355 ( not LossInPings ) and rolesNotNull and leaderResult
1356 result = int( result )
1357 if result == main.TRUE:
1358 main.log.report( "Constant State Tests Passed" )
1359 utilities.assert_equals( expect=main.TRUE, actual=result,
1360 onpass="Constant State Tests Passed",
1361 onfail="Constant state tests failed" )
1362
1363 def CASE8( self, main ):
1364 """
1365 Compare topo
1366 """
1367 import sys
1368 # FIXME add this path to params
1369 sys.path.append( "/home/admin/sts" )
1370 # assumes that sts is already in you PYTHONPATH
1371 from sts.topology.teston_topology import TestONTopology
1372 import json
1373 import time
1374
1375 description = "Compare ONOS Topology view to Mininet topology"
1376 main.case( description )
1377 main.log.report( description )
1378 main.step( "Create TestONTopology object" )
1379 ctrls = []
1380 count = 1
1381 while True:
1382 temp = ()
1383 if ( 'ip' + str( count ) ) in main.params[ 'CTRL' ]:
1384 temp = temp + ( getattr( main, ( 'ONOS' + str( count ) ) ), )
1385 temp = temp + ( "ONOS" + str( count ), )
1386 temp = temp + ( main.params[ 'CTRL' ][ 'ip' + str( count ) ], )
1387 temp = temp + \
1388 ( eval( main.params[ 'CTRL' ][ 'port' + str( count ) ] ), )
1389 ctrls.append( temp )
1390 count = count + 1
1391 else:
1392 break
1393 MNTopo = TestONTopology(
1394 main.Mininet1,
1395 ctrls ) # can also add Intent API info for intent operations
1396
1397 main.step( "Comparing ONOS topology to MN" )
1398 devicesResults = main.TRUE
1399 portsResults = main.TRUE
1400 linksResults = main.TRUE
1401 topoResult = main.FALSE
1402 elapsed = 0
1403 count = 0
1404 main.step( "Collecting topology information from ONOS" )
1405 startTime = time.time()
1406 # Give time for Gossip to work
1407 while topoResult == main.FALSE and elapsed < 60:
1408 count = count + 1
1409 if count > 1:
1410 # TODO: Depricate STS usage
1411 MNTopo = TestONTopology(
1412 main.Mininet1,
1413 ctrls )
1414 cliStart = time.time()
1415 devices = []
1416 devices.append( main.ONOScli1.devices() )
1417 devices.append( main.ONOScli2.devices() )
1418 devices.append( main.ONOScli3.devices() )
1419 devices.append( main.ONOScli4.devices() )
1420 devices.append( main.ONOScli5.devices() )
1421 devices.append( main.ONOScli6.devices() )
1422 devices.append( main.ONOScli7.devices() )
1423 hosts = []
1424 hosts.append( json.loads( main.ONOScli1.hosts() ) )
1425 hosts.append( json.loads( main.ONOScli2.hosts() ) )
1426 hosts.append( json.loads( main.ONOScli3.hosts() ) )
1427 hosts.append( json.loads( main.ONOScli4.hosts() ) )
1428 hosts.append( json.loads( main.ONOScli5.hosts() ) )
1429 hosts.append( json.loads( main.ONOScli6.hosts() ) )
1430 hosts.append( json.loads( main.ONOScli7.hosts() ) )
1431 for controller in range( 0, len( hosts ) ):
1432 controllerStr = str( controller + 1 )
1433 for host in hosts[ controller ]:
Jon Hallfeff3082015-05-19 10:23:26 -07001434 if host[ 'ipAddresses' ] == []:
Jon Hall63604932015-02-26 17:09:50 -08001435 main.log.error(
1436 "DEBUG:Error with host ips on controller" +
1437 controllerStr + ": " + str( host ) )
1438 ports = []
1439 ports.append( main.ONOScli1.ports() )
1440 ports.append( main.ONOScli2.ports() )
1441 ports.append( main.ONOScli3.ports() )
1442 ports.append( main.ONOScli4.ports() )
1443 ports.append( main.ONOScli5.ports() )
1444 ports.append( main.ONOScli6.ports() )
1445 ports.append( main.ONOScli7.ports() )
1446 links = []
1447 links.append( main.ONOScli1.links() )
1448 links.append( main.ONOScli2.links() )
1449 links.append( main.ONOScli3.links() )
1450 links.append( main.ONOScli4.links() )
1451 links.append( main.ONOScli5.links() )
1452 links.append( main.ONOScli6.links() )
1453 links.append( main.ONOScli7.links() )
1454 clusters = []
1455 clusters.append( main.ONOScli1.clusters() )
1456 clusters.append( main.ONOScli2.clusters() )
1457 clusters.append( main.ONOScli3.clusters() )
1458 clusters.append( main.ONOScli4.clusters() )
1459 clusters.append( main.ONOScli5.clusters() )
1460 clusters.append( main.ONOScli6.clusters() )
1461 clusters.append( main.ONOScli7.clusters() )
1462
1463 elapsed = time.time() - startTime
1464 cliTime = time.time() - cliStart
1465 print "CLI time: " + str( cliTime )
1466
1467 for controller in range( numControllers ):
1468 controllerStr = str( controller + 1 )
1469 if devices[ controller ] or "Error" not in devices[
1470 controller ]:
1471 currentDevicesResult = main.Mininet1.compareSwitches(
1472 MNTopo,
1473 json.loads(
1474 devices[ controller ] ) )
1475 else:
1476 currentDevicesResult = main.FALSE
1477 utilities.assert_equals( expect=main.TRUE,
1478 actual=currentDevicesResult,
1479 onpass="ONOS" + controllerStr +
1480 " Switches view is correct",
1481 onfail="ONOS" + controllerStr +
1482 " Switches view is incorrect" )
1483
1484 if ports[ controller ] or "Error" not in ports[ controller ]:
1485 currentPortsResult = main.Mininet1.comparePorts(
1486 MNTopo,
1487 json.loads(
1488 ports[ controller ] ) )
1489 else:
1490 currentPortsResult = main.FALSE
1491 utilities.assert_equals( expect=main.TRUE,
1492 actual=currentPortsResult,
1493 onpass="ONOS" + controllerStr +
1494 " ports view is correct",
1495 onfail="ONOS" + controllerStr +
1496 " ports view is incorrect" )
1497
1498 if links[ controller ] or "Error" not in links[ controller ]:
1499 currentLinksResult = main.Mininet1.compareLinks(
1500 MNTopo,
1501 json.loads(
1502 links[ controller ] ) )
1503 else:
1504 currentLinksResult = main.FALSE
1505 utilities.assert_equals( expect=main.TRUE,
1506 actual=currentLinksResult,
1507 onpass="ONOS" + controllerStr +
1508 " links view is correct",
1509 onfail="ONOS" + controllerStr +
1510 " links view is incorrect" )
1511 devicesResults = devicesResults and currentDevicesResult
1512 portsResults = portsResults and currentPortsResult
1513 linksResults = linksResults and currentLinksResult
1514
1515 # Compare json objects for hosts and dataplane clusters
1516
1517 # hosts
1518 consistentHostsResult = main.TRUE
1519 for controller in range( len( hosts ) ):
1520 controllerStr = str( controller + 1 )
1521 if "Error" not in hosts[ controller ]:
1522 if hosts[ controller ] == hosts[ 0 ]:
1523 continue
1524 else: # hosts not consistent
1525 main.log.report( "hosts from ONOS" + controllerStr +
1526 " is inconsistent with ONOS1" )
1527 main.log.warn( repr( hosts[ controller ] ) )
1528 consistentHostsResult = main.FALSE
1529
1530 else:
1531 main.log.report( "Error in getting ONOS hosts from ONOS" +
1532 controllerStr )
1533 consistentHostsResult = main.FALSE
1534 main.log.warn( "ONOS" + controllerStr +
1535 " hosts response: " +
1536 repr( hosts[ controller ] ) )
1537 utilities.assert_equals(
1538 expect=main.TRUE,
1539 actual=consistentHostsResult,
1540 onpass="Hosts view is consistent across all ONOS nodes",
1541 onfail="ONOS nodes have different views of hosts" )
1542
1543 # Strongly connected clusters of devices
1544 consistentClustersResult = main.TRUE
1545 for controller in range( len( clusters ) ):
1546 controllerStr = str( controller + 1 )
1547 if "Error" not in clusters[ controller ]:
1548 if clusters[ controller ] == clusters[ 0 ]:
1549 continue
1550 else: # clusters not consistent
1551 main.log.report( "clusters from ONOS" +
1552 controllerStr +
1553 " is inconsistent with ONOS1" )
1554 consistentClustersResult = main.FALSE
1555
1556 else:
1557 main.log.report( "Error in getting dataplane clusters " +
1558 "from ONOS" + controllerStr )
1559 consistentClustersResult = main.FALSE
1560 main.log.warn( "ONOS" + controllerStr +
1561 " clusters response: " +
1562 repr( clusters[ controller ] ) )
1563 utilities.assert_equals(
1564 expect=main.TRUE,
1565 actual=consistentClustersResult,
1566 onpass="Clusters view is consistent across all ONOS nodes",
1567 onfail="ONOS nodes have different views of clusters" )
1568 # there should always only be one cluster
1569 numClusters = len( json.loads( clusters[ 0 ] ) )
1570 utilities.assert_equals(
1571 expect=1,
1572 actual=numClusters,
1573 onpass="ONOS shows 1 SCC",
1574 onfail="ONOS shows " +
1575 str( numClusters ) +
1576 " SCCs" )
1577
1578 topoResult = ( devicesResults and portsResults and linksResults
1579 and consistentHostsResult
1580 and consistentClustersResult )
1581
1582 topoResult = topoResult and int( count <= 2 )
1583 note = "note it takes about " + str( int( cliTime ) ) + \
1584 " seconds for the test to make all the cli calls to fetch " +\
1585 "the topology from each ONOS instance"
1586 main.log.info(
1587 "Very crass estimate for topology discovery/convergence( " +
1588 str( note ) + " ): " + str( elapsed ) + " seconds, " +
1589 str( count ) + " tries" )
1590 utilities.assert_equals( expect=main.TRUE, actual=topoResult,
1591 onpass="Topology Check Test successful",
1592 onfail="Topology Check Test NOT successful" )
1593 if topoResult == main.TRUE:
1594 main.log.report( "ONOS topology view matches Mininet topology" )
1595
1596 def CASE9( self, main ):
1597 """
1598 Link s3-s28 down
1599 """
1600 import time
1601 # NOTE: You should probably run a topology check after this
1602
1603 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
1604
1605 description = "Turn off a link to ensure that Link Discovery " +\
1606 "is working properly"
1607 main.log.report( description )
1608 main.case( description )
1609
1610 main.step( "Kill Link between s3 and s28" )
1611 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
1612 main.log.info(
1613 "Waiting " +
1614 str( linkSleep ) +
1615 " seconds for link down to be discovered" )
1616 time.sleep( linkSleep )
1617 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
1618 onpass="Link down succesful",
1619 onfail="Failed to bring link down" )
1620 # TODO do some sort of check here
1621
1622 def CASE10( self, main ):
1623 """
1624 Link s3-s28 up
1625 """
1626 import time
1627 # NOTE: You should probably run a topology check after this
1628
1629 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
1630
1631 description = "Restore a link to ensure that Link Discovery is " + \
1632 "working properly"
1633 main.log.report( description )
1634 main.case( description )
1635
1636 main.step( "Bring link between s3 and s28 back up" )
1637 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
1638 main.log.info(
1639 "Waiting " +
1640 str( linkSleep ) +
1641 " seconds for link up to be discovered" )
1642 time.sleep( linkSleep )
1643 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
1644 onpass="Link up succesful",
1645 onfail="Failed to bring link up" )
1646 # TODO do some sort of check here
1647
1648 def CASE11( self, main ):
1649 """
1650 Switch Down
1651 """
1652 # NOTE: You should probably run a topology check after this
1653 import time
1654
1655 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
1656
1657 description = "Killing a switch to ensure it is discovered correctly"
1658 main.log.report( description )
1659 main.case( description )
1660 switch = main.params[ 'kill' ][ 'switch' ]
1661 switchDPID = main.params[ 'kill' ][ 'dpid' ]
1662
1663 # TODO: Make this switch parameterizable
1664 main.step( "Kill " + switch )
1665 main.log.report( "Deleting " + switch )
1666 main.Mininet1.delSwitch( switch )
1667 main.log.info( "Waiting " + str( switchSleep ) +
1668 " seconds for switch down to be discovered" )
1669 time.sleep( switchSleep )
1670 device = main.ONOScli1.getDevice( dpid=switchDPID )
1671 # Peek at the deleted switch
1672 main.log.warn( str( device ) )
1673 result = main.FALSE
1674 if device and device[ 'available' ] is False:
1675 result = main.TRUE
1676 utilities.assert_equals( expect=main.TRUE, actual=result,
1677 onpass="Kill switch succesful",
1678 onfail="Failed to kill switch?" )
1679
1680 def CASE12( self, main ):
1681 """
1682 Switch Up
1683 """
1684 # NOTE: You should probably run a topology check after this
1685 import time
1686
1687 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
1688 switch = main.params[ 'kill' ][ 'switch' ]
1689 switchDPID = main.params[ 'kill' ][ 'dpid' ]
1690 links = main.params[ 'kill' ][ 'links' ].split()
1691 description = "Adding a switch to ensure it is discovered correctly"
1692 main.log.report( description )
1693 main.case( description )
1694
1695 main.step( "Add back " + switch )
1696 main.log.report( "Adding back " + switch )
1697 main.Mininet1.addSwitch( switch, dpid=switchDPID )
1698 for peer in links:
1699 main.Mininet1.addLink( switch, peer )
1700 main.Mininet1.assignSwController(
1701 sw=switch.split( 's' )[ 1 ],
1702 count=numControllers,
1703 ip1=ONOS1Ip,
1704 port1=ONOS1Port,
1705 ip2=ONOS2Ip,
1706 port2=ONOS2Port,
1707 ip3=ONOS3Ip,
1708 port3=ONOS3Port,
1709 ip4=ONOS4Ip,
1710 port4=ONOS4Port,
1711 ip5=ONOS5Ip,
1712 port5=ONOS5Port,
1713 ip6=ONOS6Ip,
1714 port6=ONOS6Port,
1715 ip7=ONOS7Ip,
1716 port7=ONOS7Port )
1717 main.log.info(
1718 "Waiting " +
1719 str( switchSleep ) +
1720 " seconds for switch up to be discovered" )
1721 time.sleep( switchSleep )
1722 device = main.ONOScli1.getDevice( dpid=switchDPID )
1723 # Peek at the deleted switch
1724 main.log.warn( str( device ) )
1725 result = main.FALSE
1726 if device and device[ 'available' ]:
1727 result = main.TRUE
1728 utilities.assert_equals( expect=main.TRUE, actual=result,
1729 onpass="add switch succesful",
1730 onfail="Failed to add switch?" )
1731
1732 def CASE13( self, main ):
1733 """
1734 Clean up
1735 """
1736 import os
1737 import time
1738 # TODO: make use of this elsewhere
1739 ips = []
1740 ips.append( ONOS1Ip )
1741 ips.append( ONOS2Ip )
1742 ips.append( ONOS3Ip )
1743 ips.append( ONOS4Ip )
1744 ips.append( ONOS5Ip )
1745 ips.append( ONOS6Ip )
1746 ips.append( ONOS7Ip )
1747
1748 # printing colors to terminal
1749 colors = {}
1750 colors[ 'cyan' ] = '\033[96m'
1751 colors[ 'purple' ] = '\033[95m'
1752 colors[ 'blue' ] = '\033[94m'
1753 colors[ 'green' ] = '\033[92m'
1754 colors[ 'yellow' ] = '\033[93m'
1755 colors[ 'red' ] = '\033[91m'
1756 colors[ 'end' ] = '\033[0m'
1757 description = "Test Cleanup"
1758 main.log.report( description )
1759 main.case( description )
1760 main.step( "Killing tcpdumps" )
1761 main.Mininet2.stopTcpdump()
1762
1763 main.step( "Checking ONOS Logs for errors" )
1764 for i in range( 7 ):
1765 print colors[ 'purple' ] + "Checking logs for errors on " + \
1766 "ONOS" + str( i + 1 ) + ":" + colors[ 'end' ]
1767 print main.ONOSbench.checkLogs( ips[ i ] )
1768
1769 main.step( "Copying MN pcap and ONOS log files to test station" )
1770 testname = main.TEST
1771 teststationUser = main.params[ 'TESTONUSER' ]
1772 teststationIP = main.params[ 'TESTONIP' ]
1773 # NOTE: MN Pcap file is being saved to ~/packet_captures
1774 # scp this file as MN and TestON aren't necessarily the same vm
1775 # FIXME: scp
1776 # mn files
1777 # TODO: Load these from params
1778 # NOTE: must end in /
1779 logFolder = "/opt/onos/log/"
1780 logFiles = [ "karaf.log", "karaf.log.1" ]
1781 # NOTE: must end in /
1782 dstDir = "~/packet_captures/"
1783 for f in logFiles:
1784 for i in range( 7 ):
1785 main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
1786 logFolder + f + " " +
1787 teststationUser + "@" +
1788 teststationIP + ":" +
1789 dstDir + str( testname ) +
1790 "-ONOS" + str( i + 1 ) + "-" +
1791 f )
1792 # std*.log's
1793 # NOTE: must end in /
1794 logFolder = "/opt/onos/var/"
1795 logFiles = [ "stderr.log", "stdout.log" ]
1796 # NOTE: must end in /
1797 dstDir = "~/packet_captures/"
1798 for f in logFiles:
1799 for i in range( 7 ):
1800 main.ONOSbench.handle.sendline( "scp sdn@" + ips[ i ] + ":" +
1801 logFolder + f + " " +
1802 teststationUser + "@" +
1803 teststationIP + ":" +
1804 dstDir + str( testname ) +
1805 "-ONOS" + str( i + 1 ) + "-" +
1806 f )
1807 # sleep so scp can finish
1808 time.sleep( 10 )
1809 main.step( "Packing and rotating pcap archives" )
1810 os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
1811
1812 # TODO: actually check something here
1813 utilities.assert_equals( expect=main.TRUE, actual=main.TRUE,
1814 onpass="Test cleanup successful",
1815 onfail="Test cleanup NOT successful" )
1816
1817 def CASE14( self, main ):
1818 """
1819 start election app on all onos nodes
1820 """
1821 leaderResult = main.TRUE
1822 # install app on onos 1
1823 main.log.info( "Install leadership election app" )
1824 main.ONOScli1.featureInstall( "onos-app-election" )
1825 # wait for election
1826 # check for leader
1827 leader = main.ONOScli1.electionTestLeader()
1828 # verify leader is ONOS1
1829 if leader == ONOS1Ip:
1830 # all is well
1831 pass
1832 elif leader is None:
1833 # No leader elected
1834 main.log.report( "No leader was elected" )
1835 leaderResult = main.FALSE
1836 elif leader == main.FALSE:
1837 # error in response
1838 # TODO: add check for "Command not found:" in the driver, this
1839 # means the app isn't loaded
1840 main.log.report( "Something is wrong with electionTestLeader" +
1841 " function, check the error logs" )
1842 leaderResult = main.FALSE
1843 else:
1844 # error in response
1845 main.log.report(
1846 "Unexpected response from electionTestLeader function:'" +
1847 str( leader ) +
1848 "'" )
1849 leaderResult = main.FALSE
1850
1851 # install on other nodes and check for leader.
1852 # Should be onos1 and each app should show the same leader
1853 for controller in range( 2, numControllers + 1 ):
1854 # loop through ONOScli handlers
1855 node = getattr( main, ( 'ONOScli' + str( controller ) ) )
1856 node.featureInstall( "onos-app-election" )
1857 leaderN = node.electionTestLeader()
1858 # verify leader is ONOS1
1859 if leaderN == ONOS1Ip:
1860 # all is well
1861 pass
1862 elif leaderN == main.FALSE:
1863 # error in response
1864 # TODO: add check for "Command not found:" in the driver, this
1865 # means the app isn't loaded
1866 main.log.report( "Something is wrong with " +
1867 "electionTestLeader function, check the" +
1868 " error logs" )
1869 leaderResult = main.FALSE
1870 elif leader != leaderN:
1871 leaderResult = main.FALSE
1872 main.log.report( "ONOS" + str( controller ) + " sees " +
1873 str( leaderN ) +
1874 " as the leader of the election app. Leader" +
1875 " should be " +
1876 str( leader ) )
1877 if leaderResult:
1878 main.log.report( "Leadership election tests passed( consistent " +
1879 "view of leader across listeners and a leader " +
1880 "was elected )" )
1881 utilities.assert_equals(
1882 expect=main.TRUE,
1883 actual=leaderResult,
1884 onpass="Leadership election passed",
1885 onfail="Something went wrong with Leadership election" )
1886
1887 def CASE15( self, main ):
1888 """
1889 Check that Leadership Election is still functional
1890 """
1891 leaderResult = main.TRUE
1892 description = "Check that Leadership Election is still functional"
1893 main.log.report( description )
1894 main.case( description )
1895 main.step( "Find current leader and withdraw" )
1896 leader = main.ONOScli1.electionTestLeader()
1897 withdrawResult = main.FALSE
1898 if leader == ONOS1Ip:
1899 oldLeader = getattr( main, "ONOScli1" )
1900 elif leader == ONOS2Ip:
1901 oldLeader = getattr( main, "ONOScli2" )
1902 elif leader == ONOS3Ip:
1903 oldLeader = getattr( main, "ONOScli3" )
1904 elif leader == ONOS4Ip:
1905 oldLeader = getattr( main, "ONOScli4" )
1906 elif leader == ONOS5Ip:
1907 oldLeader = getattr( main, "ONOScli5" )
1908 elif leader == ONOS6Ip:
1909 oldLeader = getattr( main, "ONOScli6" )
1910 elif leader == ONOS7Ip:
1911 oldLeader = getattr( main, "ONOScli7" )
1912 elif leader is None or leader == main.FALSE:
1913 main.log.report(
1914 "Leader for the election app should be an ONOS node," +
1915 "instead got '" +
1916 str( leader ) +
1917 "'" )
1918 leaderResult = main.FALSE
1919 withdrawResult = oldLeader.electionTestWithdraw()
1920 utilities.assert_equals(
1921 expect=main.TRUE,
1922 actual=withdrawResult,
1923 onpass="App was withdrawn from election",
1924 onfail="App was not withdrawn from election" )
1925
1926 main.step( "Make sure new leader is elected" )
1927 leaderList = []
1928 for controller in range( 1, numControllers + 1 ):
1929 # loop through ONOScli handlers
1930 node = getattr( main, ( 'ONOScli' + str( controller ) ) )
1931 leaderList.append( node.electionTestLeader() )
1932 for leaderN in leaderList:
1933 if leaderN == leader:
1934 main.log.report(
1935 "ONOS" +
1936 str( controller ) +
1937 " still sees " +
1938 str( leader ) +
1939 " as leader after they withdrew" )
1940 leaderResult = main.FALSE
1941 elif leaderN == main.FALSE:
1942 # error in response
1943 # TODO: add check for "Command not found:" in the driver, this
1944 # means the app isn't loaded
1945 main.log.report( "Something is wrong with " +
1946 "electionTestLeader function, " +
1947 "check the error logs" )
1948 leaderResult = main.FALSE
1949 consistentLeader = main.FALSE
1950 if len( set( leaderList ) ) == 1:
1951 main.log.info( "Each Election-app sees '" +
1952 str( leaderList[ 0 ] ) +
1953 "' as the leader" )
1954 consistentLeader = main.TRUE
1955 else:
1956 main.log.report(
1957 "Inconsistent responses for leader of Election-app:" )
1958 for n in range( len( leaderList ) ):
1959 main.log.report( "ONOS" + str( n + 1 ) + " response: " +
1960 str( leaderList[ n ] ) )
1961 if leaderResult:
1962 main.log.report( "Leadership election tests passed( consistent " +
1963 "view of leader across listeners and a new " +
1964 "leader was elected when the old leader " +
1965 "resigned )" )
1966 utilities.assert_equals(
1967 expect=main.TRUE,
1968 actual=leaderResult,
1969 onpass="Leadership election passed",
1970 onfail="Something went wrong with Leadership election" )
1971
1972 main.step( "Run for election on old leader( just so everyone "
1973 "is in the hat )" )
1974 runResult = oldLeader.electionTestRun()
1975 utilities.assert_equals(
1976 expect=main.TRUE,
1977 actual=runResult,
1978 onpass="App re-ran for election",
1979 onfail="App failed to run for election" )
1980 if consistentLeader == main.TRUE:
1981 afterRun = main.ONOScli1.electionTestLeader()
1982 # verify leader didn't just change
1983 if afterRun == leaderList[ 0 ]:
1984 leaderResult = main.TRUE
1985 else:
1986 leaderResult = main.FALSE
1987 # TODO: assert on run and withdraw results?
1988
1989 utilities.assert_equals(
1990 expect=main.TRUE,
1991 actual=leaderResult,
1992 onpass="Leadership election passed",
1993 onfail="Something went wrong with Leadership election after " +
1994 "the old leader re-ran for election" )
1995 def CASE16( self ):
1996 """
1997 """
1998 main.ONOScli1.handle.sendline( "sudo iptables -F" )
1999 main.ONOScli1.handle.expect( "\$" )
2000 main.ONOScli2.handle.sendline( "sudo iptables -F" )
2001 main.ONOScli2.handle.expect( "\$" )
2002 main.ONOScli3.handle.sendline( "sudo iptables -F" )
2003 main.ONOScli3.handle.expect( "\$" )
2004 main.ONOScli4.handle.sendline( "sudo iptables -F" )
2005 main.ONOScli4.handle.expect( "\$" )
2006 main.ONOScli5.handle.sendline( "sudo iptables -F" )
2007 main.ONOScli5.handle.expect( "\$" )
2008 main.ONOScli6.handle.sendline( "sudo iptables -F" )
2009 main.ONOScli6.handle.expect( "\$" )
2010 main.ONOScli7.handle.sendline( "sudo iptables -F" )
2011 main.ONOScli7.handle.expect( "\$" )
2012