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