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