blob: a7ecb532ebe0308a2178b61d718483afdfec3798 [file] [log] [blame]
Jon Hall5cf14d52015-07-16 12:15:19 -07001"""
2Description: This test is to determine if ONOS can handle
3 all of it's nodes restarting
4
5List of test cases:
6CASE1: Compile ONOS and push it to the test machines
7CASE2: Assign devices to controllers
8CASE21: Assign mastership to controllers
9CASE3: Assign intents
10CASE4: Ping across added host intents
11CASE5: Reading state of ONOS
12CASE6: The Failure case.
13CASE7: Check state after control plane failure
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: Install Distributed Primitives app
23CASE17: Check for basic functionality with distributed primitives
24"""
Jon Hall5cf14d52015-07-16 12:15:19 -070025class HAclusterRestart:
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 """
Jon Halle1a3b752015-07-22 13:02:46 -070048 import imp
Jon Hallf3d16e72015-12-16 17:45:08 -080049 import time
Jon Halla440e872016-03-31 15:15:50 -070050 import json
Jon Hall5cf14d52015-07-16 12:15:19 -070051 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
52 "initialization" )
53 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070054 main.caseExplanation = "Setup the test environment including " +\
Jon Hall5cf14d52015-07-16 12:15:19 -070055 "installing ONOS, starting Mininet and ONOS" +\
56 "cli sessions."
Jon Hall5cf14d52015-07-16 12:15:19 -070057
58 # load some variables from the params file
59 PULLCODE = False
60 if main.params[ 'Git' ] == 'True':
61 PULLCODE = True
62 gitBranch = main.params[ 'branch' ]
63 cellName = main.params[ 'ENV' ][ 'cellName' ]
64
Jon Halle1a3b752015-07-22 13:02:46 -070065 main.numCtrls = int( main.params[ 'num_controllers' ] )
Jon Hall5cf14d52015-07-16 12:15:19 -070066 if main.ONOSbench.maxNodes:
Jon Halle1a3b752015-07-22 13:02:46 -070067 if main.ONOSbench.maxNodes < main.numCtrls:
68 main.numCtrls = int( main.ONOSbench.maxNodes )
69 # set global variables
Jon Hall5cf14d52015-07-16 12:15:19 -070070 global ONOS1Port
71 global ONOS2Port
72 global ONOS3Port
73 global ONOS4Port
74 global ONOS5Port
75 global ONOS6Port
76 global ONOS7Port
77 # These are for csv plotting in jenkins
78 global labels
79 global data
80 labels = []
81 data = []
82
83 # FIXME: just get controller port from params?
84 # TODO: do we really need all these?
85 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
86 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
87 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
88 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
89 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
90 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
91 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
92
Jon Halle1a3b752015-07-22 13:02:46 -070093 try:
Jon Hall53c5e662016-04-13 16:06:56 -070094 from tests.HA.dependencies.HA import HA
Jon Hall41d39f12016-04-11 22:54:35 -070095 main.HA = HA()
Jon Halle1a3b752015-07-22 13:02:46 -070096 except Exception as e:
97 main.log.exception( e )
98 main.cleanup()
99 main.exit()
100
101 main.CLIs = []
102 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700103 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700104 for i in range( 1, main.numCtrls + 1 ):
105 try:
106 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
107 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
108 ipList.append( main.nodes[ -1 ].ip_address )
109 except AttributeError:
110 break
Jon Hall5cf14d52015-07-16 12:15:19 -0700111
112 main.step( "Create cell file" )
113 cellAppString = main.params[ 'ENV' ][ 'appString' ]
114 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
115 main.Mininet1.ip_address,
116 cellAppString, ipList )
117 main.step( "Applying cell variable to environment" )
118 cellResult = main.ONOSbench.setCell( cellName )
119 verifyResult = main.ONOSbench.verifyCell()
120
121 # FIXME:this is short term fix
122 main.log.info( "Removing raft logs" )
123 main.ONOSbench.onosRemoveRaftLogs()
124
125 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700126 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700127 main.ONOSbench.onosUninstall( node.ip_address )
128
129 # Make sure ONOS is DEAD
130 main.log.info( "Killing any ONOS processes" )
131 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700132 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700133 killed = main.ONOSbench.onosKill( node.ip_address )
134 killResults = killResults and killed
135
136 cleanInstallResult = main.TRUE
137 gitPullResult = main.TRUE
138
139 main.step( "Starting Mininet" )
140 # scp topo file to mininet
141 # TODO: move to params?
142 topoName = "obelisk.py"
143 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700144 main.ONOSbench.scp( main.Mininet1,
145 filePath + topoName,
146 main.Mininet1.home,
147 direction="to" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700148 mnResult = main.Mininet1.startNet()
Jon Hall5cf14d52015-07-16 12:15:19 -0700149 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
150 onpass="Mininet Started",
151 onfail="Error starting Mininet" )
152
153 main.step( "Git checkout and pull " + gitBranch )
154 if PULLCODE:
155 main.ONOSbench.gitCheckout( gitBranch )
156 gitPullResult = main.ONOSbench.gitPull()
157 # values of 1 or 3 are good
158 utilities.assert_lesser( expect=0, actual=gitPullResult,
159 onpass="Git pull successful",
160 onfail="Git pull failed" )
161 main.ONOSbench.getVersion( report=True )
162
163 main.step( "Using mvn clean install" )
164 cleanInstallResult = main.TRUE
165 if PULLCODE and gitPullResult == main.TRUE:
166 cleanInstallResult = main.ONOSbench.cleanInstall()
167 else:
168 main.log.warn( "Did not pull new code so skipping mvn " +
169 "clean install" )
170 utilities.assert_equals( expect=main.TRUE,
171 actual=cleanInstallResult,
172 onpass="MCI successful",
173 onfail="MCI failed" )
174 # GRAPHS
175 # NOTE: important params here:
176 # job = name of Jenkins job
177 # Plot Name = Plot-HA, only can be used if multiple plots
178 # index = The number of the graph under plot name
179 job = "HAclusterRestart"
180 plotName = "Plot-HA"
Jon Hall843f8bc2016-03-18 14:28:13 -0700181 index = "2"
Jon Hall5cf14d52015-07-16 12:15:19 -0700182 graphs = '<ac:structured-macro ac:name="html">\n'
183 graphs += '<ac:plain-text-body><![CDATA[\n'
184 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Halla9845df2016-01-15 14:55:58 -0800185 '/plot/' + plotName + '/getPlot?index=' + index +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700186 '&width=500&height=300"' +\
187 'noborder="0" width="500" height="300" scrolling="yes" ' +\
188 'seamless="seamless"></iframe>\n'
189 graphs += ']]></ac:plain-text-body>\n'
190 graphs += '</ac:structured-macro>\n'
Jon Hallf37d44d2017-05-24 10:37:30 -0700191 main.log.wiki( graphs )
Jon Hall5cf14d52015-07-16 12:15:19 -0700192
193 main.step( "Creating ONOS package" )
Jon Hallbd60ea02016-08-23 10:03:59 -0700194 packageResult = main.ONOSbench.buckBuild()
Jon Hall5cf14d52015-07-16 12:15:19 -0700195 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
196 onpass="ONOS package successful",
197 onfail="ONOS package failed" )
198
199 main.step( "Installing ONOS package" )
200 onosInstallResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700201 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700202 tmpResult = main.ONOSbench.onosInstall( options="-f",
203 node=node.ip_address )
204 onosInstallResult = onosInstallResult and tmpResult
205 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
206 onpass="ONOS install successful",
207 onfail="ONOS install failed" )
208
You Wangf5de25b2017-01-06 15:13:01 -0800209 main.step( "Set up ONOS secure SSH" )
210 secureSshResult = main.TRUE
211 for node in main.nodes:
212 secureSshResult = secureSshResult and main.ONOSbench.onosSecureSSH( node=node.ip_address )
213 utilities.assert_equals( expect=main.TRUE, actual=secureSshResult,
214 onpass="Test step PASS",
215 onfail="Test step FAIL" )
216
Jon Hall5cf14d52015-07-16 12:15:19 -0700217 main.step( "Checking if ONOS is up yet" )
218 for i in range( 2 ):
219 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700220 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700221 started = main.ONOSbench.isup( node.ip_address )
222 if not started:
Jon Hallc6793552016-01-19 14:18:37 -0800223 main.log.error( node.name + " hasn't started" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700224 onosIsupResult = onosIsupResult and started
225 if onosIsupResult == main.TRUE:
226 break
227 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
228 onpass="ONOS startup successful",
229 onfail="ONOS startup failed" )
230
Jon Hall6509dbf2016-06-21 17:01:17 -0700231 main.step( "Starting ONOS CLI sessions" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700232 cliResults = main.TRUE
233 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700234 for i in range( main.numCtrls ):
Jon Hallf37d44d2017-05-24 10:37:30 -0700235 t = main.Thread( target=main.CLIs[ i ].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -0700236 name="startOnosCli-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -0700237 args=[ main.nodes[ i ].ip_address ] )
Jon Hall5cf14d52015-07-16 12:15:19 -0700238 threads.append( t )
239 t.start()
240
241 for t in threads:
242 t.join()
243 cliResults = cliResults and t.result
244 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
245 onpass="ONOS cli startup successful",
246 onfail="ONOS cli startup failed" )
247
Jon Halla440e872016-03-31 15:15:50 -0700248 # Create a list of active nodes for use when some nodes are stopped
249 main.activeNodes = [ i for i in range( 0, len( main.CLIs ) ) ]
250
Jon Hall5cf14d52015-07-16 12:15:19 -0700251 if main.params[ 'tcpdump' ].lower() == "true":
252 main.step( "Start Packet Capture MN" )
253 main.Mininet2.startTcpdump(
254 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
255 + "-MN.pcap",
256 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
257 port=main.params[ 'MNtcpdump' ][ 'port' ] )
258
Jon Halla440e872016-03-31 15:15:50 -0700259 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -0700260 nodeResults = utilities.retry( main.HA.nodesCheck,
261 False,
Jon Hallf37d44d2017-05-24 10:37:30 -0700262 args=[ main.activeNodes ],
Jon Hall41d39f12016-04-11 22:54:35 -0700263 attempts=5 )
Jon Halla440e872016-03-31 15:15:50 -0700264
Jon Hall41d39f12016-04-11 22:54:35 -0700265 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Halla440e872016-03-31 15:15:50 -0700266 onpass="Nodes check successful",
267 onfail="Nodes check NOT successful" )
268
269 if not nodeResults:
Jon Hall7ac7bc32016-05-05 10:57:02 -0700270 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700271 cli = main.CLIs[ i ]
Jon Halla440e872016-03-31 15:15:50 -0700272 main.log.debug( "{} components not ACTIVE: \n{}".format(
273 cli.name,
274 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700275 main.log.error( "Failed to start ONOS, stopping test" )
276 main.cleanup()
277 main.exit()
278
Jon Hall172b7ba2016-04-07 18:12:20 -0700279 main.step( "Activate apps defined in the params file" )
280 # get data from the params
281 apps = main.params.get( 'apps' )
282 if apps:
Jon Hallf37d44d2017-05-24 10:37:30 -0700283 apps = apps.split( ',' )
Jon Hall172b7ba2016-04-07 18:12:20 -0700284 main.log.warn( apps )
285 activateResult = True
286 for app in apps:
287 main.CLIs[ 0 ].app( app, "Activate" )
288 # TODO: check this worked
289 time.sleep( 10 ) # wait for apps to activate
290 for app in apps:
291 state = main.CLIs[ 0 ].appStatus( app )
292 if state == "ACTIVE":
Jon Hall937bc812017-01-31 16:44:10 -0800293 activateResult = activateResult and True
Jon Hall172b7ba2016-04-07 18:12:20 -0700294 else:
295 main.log.error( "{} is in {} state".format( app, state ) )
Jon Hall937bc812017-01-31 16:44:10 -0800296 activateResult = False
Jon Hall172b7ba2016-04-07 18:12:20 -0700297 utilities.assert_equals( expect=True,
298 actual=activateResult,
299 onpass="Successfully activated apps",
300 onfail="Failed to activate apps" )
301 else:
302 main.log.warn( "No apps were specified to be loaded after startup" )
303
304 main.step( "Set ONOS configurations" )
305 config = main.params.get( 'ONOS_Configuration' )
306 if config:
307 main.log.debug( config )
308 checkResult = main.TRUE
309 for component in config:
Jon Hallf37d44d2017-05-24 10:37:30 -0700310 for setting in config[ component ]:
311 value = config[ component ][ setting ]
Jon Hall172b7ba2016-04-07 18:12:20 -0700312 check = main.CLIs[ 0 ].setCfg( component, setting, value )
313 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
314 checkResult = check and checkResult
315 utilities.assert_equals( expect=main.TRUE,
316 actual=checkResult,
317 onpass="Successfully set config",
318 onfail="Failed to set config" )
319 else:
320 main.log.warn( "No configurations were specified to be changed after startup" )
321
Jon Hall9d2dcad2016-04-08 10:15:20 -0700322 main.step( "App Ids check" )
323 appCheck = main.TRUE
324 threads = []
325 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700326 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall9d2dcad2016-04-08 10:15:20 -0700327 name="appToIDCheck-" + str( i ),
328 args=[] )
329 threads.append( t )
330 t.start()
331
332 for t in threads:
333 t.join()
334 appCheck = appCheck and t.result
335 if appCheck != main.TRUE:
Jon Hallf37d44d2017-05-24 10:37:30 -0700336 node = main.activeNodes[ 0 ]
337 main.log.warn( main.CLIs[ node ].apps() )
338 main.log.warn( main.CLIs[ node ].appIDs() )
Jon Hall9d2dcad2016-04-08 10:15:20 -0700339 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
340 onpass="App Ids seem to be correct",
341 onfail="Something is wrong with app Ids" )
342
Jon Hall5cf14d52015-07-16 12:15:19 -0700343 def CASE2( self, main ):
344 """
345 Assign devices to controllers
346 """
347 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700348 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700349 assert main, "main not defined"
350 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700351 assert main.CLIs, "main.CLIs not defined"
352 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700353 assert ONOS1Port, "ONOS1Port not defined"
354 assert ONOS2Port, "ONOS2Port not defined"
355 assert ONOS3Port, "ONOS3Port not defined"
356 assert ONOS4Port, "ONOS4Port not defined"
357 assert ONOS5Port, "ONOS5Port not defined"
358 assert ONOS6Port, "ONOS6Port not defined"
359 assert ONOS7Port, "ONOS7Port not defined"
360
361 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700362 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700363 "and check that an ONOS node becomes the " +\
364 "master of the device."
365 main.step( "Assign switches to controllers" )
366
367 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700368 for i in range( main.numCtrls ):
369 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700370 swList = []
371 for i in range( 1, 29 ):
372 swList.append( "s" + str( i ) )
373 main.Mininet1.assignSwController( sw=swList, ip=ipList )
374
375 mastershipCheck = main.TRUE
376 for i in range( 1, 29 ):
377 response = main.Mininet1.getSwController( "s" + str( i ) )
378 try:
379 main.log.info( str( response ) )
380 except Exception:
381 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700382 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700383 if re.search( "tcp:" + node.ip_address, response ):
384 mastershipCheck = mastershipCheck and main.TRUE
385 else:
386 main.log.error( "Error, node " + node.ip_address + " is " +
387 "not in the list of controllers s" +
388 str( i ) + " is connecting to." )
389 mastershipCheck = main.FALSE
390 utilities.assert_equals(
391 expect=main.TRUE,
392 actual=mastershipCheck,
393 onpass="Switch mastership assigned correctly",
394 onfail="Switches not assigned correctly to controllers" )
395
396 def CASE21( self, main ):
397 """
398 Assign mastership to controllers
399 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700400 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700401 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700402 assert main, "main not defined"
403 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700404 assert main.CLIs, "main.CLIs not defined"
405 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700406 assert ONOS1Port, "ONOS1Port not defined"
407 assert ONOS2Port, "ONOS2Port not defined"
408 assert ONOS3Port, "ONOS3Port not defined"
409 assert ONOS4Port, "ONOS4Port not defined"
410 assert ONOS5Port, "ONOS5Port not defined"
411 assert ONOS6Port, "ONOS6Port not defined"
412 assert ONOS7Port, "ONOS7Port not defined"
413
414 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700415 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700416 "device. Then manually assign" +\
417 " mastership to specific ONOS nodes using" +\
418 " 'device-role'"
419 main.step( "Assign mastership of switches to specific controllers" )
420 # Manually assign mastership to the controller we want
421 roleCall = main.TRUE
422
Jon Hallf37d44d2017-05-24 10:37:30 -0700423 ipList = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700424 deviceList = []
Jon Hallf37d44d2017-05-24 10:37:30 -0700425 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700426 try:
427 # Assign mastership to specific controllers. This assignment was
428 # determined for a 7 node cluser, but will work with any sized
429 # cluster
430 for i in range( 1, 29 ): # switches 1 through 28
431 # set up correct variables:
432 if i == 1:
433 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700434 ip = main.nodes[ c ].ip_address # ONOS1
Jon Halla440e872016-03-31 15:15:50 -0700435 deviceId = onosCli.getDevice( "1000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700436 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700437 c = 1 % main.numCtrls
438 ip = main.nodes[ c ].ip_address # ONOS2
Jon Halla440e872016-03-31 15:15:50 -0700439 deviceId = onosCli.getDevice( "2000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700440 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700441 c = 1 % main.numCtrls
442 ip = main.nodes[ c ].ip_address # ONOS2
Jon Halla440e872016-03-31 15:15:50 -0700443 deviceId = onosCli.getDevice( "3000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700444 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700445 c = 3 % main.numCtrls
446 ip = main.nodes[ c ].ip_address # ONOS4
Jon Halla440e872016-03-31 15:15:50 -0700447 deviceId = onosCli.getDevice( "3004" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700448 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700449 c = 2 % main.numCtrls
450 ip = main.nodes[ c ].ip_address # ONOS3
Jon Halla440e872016-03-31 15:15:50 -0700451 deviceId = onosCli.getDevice( "5000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700452 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700453 c = 2 % main.numCtrls
454 ip = main.nodes[ c ].ip_address # ONOS3
Jon Halla440e872016-03-31 15:15:50 -0700455 deviceId = onosCli.getDevice( "6000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700456 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700457 c = 5 % main.numCtrls
458 ip = main.nodes[ c ].ip_address # ONOS6
Jon Halla440e872016-03-31 15:15:50 -0700459 deviceId = onosCli.getDevice( "6007" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700460 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700461 c = 4 % main.numCtrls
462 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700463 dpid = '3' + str( i ).zfill( 3 )
Jon Halla440e872016-03-31 15:15:50 -0700464 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700465 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700466 c = 6 % main.numCtrls
467 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700468 dpid = '6' + str( i ).zfill( 3 )
Jon Halla440e872016-03-31 15:15:50 -0700469 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700470 elif i == 28:
471 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700472 ip = main.nodes[ c ].ip_address # ONOS1
Jon Halla440e872016-03-31 15:15:50 -0700473 deviceId = onosCli.getDevice( "2800" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700474 else:
475 main.log.error( "You didn't write an else statement for " +
476 "switch s" + str( i ) )
477 roleCall = main.FALSE
478 # Assign switch
479 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
480 # TODO: make this controller dynamic
Jon Halla440e872016-03-31 15:15:50 -0700481 roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
Jon Hall5cf14d52015-07-16 12:15:19 -0700482 ipList.append( ip )
483 deviceList.append( deviceId )
484 except ( AttributeError, AssertionError ):
485 main.log.exception( "Something is wrong with ONOS device view" )
Jon Halla440e872016-03-31 15:15:50 -0700486 main.log.info( onosCli.devices() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700487 utilities.assert_equals(
488 expect=main.TRUE,
489 actual=roleCall,
490 onpass="Re-assigned switch mastership to designated controller",
491 onfail="Something wrong with deviceRole calls" )
492
493 main.step( "Check mastership was correctly assigned" )
494 roleCheck = main.TRUE
495 # NOTE: This is due to the fact that device mastership change is not
496 # atomic and is actually a multi step process
497 time.sleep( 5 )
498 for i in range( len( ipList ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -0700499 ip = ipList[ i ]
500 deviceId = deviceList[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700501 # Check assignment
Jon Halla440e872016-03-31 15:15:50 -0700502 master = onosCli.getRole( deviceId ).get( 'master' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700503 if ip in master:
504 roleCheck = roleCheck and main.TRUE
505 else:
506 roleCheck = roleCheck and main.FALSE
507 main.log.error( "Error, controller " + ip + " is not" +
508 " master " + "of device " +
509 str( deviceId ) + ". Master is " +
510 repr( master ) + "." )
511 utilities.assert_equals(
512 expect=main.TRUE,
513 actual=roleCheck,
514 onpass="Switches were successfully reassigned to designated " +
515 "controller",
516 onfail="Switches were not successfully reassigned" )
517
518 def CASE3( self, main ):
519 """
520 Assign intents
521 """
522 import time
523 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700524 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700525 assert main, "main not defined"
526 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700527 assert main.CLIs, "main.CLIs not defined"
528 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700529 try:
530 labels
531 except NameError:
532 main.log.error( "labels not defined, setting to []" )
533 labels = []
534 try:
535 data
536 except NameError:
537 main.log.error( "data not defined, setting to []" )
538 data = []
539 # NOTE: we must reinstall intents until we have a persistant intent
540 # datastore!
541 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700542 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700543 "assign predetermined host-to-host intents." +\
544 " After installation, check that the intent" +\
545 " is distributed to all nodes and the state" +\
546 " is INSTALLED"
547
548 # install onos-app-fwd
549 main.step( "Install reactive forwarding app" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700550 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Halla440e872016-03-31 15:15:50 -0700551 installResults = onosCli.activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700552 utilities.assert_equals( expect=main.TRUE, actual=installResults,
553 onpass="Install fwd successful",
554 onfail="Install fwd failed" )
555
556 main.step( "Check app ids" )
557 appCheck = main.TRUE
558 threads = []
Jon Halla440e872016-03-31 15:15:50 -0700559 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700560 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700561 name="appToIDCheck-" + str( i ),
562 args=[] )
563 threads.append( t )
564 t.start()
565
566 for t in threads:
567 t.join()
568 appCheck = appCheck and t.result
569 if appCheck != main.TRUE:
Jon Halla440e872016-03-31 15:15:50 -0700570 main.log.warn( onosCli.apps() )
571 main.log.warn( onosCli.appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700572 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
573 onpass="App Ids seem to be correct",
574 onfail="Something is wrong with app Ids" )
575
576 main.step( "Discovering Hosts( Via pingall for now )" )
577 # FIXME: Once we have a host discovery mechanism, use that instead
578 # REACTIVE FWD test
579 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700580 passMsg = "Reactive Pingall test passed"
581 time1 = time.time()
582 pingResult = main.Mininet1.pingall()
583 time2 = time.time()
584 if not pingResult:
Jon Hallf37d44d2017-05-24 10:37:30 -0700585 main.log.warn( "First pingall failed. Trying again..." )
Jon Hall5cf14d52015-07-16 12:15:19 -0700586 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700587 passMsg += " on the second try"
588 utilities.assert_equals(
589 expect=main.TRUE,
590 actual=pingResult,
Jon Hallf37d44d2017-05-24 10:37:30 -0700591 onpass=passMsg,
Jon Hall96091e62015-09-21 17:34:17 -0700592 onfail="Reactive Pingall failed, " +
593 "one or more ping pairs failed" )
594 main.log.info( "Time for pingall: %2f seconds" %
595 ( time2 - time1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700596 # timeout for fwd flows
597 time.sleep( 11 )
598 # uninstall onos-app-fwd
599 main.step( "Uninstall reactive forwarding app" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700600 node = main.activeNodes[ 0 ]
601 uninstallResult = main.CLIs[ node ].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700602 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
603 onpass="Uninstall fwd successful",
604 onfail="Uninstall fwd failed" )
605
606 main.step( "Check app ids" )
607 threads = []
608 appCheck2 = main.TRUE
Jon Halla440e872016-03-31 15:15:50 -0700609 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700610 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700611 name="appToIDCheck-" + str( i ),
612 args=[] )
613 threads.append( t )
614 t.start()
615
616 for t in threads:
617 t.join()
618 appCheck2 = appCheck2 and t.result
619 if appCheck2 != main.TRUE:
Jon Hallf37d44d2017-05-24 10:37:30 -0700620 node = main.activeNodes[ 0 ]
621 main.log.warn( main.CLIs[ node ].apps() )
622 main.log.warn( main.CLIs[ node ].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700623 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
624 onpass="App Ids seem to be correct",
625 onfail="Something is wrong with app Ids" )
626
627 main.step( "Add host intents via cli" )
628 intentIds = []
Jon Hall6e709752016-02-01 13:38:46 -0800629 # TODO: move the host numbers to params
630 # Maybe look at all the paths we ping?
Jon Hall5cf14d52015-07-16 12:15:19 -0700631 intentAddResult = True
632 hostResult = main.TRUE
633 for i in range( 8, 18 ):
634 main.log.info( "Adding host intent between h" + str( i ) +
635 " and h" + str( i + 10 ) )
636 host1 = "00:00:00:00:00:" + \
637 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
638 host2 = "00:00:00:00:00:" + \
639 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
640 # NOTE: getHost can return None
Jon Halla440e872016-03-31 15:15:50 -0700641 host1Dict = onosCli.getHost( host1 )
642 host2Dict = onosCli.getHost( host2 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700643 host1Id = None
644 host2Id = None
645 if host1Dict and host2Dict:
646 host1Id = host1Dict.get( 'id', None )
647 host2Id = host2Dict.get( 'id', None )
648 if host1Id and host2Id:
Jon Halla440e872016-03-31 15:15:50 -0700649 nodeNum = ( i % len( main.activeNodes ) )
Jon Hallf37d44d2017-05-24 10:37:30 -0700650 node = main.activeNodes[ nodeNum ]
651 tmpId = main.CLIs[ node ].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700652 if tmpId:
653 main.log.info( "Added intent with id: " + tmpId )
654 intentIds.append( tmpId )
655 else:
656 main.log.error( "addHostIntent returned: " +
657 repr( tmpId ) )
658 else:
659 main.log.error( "Error, getHost() failed for h" + str( i ) +
660 " and/or h" + str( i + 10 ) )
Jon Hallf37d44d2017-05-24 10:37:30 -0700661 node = main.activeNodes[ 0 ]
662 hosts = main.CLIs[ node ].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700663 main.log.warn( "Hosts output: " )
664 try:
665 main.log.warn( json.dumps( json.loads( hosts ),
666 sort_keys=True,
667 indent=4,
668 separators=( ',', ': ' ) ) )
669 except ( ValueError, TypeError ):
670 main.log.warn( repr( hosts ) )
671 hostResult = main.FALSE
672 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
673 onpass="Found a host id for each host",
674 onfail="Error looking up host ids" )
675
676 intentStart = time.time()
Jon Halla440e872016-03-31 15:15:50 -0700677 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700678 main.log.info( "Submitted intents: " + str( intentIds ) )
679 main.log.info( "Intents in ONOS: " + str( onosIds ) )
680 for intent in intentIds:
681 if intent in onosIds:
682 pass # intent submitted is in onos
683 else:
684 intentAddResult = False
685 if intentAddResult:
686 intentStop = time.time()
687 else:
688 intentStop = None
689 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -0700690 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700691 intentStates = []
692 installedCheck = True
693 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
694 count = 0
695 try:
696 for intent in json.loads( intents ):
697 state = intent.get( 'state', None )
698 if "INSTALLED" not in state:
699 installedCheck = False
700 intentId = intent.get( 'id', None )
701 intentStates.append( ( intentId, state ) )
702 except ( ValueError, TypeError ):
703 main.log.exception( "Error parsing intents" )
704 # add submitted intents not in the store
705 tmplist = [ i for i, s in intentStates ]
706 missingIntents = False
707 for i in intentIds:
708 if i not in tmplist:
709 intentStates.append( ( i, " - " ) )
710 missingIntents = True
711 intentStates.sort()
712 for i, s in intentStates:
713 count += 1
714 main.log.info( "%-6s%-15s%-15s" %
715 ( str( count ), str( i ), str( s ) ) )
Jon Halla440e872016-03-31 15:15:50 -0700716 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700717 try:
718 missing = False
719 if leaders:
720 parsedLeaders = json.loads( leaders )
721 main.log.warn( json.dumps( parsedLeaders,
722 sort_keys=True,
723 indent=4,
724 separators=( ',', ': ' ) ) )
725 # check for all intent partitions
726 topics = []
727 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700728 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700729 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -0700730 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700731 for topic in topics:
732 if topic not in ONOStopics:
733 main.log.error( "Error: " + topic +
734 " not in leaders" )
735 missing = True
736 else:
737 main.log.error( "leaders() returned None" )
738 except ( ValueError, TypeError ):
739 main.log.exception( "Error parsing leaders" )
740 main.log.error( repr( leaders ) )
741 # Check all nodes
742 if missing:
Jon Halla440e872016-03-31 15:15:50 -0700743 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700744 response = main.CLIs[ i ].leaders( jsonFormat=False )
745 main.log.warn( str( main.CLIs[ i ].name ) + " leaders output: \n" +
Jon Hall5cf14d52015-07-16 12:15:19 -0700746 str( response ) )
747
Jon Halla440e872016-03-31 15:15:50 -0700748 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700749 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700750 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -0700751 parsedPartitions = json.loads( partitions )
752 main.log.warn( json.dumps( parsedPartitions,
753 sort_keys=True,
754 indent=4,
755 separators=( ',', ': ' ) ) )
756 # TODO check for a leader in all paritions
757 # TODO check for consistency among nodes
758 else:
759 main.log.error( "partitions() returned None" )
760 except ( ValueError, TypeError ):
761 main.log.exception( "Error parsing partitions" )
762 main.log.error( repr( partitions ) )
Jon Halla440e872016-03-31 15:15:50 -0700763 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700764 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700765 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -0700766 parsedPending = json.loads( pendingMap )
767 main.log.warn( json.dumps( parsedPending,
768 sort_keys=True,
769 indent=4,
770 separators=( ',', ': ' ) ) )
771 # TODO check something here?
772 else:
773 main.log.error( "pendingMap() returned None" )
774 except ( ValueError, TypeError ):
775 main.log.exception( "Error parsing pending map" )
776 main.log.error( repr( pendingMap ) )
777
778 intentAddResult = bool( intentAddResult and not missingIntents and
779 installedCheck )
780 if not intentAddResult:
781 main.log.error( "Error in pushing host intents to ONOS" )
782
783 main.step( "Intent Anti-Entropy dispersion" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700784 for j in range( 100 ):
Jon Hall5cf14d52015-07-16 12:15:19 -0700785 correct = True
786 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Halla440e872016-03-31 15:15:50 -0700787 for i in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700788 onosIds = []
Jon Hallf37d44d2017-05-24 10:37:30 -0700789 ids = main.CLIs[ i ].getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700790 onosIds.append( ids )
Jon Hallf37d44d2017-05-24 10:37:30 -0700791 main.log.debug( "Intents in " + main.CLIs[ i ].name + ": " +
Jon Hall5cf14d52015-07-16 12:15:19 -0700792 str( sorted( onosIds ) ) )
793 if sorted( ids ) != sorted( intentIds ):
794 main.log.warn( "Set of intent IDs doesn't match" )
795 correct = False
796 break
797 else:
Jon Hallf37d44d2017-05-24 10:37:30 -0700798 intents = json.loads( main.CLIs[ i ].intents() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700799 for intent in intents:
800 if intent[ 'state' ] != "INSTALLED":
801 main.log.warn( "Intent " + intent[ 'id' ] +
802 " is " + intent[ 'state' ] )
803 correct = False
804 break
805 if correct:
806 break
807 else:
Jon Hallf37d44d2017-05-24 10:37:30 -0700808 time.sleep( 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700809 if not intentStop:
810 intentStop = time.time()
811 global gossipTime
812 gossipTime = intentStop - intentStart
813 main.log.info( "It took about " + str( gossipTime ) +
814 " seconds for all intents to appear in each node" )
815 append = False
816 title = "Gossip Intents"
817 count = 1
818 while append is False:
819 curTitle = title + str( count )
820 if curTitle not in labels:
821 labels.append( curTitle )
822 data.append( str( gossipTime ) )
823 append = True
824 else:
825 count += 1
Jon Hallf37d44d2017-05-24 10:37:30 -0700826 gossipPeriod = int( main.params[ 'timers' ][ 'gossip' ] )
Jon Halla440e872016-03-31 15:15:50 -0700827 maxGossipTime = gossipPeriod * len( main.activeNodes )
Jon Hall5cf14d52015-07-16 12:15:19 -0700828 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700829 expect=maxGossipTime, actual=gossipTime,
Jon Hall5cf14d52015-07-16 12:15:19 -0700830 onpass="ECM anti-entropy for intents worked within " +
831 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700832 onfail="Intent ECM anti-entropy took too long. " +
833 "Expected time:{}, Actual time:{}".format( maxGossipTime,
834 gossipTime ) )
835 if gossipTime <= maxGossipTime:
Jon Hall5cf14d52015-07-16 12:15:19 -0700836 intentAddResult = True
837
838 if not intentAddResult or "key" in pendingMap:
839 import time
840 installedCheck = True
841 main.log.info( "Sleeping 60 seconds to see if intents are found" )
842 time.sleep( 60 )
Jon Halla440e872016-03-31 15:15:50 -0700843 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700844 main.log.info( "Submitted intents: " + str( intentIds ) )
845 main.log.info( "Intents in ONOS: " + str( onosIds ) )
846 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -0700847 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700848 intentStates = []
849 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
850 count = 0
851 try:
852 for intent in json.loads( intents ):
853 # Iter through intents of a node
854 state = intent.get( 'state', None )
855 if "INSTALLED" not in state:
856 installedCheck = False
857 intentId = intent.get( 'id', None )
858 intentStates.append( ( intentId, state ) )
859 except ( ValueError, TypeError ):
860 main.log.exception( "Error parsing intents" )
861 # add submitted intents not in the store
862 tmplist = [ i for i, s in intentStates ]
863 for i in intentIds:
864 if i not in tmplist:
865 intentStates.append( ( i, " - " ) )
866 intentStates.sort()
867 for i, s in intentStates:
868 count += 1
869 main.log.info( "%-6s%-15s%-15s" %
870 ( str( count ), str( i ), str( s ) ) )
Jon Halla440e872016-03-31 15:15:50 -0700871 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700872 try:
873 missing = False
874 if leaders:
875 parsedLeaders = json.loads( leaders )
876 main.log.warn( json.dumps( parsedLeaders,
877 sort_keys=True,
878 indent=4,
879 separators=( ',', ': ' ) ) )
880 # check for all intent partitions
881 # check for election
882 topics = []
883 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700884 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700885 # FIXME: this should only be after we start the app
886 topics.append( "org.onosproject.election" )
887 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -0700888 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700889 for topic in topics:
890 if topic not in ONOStopics:
891 main.log.error( "Error: " + topic +
892 " not in leaders" )
893 missing = True
894 else:
895 main.log.error( "leaders() returned None" )
896 except ( ValueError, TypeError ):
897 main.log.exception( "Error parsing leaders" )
898 main.log.error( repr( leaders ) )
899 # Check all nodes
900 if missing:
Jon Halla440e872016-03-31 15:15:50 -0700901 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700902 node = main.CLIs[ i ]
903 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -0700904 main.log.warn( str( node.name ) + " leaders output: \n" +
905 str( response ) )
906
Jon Halla440e872016-03-31 15:15:50 -0700907 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700908 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700909 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -0700910 parsedPartitions = json.loads( partitions )
911 main.log.warn( json.dumps( parsedPartitions,
912 sort_keys=True,
913 indent=4,
914 separators=( ',', ': ' ) ) )
915 # TODO check for a leader in all paritions
916 # TODO check for consistency among nodes
917 else:
918 main.log.error( "partitions() returned None" )
919 except ( ValueError, TypeError ):
920 main.log.exception( "Error parsing partitions" )
921 main.log.error( repr( partitions ) )
Jon Halla440e872016-03-31 15:15:50 -0700922 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700923 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700924 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -0700925 parsedPending = json.loads( pendingMap )
926 main.log.warn( json.dumps( parsedPending,
927 sort_keys=True,
928 indent=4,
929 separators=( ',', ': ' ) ) )
930 # TODO check something here?
931 else:
932 main.log.error( "pendingMap() returned None" )
933 except ( ValueError, TypeError ):
934 main.log.exception( "Error parsing pending map" )
935 main.log.error( repr( pendingMap ) )
936
937 def CASE4( self, main ):
938 """
939 Ping across added host intents
940 """
941 import json
942 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700943 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700944 assert main, "main not defined"
945 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700946 assert main.CLIs, "main.CLIs not defined"
947 assert main.nodes, "main.nodes not defined"
Jon Hall6e709752016-02-01 13:38:46 -0800948 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700949 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700950 "functionality and check the state of " +\
951 "the intent"
Jon Hall5cf14d52015-07-16 12:15:19 -0700952
Jon Hallf37d44d2017-05-24 10:37:30 -0700953 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700954 main.step( "Check Intent state" )
955 installedCheck = False
956 loopCount = 0
957 while not installedCheck and loopCount < 40:
958 installedCheck = True
959 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -0700960 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700961 intentStates = []
962 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700963 count = 0
Jon Hall5cf14d52015-07-16 12:15:19 -0700964 # Iter through intents of a node
965 try:
966 for intent in json.loads( intents ):
967 state = intent.get( 'state', None )
968 if "INSTALLED" not in state:
969 installedCheck = False
970 intentId = intent.get( 'id', None )
971 intentStates.append( ( intentId, state ) )
972 except ( ValueError, TypeError ):
973 main.log.exception( "Error parsing intents." )
974 # Print states
975 intentStates.sort()
976 for i, s in intentStates:
977 count += 1
978 main.log.info( "%-6s%-15s%-15s" %
979 ( str( count ), str( i ), str( s ) ) )
980 if not installedCheck:
981 time.sleep( 1 )
982 loopCount += 1
983 utilities.assert_equals( expect=True, actual=installedCheck,
984 onpass="Intents are all INSTALLED",
985 onfail="Intents are not all in " +
986 "INSTALLED state" )
987
Jon Hall9d2dcad2016-04-08 10:15:20 -0700988 main.step( "Ping across added host intents" )
Jon Hall9d2dcad2016-04-08 10:15:20 -0700989 PingResult = main.TRUE
990 for i in range( 8, 18 ):
991 ping = main.Mininet1.pingHost( src="h" + str( i ),
992 target="h" + str( i + 10 ) )
993 PingResult = PingResult and ping
994 if ping == main.FALSE:
995 main.log.warn( "Ping failed between h" + str( i ) +
996 " and h" + str( i + 10 ) )
997 elif ping == main.TRUE:
998 main.log.info( "Ping test passed!" )
999 # Don't set PingResult or you'd override failures
1000 if PingResult == main.FALSE:
1001 main.log.error(
1002 "Intents have not been installed correctly, pings failed." )
1003 # TODO: pretty print
1004 main.log.warn( "ONOS1 intents: " )
1005 try:
1006 tmpIntents = onosCli.intents()
1007 main.log.warn( json.dumps( json.loads( tmpIntents ),
1008 sort_keys=True,
1009 indent=4,
1010 separators=( ',', ': ' ) ) )
1011 except ( ValueError, TypeError ):
1012 main.log.warn( repr( tmpIntents ) )
1013 utilities.assert_equals(
1014 expect=main.TRUE,
1015 actual=PingResult,
1016 onpass="Intents have been installed correctly and pings work",
1017 onfail="Intents have not been installed correctly, pings failed." )
1018
Jon Hall5cf14d52015-07-16 12:15:19 -07001019 main.step( "Check leadership of topics" )
Jon Halla440e872016-03-31 15:15:50 -07001020 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001021 topicCheck = main.TRUE
1022 try:
1023 if leaders:
1024 parsedLeaders = json.loads( leaders )
1025 main.log.warn( json.dumps( parsedLeaders,
1026 sort_keys=True,
1027 indent=4,
1028 separators=( ',', ': ' ) ) )
1029 # check for all intent partitions
1030 # check for election
1031 # TODO: Look at Devices as topics now that it uses this system
1032 topics = []
1033 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -07001034 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001035 # FIXME: this should only be after we start the app
1036 # FIXME: topics.append( "org.onosproject.election" )
1037 # Print leaders output
1038 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -07001039 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -07001040 for topic in topics:
1041 if topic not in ONOStopics:
1042 main.log.error( "Error: " + topic +
1043 " not in leaders" )
1044 topicCheck = main.FALSE
1045 else:
1046 main.log.error( "leaders() returned None" )
1047 topicCheck = main.FALSE
1048 except ( ValueError, TypeError ):
1049 topicCheck = main.FALSE
1050 main.log.exception( "Error parsing leaders" )
1051 main.log.error( repr( leaders ) )
1052 # TODO: Check for a leader of these topics
1053 # Check all nodes
1054 if topicCheck:
Jon Halla440e872016-03-31 15:15:50 -07001055 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001056 node = main.CLIs[ i ]
1057 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -07001058 main.log.warn( str( node.name ) + " leaders output: \n" +
1059 str( response ) )
1060
1061 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
1062 onpass="intent Partitions is in leaders",
1063 onfail="Some topics were lost " )
1064 # Print partitions
Jon Halla440e872016-03-31 15:15:50 -07001065 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001066 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001067 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -07001068 parsedPartitions = json.loads( partitions )
1069 main.log.warn( json.dumps( parsedPartitions,
1070 sort_keys=True,
1071 indent=4,
1072 separators=( ',', ': ' ) ) )
1073 # TODO check for a leader in all paritions
1074 # TODO check for consistency among nodes
1075 else:
1076 main.log.error( "partitions() returned None" )
1077 except ( ValueError, TypeError ):
1078 main.log.exception( "Error parsing partitions" )
1079 main.log.error( repr( partitions ) )
1080 # Print Pending Map
Jon Halla440e872016-03-31 15:15:50 -07001081 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001082 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001083 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -07001084 parsedPending = json.loads( pendingMap )
1085 main.log.warn( json.dumps( parsedPending,
1086 sort_keys=True,
1087 indent=4,
1088 separators=( ',', ': ' ) ) )
1089 # TODO check something here?
1090 else:
1091 main.log.error( "pendingMap() returned None" )
1092 except ( ValueError, TypeError ):
1093 main.log.exception( "Error parsing pending map" )
1094 main.log.error( repr( pendingMap ) )
1095
1096 if not installedCheck:
1097 main.log.info( "Waiting 60 seconds to see if the state of " +
1098 "intents change" )
1099 time.sleep( 60 )
1100 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -07001101 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001102 intentStates = []
1103 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1104 count = 0
1105 # Iter through intents of a node
1106 try:
1107 for intent in json.loads( intents ):
1108 state = intent.get( 'state', None )
1109 if "INSTALLED" not in state:
1110 installedCheck = False
1111 intentId = intent.get( 'id', None )
1112 intentStates.append( ( intentId, state ) )
1113 except ( ValueError, TypeError ):
1114 main.log.exception( "Error parsing intents." )
1115 intentStates.sort()
1116 for i, s in intentStates:
1117 count += 1
1118 main.log.info( "%-6s%-15s%-15s" %
1119 ( str( count ), str( i ), str( s ) ) )
Jon Halla440e872016-03-31 15:15:50 -07001120 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001121 try:
1122 missing = False
1123 if leaders:
1124 parsedLeaders = json.loads( leaders )
1125 main.log.warn( json.dumps( parsedLeaders,
1126 sort_keys=True,
1127 indent=4,
1128 separators=( ',', ': ' ) ) )
1129 # check for all intent partitions
1130 # check for election
1131 topics = []
1132 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -07001133 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001134 # FIXME: this should only be after we start the app
1135 topics.append( "org.onosproject.election" )
1136 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -07001137 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -07001138 for topic in topics:
1139 if topic not in ONOStopics:
1140 main.log.error( "Error: " + topic +
1141 " not in leaders" )
1142 missing = True
1143 else:
1144 main.log.error( "leaders() returned None" )
1145 except ( ValueError, TypeError ):
1146 main.log.exception( "Error parsing leaders" )
1147 main.log.error( repr( leaders ) )
1148 if missing:
Jon Halla440e872016-03-31 15:15:50 -07001149 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001150 node = main.CLIs[ i ]
1151 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -07001152 main.log.warn( str( node.name ) + " leaders output: \n" +
1153 str( response ) )
1154
Jon Halla440e872016-03-31 15:15:50 -07001155 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001156 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001157 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -07001158 parsedPartitions = json.loads( partitions )
1159 main.log.warn( json.dumps( parsedPartitions,
1160 sort_keys=True,
1161 indent=4,
1162 separators=( ',', ': ' ) ) )
1163 # TODO check for a leader in all paritions
1164 # TODO check for consistency among nodes
1165 else:
1166 main.log.error( "partitions() returned None" )
1167 except ( ValueError, TypeError ):
1168 main.log.exception( "Error parsing partitions" )
1169 main.log.error( repr( partitions ) )
Jon Halla440e872016-03-31 15:15:50 -07001170 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001171 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001172 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -07001173 parsedPending = json.loads( pendingMap )
1174 main.log.warn( json.dumps( parsedPending,
1175 sort_keys=True,
1176 indent=4,
1177 separators=( ',', ': ' ) ) )
1178 # TODO check something here?
1179 else:
1180 main.log.error( "pendingMap() returned None" )
1181 except ( ValueError, TypeError ):
1182 main.log.exception( "Error parsing pending map" )
1183 main.log.error( repr( pendingMap ) )
1184 # Print flowrules
Jon Hallf37d44d2017-05-24 10:37:30 -07001185 node = main.activeNodes[ 0 ]
1186 main.log.debug( main.CLIs[ node ].flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001187 main.step( "Wait a minute then ping again" )
1188 # the wait is above
1189 PingResult = main.TRUE
1190 for i in range( 8, 18 ):
1191 ping = main.Mininet1.pingHost( src="h" + str( i ),
1192 target="h" + str( i + 10 ) )
1193 PingResult = PingResult and ping
1194 if ping == main.FALSE:
1195 main.log.warn( "Ping failed between h" + str( i ) +
1196 " and h" + str( i + 10 ) )
1197 elif ping == main.TRUE:
1198 main.log.info( "Ping test passed!" )
1199 # Don't set PingResult or you'd override failures
1200 if PingResult == main.FALSE:
1201 main.log.error(
1202 "Intents have not been installed correctly, pings failed." )
1203 # TODO: pretty print
1204 main.log.warn( "ONOS1 intents: " )
1205 try:
Jon Halla440e872016-03-31 15:15:50 -07001206 tmpIntents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001207 main.log.warn( json.dumps( json.loads( tmpIntents ),
1208 sort_keys=True,
1209 indent=4,
1210 separators=( ',', ': ' ) ) )
1211 except ( ValueError, TypeError ):
1212 main.log.warn( repr( tmpIntents ) )
1213 utilities.assert_equals(
1214 expect=main.TRUE,
1215 actual=PingResult,
1216 onpass="Intents have been installed correctly and pings work",
1217 onfail="Intents have not been installed correctly, pings failed." )
1218
1219 def CASE5( self, main ):
1220 """
1221 Reading state of ONOS
1222 """
1223 import json
1224 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001225 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001226 assert main, "main not defined"
1227 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001228 assert main.CLIs, "main.CLIs not defined"
1229 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001230
1231 main.case( "Setting up and gathering data for current state" )
1232 # The general idea for this test case is to pull the state of
1233 # ( intents,flows, topology,... ) from each ONOS node
1234 # We can then compare them with each other and also with past states
1235
1236 main.step( "Check that each switch has a master" )
1237 global mastershipState
1238 mastershipState = '[]'
1239
1240 # Assert that each device has a master
1241 rolesNotNull = main.TRUE
1242 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001243 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001244 t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001245 name="rolesNotNull-" + str( i ),
1246 args=[] )
1247 threads.append( t )
1248 t.start()
1249
1250 for t in threads:
1251 t.join()
1252 rolesNotNull = rolesNotNull and t.result
1253 utilities.assert_equals(
1254 expect=main.TRUE,
1255 actual=rolesNotNull,
1256 onpass="Each device has a master",
1257 onfail="Some devices don't have a master assigned" )
1258
1259 main.step( "Get the Mastership of each switch from each controller" )
1260 ONOSMastership = []
1261 mastershipCheck = main.FALSE
1262 consistentMastership = True
1263 rolesResults = True
1264 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001265 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001266 t = main.Thread( target=main.CLIs[ i ].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001267 name="roles-" + str( i ),
1268 args=[] )
1269 threads.append( t )
1270 t.start()
1271
1272 for t in threads:
1273 t.join()
1274 ONOSMastership.append( t.result )
1275
Jon Halla440e872016-03-31 15:15:50 -07001276 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001277 node = str( main.activeNodes[ i ] + 1 )
1278 if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
Jon Halla440e872016-03-31 15:15:50 -07001279 main.log.error( "Error in getting ONOS" + node + " roles" )
1280 main.log.warn( "ONOS" + node + " mastership response: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001281 repr( ONOSMastership[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001282 rolesResults = False
1283 utilities.assert_equals(
1284 expect=True,
1285 actual=rolesResults,
1286 onpass="No error in reading roles output",
1287 onfail="Error in reading roles from ONOS" )
1288
1289 main.step( "Check for consistency in roles from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001290 if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001291 main.log.info(
1292 "Switch roles are consistent across all ONOS nodes" )
1293 else:
1294 consistentMastership = False
1295 utilities.assert_equals(
1296 expect=True,
1297 actual=consistentMastership,
1298 onpass="Switch roles are consistent across all ONOS nodes",
1299 onfail="ONOS nodes have different views of switch roles" )
1300
1301 if rolesResults and not consistentMastership:
Jon Halla440e872016-03-31 15:15:50 -07001302 for i in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001303 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001304 try:
1305 main.log.warn(
Jon Halla440e872016-03-31 15:15:50 -07001306 "ONOS" + node + " roles: ",
Jon Hall5cf14d52015-07-16 12:15:19 -07001307 json.dumps(
1308 json.loads( ONOSMastership[ i ] ),
1309 sort_keys=True,
1310 indent=4,
1311 separators=( ',', ': ' ) ) )
1312 except ( ValueError, TypeError ):
1313 main.log.warn( repr( ONOSMastership[ i ] ) )
1314 elif rolesResults and consistentMastership:
1315 mastershipCheck = main.TRUE
1316 mastershipState = ONOSMastership[ 0 ]
1317
1318 main.step( "Get the intents from each controller" )
1319 global intentState
1320 intentState = []
1321 ONOSIntents = []
1322 intentCheck = main.FALSE
1323 consistentIntents = True
1324 intentsResults = True
1325 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001326 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001327 t = main.Thread( target=main.CLIs[ i ].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001328 name="intents-" + str( i ),
1329 args=[],
1330 kwargs={ 'jsonFormat': True } )
1331 threads.append( t )
1332 t.start()
1333
1334 for t in threads:
1335 t.join()
1336 ONOSIntents.append( t.result )
1337
Jon Halla440e872016-03-31 15:15:50 -07001338 for i in range( len( ONOSIntents ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001339 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001340 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall6e709752016-02-01 13:38:46 -08001341 main.log.error( "Error in getting ONOS" + node + " intents" )
1342 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001343 repr( ONOSIntents[ i ] ) )
1344 intentsResults = False
1345 utilities.assert_equals(
1346 expect=True,
1347 actual=intentsResults,
1348 onpass="No error in reading intents output",
1349 onfail="Error in reading intents from ONOS" )
1350
1351 main.step( "Check for consistency in Intents from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001352 if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001353 main.log.info( "Intents are consistent across all ONOS " +
1354 "nodes" )
1355 else:
1356 consistentIntents = False
1357 main.log.error( "Intents not consistent" )
1358 utilities.assert_equals(
1359 expect=True,
1360 actual=consistentIntents,
1361 onpass="Intents are consistent across all ONOS nodes",
1362 onfail="ONOS nodes have different views of intents" )
1363
1364 if intentsResults:
1365 # Try to make it easy to figure out what is happening
1366 #
1367 # Intent ONOS1 ONOS2 ...
1368 # 0x01 INSTALLED INSTALLING
1369 # ... ... ...
1370 # ... ... ...
1371 title = " Id"
Jon Halla440e872016-03-31 15:15:50 -07001372 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001373 title += " " * 10 + "ONOS" + str( n + 1 )
1374 main.log.warn( title )
1375 # get all intent keys in the cluster
1376 keys = []
Jon Halla440e872016-03-31 15:15:50 -07001377 try:
1378 # Get the set of all intent keys
Jon Hall5cf14d52015-07-16 12:15:19 -07001379 for nodeStr in ONOSIntents:
1380 node = json.loads( nodeStr )
1381 for intent in node:
Jon Halla440e872016-03-31 15:15:50 -07001382 keys.append( intent.get( 'id' ) )
1383 keys = set( keys )
1384 # For each intent key, print the state on each node
1385 for key in keys:
1386 row = "%-13s" % key
1387 for nodeStr in ONOSIntents:
1388 node = json.loads( nodeStr )
1389 for intent in node:
1390 if intent.get( 'id', "Error" ) == key:
1391 row += "%-15s" % intent.get( 'state' )
1392 main.log.warn( row )
1393 # End of intent state table
1394 except ValueError as e:
1395 main.log.exception( e )
1396 main.log.debug( "nodeStr was: " + repr( nodeStr ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001397
1398 if intentsResults and not consistentIntents:
1399 # print the json objects
Jon Hallf37d44d2017-05-24 10:37:30 -07001400 n = str( main.activeNodes[ -1 ] + 1 )
Jon Halla440e872016-03-31 15:15:50 -07001401 main.log.debug( "ONOS" + n + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001402 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1403 sort_keys=True,
1404 indent=4,
1405 separators=( ',', ': ' ) ) )
Jon Halla440e872016-03-31 15:15:50 -07001406 for i in range( len( ONOSIntents ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001407 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001408 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Halla440e872016-03-31 15:15:50 -07001409 main.log.debug( "ONOS" + node + " intents: " )
Jon Hallf37d44d2017-05-24 10:37:30 -07001410 main.log.debug( json.dumps( json.loads( ONOSIntents[ i ] ),
Jon Hall5cf14d52015-07-16 12:15:19 -07001411 sort_keys=True,
1412 indent=4,
1413 separators=( ',', ': ' ) ) )
1414 else:
Jon Halla440e872016-03-31 15:15:50 -07001415 main.log.debug( "ONOS" + node + " intents match ONOS" +
1416 n + " intents" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001417 elif intentsResults and consistentIntents:
1418 intentCheck = main.TRUE
1419 intentState = ONOSIntents[ 0 ]
1420
1421 main.step( "Get the flows from each controller" )
1422 global flowState
1423 flowState = []
1424 ONOSFlows = []
1425 ONOSFlowsJson = []
1426 flowCheck = main.FALSE
1427 consistentFlows = True
1428 flowsResults = True
1429 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001430 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001431 t = main.Thread( target=main.CLIs[ i ].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001432 name="flows-" + str( i ),
1433 args=[],
1434 kwargs={ 'jsonFormat': True } )
1435 threads.append( t )
1436 t.start()
1437
1438 # NOTE: Flows command can take some time to run
Jon Hallf37d44d2017-05-24 10:37:30 -07001439 time.sleep( 30 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001440 for t in threads:
1441 t.join()
1442 result = t.result
1443 ONOSFlows.append( result )
1444
Jon Halla440e872016-03-31 15:15:50 -07001445 for i in range( len( ONOSFlows ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001446 num = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001447 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1448 main.log.error( "Error in getting ONOS" + num + " flows" )
1449 main.log.warn( "ONOS" + num + " flows response: " +
1450 repr( ONOSFlows[ i ] ) )
1451 flowsResults = False
1452 ONOSFlowsJson.append( None )
1453 else:
1454 try:
1455 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1456 except ( ValueError, TypeError ):
1457 # FIXME: change this to log.error?
1458 main.log.exception( "Error in parsing ONOS" + num +
1459 " response as json." )
1460 main.log.error( repr( ONOSFlows[ i ] ) )
1461 ONOSFlowsJson.append( None )
1462 flowsResults = False
1463 utilities.assert_equals(
1464 expect=True,
1465 actual=flowsResults,
1466 onpass="No error in reading flows output",
1467 onfail="Error in reading flows from ONOS" )
1468
1469 main.step( "Check for consistency in Flows from each controller" )
1470 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1471 if all( tmp ):
1472 main.log.info( "Flow count is consistent across all ONOS nodes" )
1473 else:
1474 consistentFlows = False
1475 utilities.assert_equals(
1476 expect=True,
1477 actual=consistentFlows,
1478 onpass="The flow count is consistent across all ONOS nodes",
1479 onfail="ONOS nodes have different flow counts" )
1480
1481 if flowsResults and not consistentFlows:
Jon Halla440e872016-03-31 15:15:50 -07001482 for i in range( len( ONOSFlows ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001483 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001484 try:
1485 main.log.warn(
Jon Halla440e872016-03-31 15:15:50 -07001486 "ONOS" + node + " flows: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001487 json.dumps( json.loads( ONOSFlows[ i ] ), sort_keys=True,
Jon Hall5cf14d52015-07-16 12:15:19 -07001488 indent=4, separators=( ',', ': ' ) ) )
1489 except ( ValueError, TypeError ):
Jon Halla440e872016-03-31 15:15:50 -07001490 main.log.warn( "ONOS" + node + " flows: " +
1491 repr( ONOSFlows[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001492 elif flowsResults and consistentFlows:
1493 flowCheck = main.TRUE
1494 flowState = ONOSFlows[ 0 ]
1495
1496 main.step( "Get the OF Table entries" )
1497 global flows
1498 flows = []
1499 for i in range( 1, 29 ):
Jon Halla440e872016-03-31 15:15:50 -07001500 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001501 if flowCheck == main.FALSE:
1502 for table in flows:
1503 main.log.warn( table )
1504 # TODO: Compare switch flow tables with ONOS flow tables
1505
1506 main.step( "Start continuous pings" )
1507 main.Mininet2.pingLong(
1508 src=main.params[ 'PING' ][ 'source1' ],
1509 target=main.params[ 'PING' ][ 'target1' ],
1510 pingTime=500 )
1511 main.Mininet2.pingLong(
1512 src=main.params[ 'PING' ][ 'source2' ],
1513 target=main.params[ 'PING' ][ 'target2' ],
1514 pingTime=500 )
1515 main.Mininet2.pingLong(
1516 src=main.params[ 'PING' ][ 'source3' ],
1517 target=main.params[ 'PING' ][ 'target3' ],
1518 pingTime=500 )
1519 main.Mininet2.pingLong(
1520 src=main.params[ 'PING' ][ 'source4' ],
1521 target=main.params[ 'PING' ][ 'target4' ],
1522 pingTime=500 )
1523 main.Mininet2.pingLong(
1524 src=main.params[ 'PING' ][ 'source5' ],
1525 target=main.params[ 'PING' ][ 'target5' ],
1526 pingTime=500 )
1527 main.Mininet2.pingLong(
1528 src=main.params[ 'PING' ][ 'source6' ],
1529 target=main.params[ 'PING' ][ 'target6' ],
1530 pingTime=500 )
1531 main.Mininet2.pingLong(
1532 src=main.params[ 'PING' ][ 'source7' ],
1533 target=main.params[ 'PING' ][ 'target7' ],
1534 pingTime=500 )
1535 main.Mininet2.pingLong(
1536 src=main.params[ 'PING' ][ 'source8' ],
1537 target=main.params[ 'PING' ][ 'target8' ],
1538 pingTime=500 )
1539 main.Mininet2.pingLong(
1540 src=main.params[ 'PING' ][ 'source9' ],
1541 target=main.params[ 'PING' ][ 'target9' ],
1542 pingTime=500 )
1543 main.Mininet2.pingLong(
1544 src=main.params[ 'PING' ][ 'source10' ],
1545 target=main.params[ 'PING' ][ 'target10' ],
1546 pingTime=500 )
1547
1548 main.step( "Collecting topology information from ONOS" )
1549 devices = []
1550 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001551 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001552 t = main.Thread( target=main.CLIs[ i ].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001553 name="devices-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001554 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001555 threads.append( t )
1556 t.start()
1557
1558 for t in threads:
1559 t.join()
1560 devices.append( t.result )
1561 hosts = []
1562 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001563 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001564 t = main.Thread( target=main.CLIs[ i ].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001565 name="hosts-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001566 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001567 threads.append( t )
1568 t.start()
1569
1570 for t in threads:
1571 t.join()
1572 try:
1573 hosts.append( json.loads( t.result ) )
1574 except ( ValueError, TypeError ):
1575 # FIXME: better handling of this, print which node
1576 # Maybe use thread name?
1577 main.log.exception( "Error parsing json output of hosts" )
Jon Hall3afe4c92015-12-14 19:30:38 -08001578 main.log.warn( repr( t.result ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001579 hosts.append( None )
1580
1581 ports = []
1582 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001583 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001584 t = main.Thread( target=main.CLIs[ i ].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001585 name="ports-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001586 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001587 threads.append( t )
1588 t.start()
1589
1590 for t in threads:
1591 t.join()
1592 ports.append( t.result )
1593 links = []
1594 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001595 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001596 t = main.Thread( target=main.CLIs[ i ].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001597 name="links-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001598 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001599 threads.append( t )
1600 t.start()
1601
1602 for t in threads:
1603 t.join()
1604 links.append( t.result )
1605 clusters = []
1606 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001607 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001608 t = main.Thread( target=main.CLIs[ i ].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001609 name="clusters-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001610 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001611 threads.append( t )
1612 t.start()
1613
1614 for t in threads:
1615 t.join()
1616 clusters.append( t.result )
1617 # Compare json objects for hosts and dataplane clusters
1618
1619 # hosts
1620 main.step( "Host view is consistent across ONOS nodes" )
1621 consistentHostsResult = main.TRUE
1622 for controller in range( len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001623 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall3afe4c92015-12-14 19:30:38 -08001624 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001625 if hosts[ controller ] == hosts[ 0 ]:
1626 continue
1627 else: # hosts not consistent
1628 main.log.error( "hosts from ONOS" +
1629 controllerStr +
1630 " is inconsistent with ONOS1" )
1631 main.log.warn( repr( hosts[ controller ] ) )
1632 consistentHostsResult = main.FALSE
1633
1634 else:
1635 main.log.error( "Error in getting ONOS hosts from ONOS" +
1636 controllerStr )
1637 consistentHostsResult = main.FALSE
1638 main.log.warn( "ONOS" + controllerStr +
1639 " hosts response: " +
1640 repr( hosts[ controller ] ) )
1641 utilities.assert_equals(
1642 expect=main.TRUE,
1643 actual=consistentHostsResult,
1644 onpass="Hosts view is consistent across all ONOS nodes",
1645 onfail="ONOS nodes have different views of hosts" )
1646
1647 main.step( "Each host has an IP address" )
1648 ipResult = main.TRUE
1649 for controller in range( 0, len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001650 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall3afe4c92015-12-14 19:30:38 -08001651 if hosts[ controller ]:
1652 for host in hosts[ controller ]:
Jon Hallf37d44d2017-05-24 10:37:30 -07001653 if not host.get( 'ipAddresses', [] ):
Jon Hallf3d16e72015-12-16 17:45:08 -08001654 main.log.error( "Error with host ips on controller" +
Jon Hall3afe4c92015-12-14 19:30:38 -08001655 controllerStr + ": " + str( host ) )
1656 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001657 utilities.assert_equals(
1658 expect=main.TRUE,
1659 actual=ipResult,
1660 onpass="The ips of the hosts aren't empty",
1661 onfail="The ip of at least one host is missing" )
1662
1663 # Strongly connected clusters of devices
1664 main.step( "Cluster view is consistent across ONOS nodes" )
1665 consistentClustersResult = main.TRUE
1666 for controller in range( len( clusters ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001667 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001668 if "Error" not in clusters[ controller ]:
1669 if clusters[ controller ] == clusters[ 0 ]:
1670 continue
1671 else: # clusters not consistent
1672 main.log.error( "clusters from ONOS" + controllerStr +
1673 " is inconsistent with ONOS1" )
1674 consistentClustersResult = main.FALSE
1675
1676 else:
1677 main.log.error( "Error in getting dataplane clusters " +
1678 "from ONOS" + controllerStr )
1679 consistentClustersResult = main.FALSE
1680 main.log.warn( "ONOS" + controllerStr +
1681 " clusters response: " +
1682 repr( clusters[ controller ] ) )
1683 utilities.assert_equals(
1684 expect=main.TRUE,
1685 actual=consistentClustersResult,
1686 onpass="Clusters view is consistent across all ONOS nodes",
1687 onfail="ONOS nodes have different views of clusters" )
Jon Hall64948022016-05-12 13:38:50 -07001688 if not consistentClustersResult:
Jon Hall172b7ba2016-04-07 18:12:20 -07001689 main.log.debug( clusters )
Jon Hall64948022016-05-12 13:38:50 -07001690
Jon Hall5cf14d52015-07-16 12:15:19 -07001691 # there should always only be one cluster
1692 main.step( "Cluster view correct across ONOS nodes" )
1693 try:
1694 numClusters = len( json.loads( clusters[ 0 ] ) )
1695 except ( ValueError, TypeError ):
1696 main.log.exception( "Error parsing clusters[0]: " +
1697 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001698 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07001699 clusterResults = main.FALSE
1700 if numClusters == 1:
1701 clusterResults = main.TRUE
1702 utilities.assert_equals(
1703 expect=1,
1704 actual=numClusters,
1705 onpass="ONOS shows 1 SCC",
1706 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1707
1708 main.step( "Comparing ONOS topology to MN" )
1709 devicesResults = main.TRUE
1710 linksResults = main.TRUE
1711 hostsResults = main.TRUE
1712 mnSwitches = main.Mininet1.getSwitches()
1713 mnLinks = main.Mininet1.getLinks()
1714 mnHosts = main.Mininet1.getHosts()
Jon Halla440e872016-03-31 15:15:50 -07001715 for controller in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001716 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001717 if devices[ controller ] and ports[ controller ] and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001718 "Error" not in devices[ controller ] and\
1719 "Error" not in ports[ controller ]:
1720 currentDevicesResult = main.Mininet1.compareSwitches(
1721 mnSwitches,
1722 json.loads( devices[ controller ] ),
1723 json.loads( ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001724 else:
1725 currentDevicesResult = main.FALSE
1726 utilities.assert_equals( expect=main.TRUE,
1727 actual=currentDevicesResult,
1728 onpass="ONOS" + controllerStr +
1729 " Switches view is correct",
1730 onfail="ONOS" + controllerStr +
1731 " Switches view is incorrect" )
1732 if links[ controller ] and "Error" not in links[ controller ]:
1733 currentLinksResult = main.Mininet1.compareLinks(
1734 mnSwitches, mnLinks,
1735 json.loads( links[ controller ] ) )
1736 else:
1737 currentLinksResult = main.FALSE
1738 utilities.assert_equals( expect=main.TRUE,
1739 actual=currentLinksResult,
1740 onpass="ONOS" + controllerStr +
1741 " links view is correct",
1742 onfail="ONOS" + controllerStr +
1743 " links view is incorrect" )
1744
Jon Hall657cdf62015-12-17 14:40:51 -08001745 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001746 currentHostsResult = main.Mininet1.compareHosts(
1747 mnHosts,
1748 hosts[ controller ] )
1749 else:
1750 currentHostsResult = main.FALSE
1751 utilities.assert_equals( expect=main.TRUE,
1752 actual=currentHostsResult,
1753 onpass="ONOS" + controllerStr +
1754 " hosts exist in Mininet",
1755 onfail="ONOS" + controllerStr +
1756 " hosts don't match Mininet" )
1757
1758 devicesResults = devicesResults and currentDevicesResult
1759 linksResults = linksResults and currentLinksResult
1760 hostsResults = hostsResults and currentHostsResult
1761
1762 main.step( "Device information is correct" )
1763 utilities.assert_equals(
1764 expect=main.TRUE,
1765 actual=devicesResults,
1766 onpass="Device information is correct",
1767 onfail="Device information is incorrect" )
1768
1769 main.step( "Links are correct" )
1770 utilities.assert_equals(
1771 expect=main.TRUE,
1772 actual=linksResults,
1773 onpass="Link are correct",
1774 onfail="Links are incorrect" )
1775
1776 main.step( "Hosts are correct" )
1777 utilities.assert_equals(
1778 expect=main.TRUE,
1779 actual=hostsResults,
1780 onpass="Hosts are correct",
1781 onfail="Hosts are incorrect" )
1782
1783 def CASE6( self, main ):
1784 """
1785 The Failure case.
1786 """
1787 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001788 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001789 assert main, "main not defined"
1790 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001791 assert main.CLIs, "main.CLIs not defined"
1792 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001793 try:
1794 labels
1795 except NameError:
1796 main.log.error( "labels not defined, setting to []" )
1797 global labels
1798 labels = []
1799 try:
1800 data
1801 except NameError:
1802 main.log.error( "data not defined, setting to []" )
1803 global data
1804 data = []
1805 # Reset non-persistent variables
1806 try:
1807 iCounterValue = 0
1808 except NameError:
1809 main.log.error( "iCounterValue not defined, setting to 0" )
1810 iCounterValue = 0
1811
1812 main.case( "Restart entire ONOS cluster" )
1813
Jon Hall5ec6b1b2015-09-17 18:20:14 -07001814 main.step( "Checking ONOS Logs for errors" )
1815 for node in main.nodes:
1816 main.log.debug( "Checking logs for errors on " + node.name + ":" )
1817 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
1818
Jon Hall5cf14d52015-07-16 12:15:19 -07001819 main.step( "Killing ONOS nodes" )
1820 killResults = main.TRUE
1821 killTime = time.time()
Jon Halle1a3b752015-07-22 13:02:46 -07001822 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001823 killed = main.ONOSbench.onosKill( node.ip_address )
1824 killResults = killResults and killed
1825 utilities.assert_equals( expect=main.TRUE, actual=killResults,
1826 onpass="ONOS nodes killed",
1827 onfail="ONOS kill unsuccessful" )
1828
1829 main.step( "Checking if ONOS is up yet" )
1830 for i in range( 2 ):
1831 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07001832 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001833 started = main.ONOSbench.isup( node.ip_address )
1834 if not started:
1835 main.log.error( node.name + " didn't start!" )
1836 onosIsupResult = onosIsupResult and started
1837 if onosIsupResult == main.TRUE:
1838 break
1839 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1840 onpass="ONOS restarted",
1841 onfail="ONOS restart NOT successful" )
1842
Jon Hall6509dbf2016-06-21 17:01:17 -07001843 main.step( "Starting ONOS CLI sessions" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001844 cliResults = main.TRUE
1845 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -07001846 for i in range( main.numCtrls ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001847 t = main.Thread( target=main.CLIs[ i ].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -07001848 name="startOnosCli-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001849 args=[ main.nodes[ i ].ip_address ] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001850 threads.append( t )
1851 t.start()
1852
1853 for t in threads:
1854 t.join()
1855 cliResults = cliResults and t.result
1856 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1857 onpass="ONOS cli started",
1858 onfail="ONOS clis did not restart" )
1859
Jon Hall6e709752016-02-01 13:38:46 -08001860 for i in range( 10 ):
1861 ready = True
Jon Hall7ac7bc32016-05-05 10:57:02 -07001862 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001863 cli = main.CLIs[ i ]
Jon Hall6e709752016-02-01 13:38:46 -08001864 output = cli.summary()
1865 if not output:
1866 ready = False
Jon Halld2871c22016-07-26 11:01:14 -07001867 if ready:
1868 break
Jon Hall6e709752016-02-01 13:38:46 -08001869 time.sleep( 30 )
1870 utilities.assert_equals( expect=True, actual=ready,
1871 onpass="ONOS summary command succeded",
1872 onfail="ONOS summary command failed" )
1873 if not ready:
1874 main.cleanup()
1875 main.exit()
1876
Jon Hall5cf14d52015-07-16 12:15:19 -07001877 # Grab the time of restart so we chan check how long the gossip
1878 # protocol has had time to work
1879 main.restartTime = time.time() - killTime
1880 main.log.debug( "Restart time: " + str( main.restartTime ) )
1881 labels.append( "Restart" )
1882 data.append( str( main.restartTime ) )
1883
Jon Hall5cf14d52015-07-16 12:15:19 -07001884 # Rerun for election on restarted nodes
1885 runResults = main.TRUE
Jon Hall7ac7bc32016-05-05 10:57:02 -07001886 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001887 cli = main.CLIs[ i ]
Jon Halla440e872016-03-31 15:15:50 -07001888 run = cli.electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07001889 if run != main.TRUE:
1890 main.log.error( "Error running for election on " + cli.name )
1891 runResults = runResults and run
1892 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1893 onpass="Reran for election",
1894 onfail="Failed to rerun for election" )
1895
1896 # TODO: Make this configurable
1897 time.sleep( 60 )
Jon Hallf37d44d2017-05-24 10:37:30 -07001898 node = main.activeNodes[ 0 ]
1899 main.log.debug( main.CLIs[ node ].nodes( jsonFormat=False ) )
1900 main.log.debug( main.CLIs[ node ].leaders( jsonFormat=False ) )
1901 main.log.debug( main.CLIs[ node ].partitions( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001902
1903 def CASE7( self, main ):
1904 """
1905 Check state after ONOS failure
1906 """
1907 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001908 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001909 assert main, "main not defined"
1910 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001911 assert main.CLIs, "main.CLIs not defined"
1912 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001913 main.case( "Running ONOS Constant State Tests" )
1914
1915 main.step( "Check that each switch has a master" )
1916 # Assert that each device has a master
1917 rolesNotNull = main.TRUE
1918 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001919 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001920 t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001921 name="rolesNotNull-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001922 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001923 threads.append( t )
1924 t.start()
1925
1926 for t in threads:
1927 t.join()
1928 rolesNotNull = rolesNotNull and t.result
1929 utilities.assert_equals(
1930 expect=main.TRUE,
1931 actual=rolesNotNull,
1932 onpass="Each device has a master",
1933 onfail="Some devices don't have a master assigned" )
1934
1935 main.step( "Read device roles from ONOS" )
1936 ONOSMastership = []
1937 mastershipCheck = main.FALSE
1938 consistentMastership = True
1939 rolesResults = True
1940 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001941 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001942 t = main.Thread( target=main.CLIs[ i ].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001943 name="roles-" + str( i ),
1944 args=[] )
1945 threads.append( t )
1946 t.start()
1947
1948 for t in threads:
1949 t.join()
1950 ONOSMastership.append( t.result )
1951
Jon Halla440e872016-03-31 15:15:50 -07001952 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001953 node = str( main.activeNodes[ i ] + 1 )
1954 if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
Jon Halla440e872016-03-31 15:15:50 -07001955 main.log.error( "Error in getting ONOS" + node + " roles" )
1956 main.log.warn( "ONOS" + node + " mastership response: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001957 repr( ONOSMastership[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001958 rolesResults = False
1959 utilities.assert_equals(
1960 expect=True,
1961 actual=rolesResults,
1962 onpass="No error in reading roles output",
1963 onfail="Error in reading roles from ONOS" )
1964
1965 main.step( "Check for consistency in roles from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001966 if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001967 main.log.info(
1968 "Switch roles are consistent across all ONOS nodes" )
1969 else:
1970 consistentMastership = False
1971 utilities.assert_equals(
1972 expect=True,
1973 actual=consistentMastership,
1974 onpass="Switch roles are consistent across all ONOS nodes",
1975 onfail="ONOS nodes have different views of switch roles" )
1976
1977 if rolesResults and not consistentMastership:
Jon Halla440e872016-03-31 15:15:50 -07001978 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001979 node = str( main.activeNodes[ i ] + 1 )
Jon Halla440e872016-03-31 15:15:50 -07001980 main.log.warn( "ONOS" + node + " roles: ",
Jon Hall6e709752016-02-01 13:38:46 -08001981 json.dumps( json.loads( ONOSMastership[ i ] ),
1982 sort_keys=True,
1983 indent=4,
1984 separators=( ',', ': ' ) ) )
1985 elif rolesResults and consistentMastership:
Jon Hall5cf14d52015-07-16 12:15:19 -07001986 mastershipCheck = main.TRUE
1987
Jon Hall5cf14d52015-07-16 12:15:19 -07001988 # NOTE: we expect mastership to change on controller failure
1989
1990 main.step( "Get the intents and compare across all nodes" )
1991 ONOSIntents = []
1992 intentCheck = main.FALSE
1993 consistentIntents = True
1994 intentsResults = True
1995 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001996 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001997 t = main.Thread( target=main.CLIs[ i ].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001998 name="intents-" + str( i ),
1999 args=[],
2000 kwargs={ 'jsonFormat': True } )
2001 threads.append( t )
2002 t.start()
2003
2004 for t in threads:
2005 t.join()
2006 ONOSIntents.append( t.result )
2007
Jon Hallf37d44d2017-05-24 10:37:30 -07002008 for i in range( len( ONOSIntents ) ):
2009 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002010 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Halla440e872016-03-31 15:15:50 -07002011 main.log.error( "Error in getting ONOS" + node + " intents" )
2012 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07002013 repr( ONOSIntents[ i ] ) )
2014 intentsResults = False
2015 utilities.assert_equals(
2016 expect=True,
2017 actual=intentsResults,
2018 onpass="No error in reading intents output",
2019 onfail="Error in reading intents from ONOS" )
2020
2021 main.step( "Check for consistency in Intents from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002022 if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07002023 main.log.info( "Intents are consistent across all ONOS " +
2024 "nodes" )
2025 else:
2026 consistentIntents = False
2027
2028 # Try to make it easy to figure out what is happening
2029 #
2030 # Intent ONOS1 ONOS2 ...
2031 # 0x01 INSTALLED INSTALLING
2032 # ... ... ...
2033 # ... ... ...
2034 title = " ID"
Jon Halla440e872016-03-31 15:15:50 -07002035 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002036 title += " " * 10 + "ONOS" + str( n + 1 )
2037 main.log.warn( title )
2038 # get all intent keys in the cluster
2039 keys = []
2040 for nodeStr in ONOSIntents:
2041 node = json.loads( nodeStr )
2042 for intent in node:
2043 keys.append( intent.get( 'id' ) )
2044 keys = set( keys )
2045 for key in keys:
2046 row = "%-13s" % key
2047 for nodeStr in ONOSIntents:
2048 node = json.loads( nodeStr )
2049 for intent in node:
2050 if intent.get( 'id' ) == key:
2051 row += "%-15s" % intent.get( 'state' )
2052 main.log.warn( row )
2053 # End table view
2054
2055 utilities.assert_equals(
2056 expect=True,
2057 actual=consistentIntents,
2058 onpass="Intents are consistent across all ONOS nodes",
2059 onfail="ONOS nodes have different views of intents" )
2060 intentStates = []
2061 for node in ONOSIntents: # Iter through ONOS nodes
2062 nodeStates = []
2063 # Iter through intents of a node
2064 try:
2065 for intent in json.loads( node ):
2066 nodeStates.append( intent[ 'state' ] )
2067 except ( ValueError, TypeError ):
2068 main.log.exception( "Error in parsing intents" )
2069 main.log.error( repr( node ) )
2070 intentStates.append( nodeStates )
Jon Hallf37d44d2017-05-24 10:37:30 -07002071 out = [ ( i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002072 main.log.info( dict( out ) )
2073
2074 if intentsResults and not consistentIntents:
Jon Halla440e872016-03-31 15:15:50 -07002075 for i in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002076 node = str( main.activeNodes[ i ] + 1 )
Jon Halla440e872016-03-31 15:15:50 -07002077 main.log.warn( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07002078 main.log.warn( json.dumps(
2079 json.loads( ONOSIntents[ i ] ),
2080 sort_keys=True,
2081 indent=4,
2082 separators=( ',', ': ' ) ) )
2083 elif intentsResults and consistentIntents:
2084 intentCheck = main.TRUE
2085
2086 # NOTE: Store has no durability, so intents are lost across system
2087 # restarts
2088 """
2089 main.step( "Compare current intents with intents before the failure" )
2090 # NOTE: this requires case 5 to pass for intentState to be set.
2091 # maybe we should stop the test if that fails?
2092 sameIntents = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002093 try:
2094 intentState
2095 except NameError:
2096 main.log.warn( "No previous intent state was saved" )
2097 else:
2098 if intentState and intentState == ONOSIntents[ 0 ]:
2099 sameIntents = main.TRUE
2100 main.log.info( "Intents are consistent with before failure" )
2101 # TODO: possibly the states have changed? we may need to figure out
2102 # what the acceptable states are
2103 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
2104 sameIntents = main.TRUE
2105 try:
2106 before = json.loads( intentState )
2107 after = json.loads( ONOSIntents[ 0 ] )
2108 for intent in before:
2109 if intent not in after:
2110 sameIntents = main.FALSE
2111 main.log.debug( "Intent is not currently in ONOS " +
2112 "(at least in the same form):" )
2113 main.log.debug( json.dumps( intent ) )
2114 except ( ValueError, TypeError ):
2115 main.log.exception( "Exception printing intents" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002116 main.log.debug( repr( ONOSIntents[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002117 main.log.debug( repr( intentState ) )
2118 if sameIntents == main.FALSE:
2119 try:
2120 main.log.debug( "ONOS intents before: " )
2121 main.log.debug( json.dumps( json.loads( intentState ),
2122 sort_keys=True, indent=4,
2123 separators=( ',', ': ' ) ) )
2124 main.log.debug( "Current ONOS intents: " )
2125 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2126 sort_keys=True, indent=4,
2127 separators=( ',', ': ' ) ) )
2128 except ( ValueError, TypeError ):
2129 main.log.exception( "Exception printing intents" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002130 main.log.debug( repr( ONOSIntents[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002131 main.log.debug( repr( intentState ) )
2132 utilities.assert_equals(
2133 expect=main.TRUE,
2134 actual=sameIntents,
2135 onpass="Intents are consistent with before failure",
2136 onfail="The Intents changed during failure" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002137 intentCheck = intentCheck and sameIntents
2138 """
2139 main.step( "Get the OF Table entries and compare to before " +
2140 "component failure" )
2141 FlowTables = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002142 for i in range( 28 ):
2143 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08002144 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
Jon Hallf37d44d2017-05-24 10:37:30 -07002145 curSwitch = main.Mininet1.flowTableComp( flows[ i ], tmpFlows )
Jon Hall41d39f12016-04-11 22:54:35 -07002146 FlowTables = FlowTables and curSwitch
2147 if curSwitch == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08002148 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002149 utilities.assert_equals(
2150 expect=main.TRUE,
2151 actual=FlowTables,
2152 onpass="No changes were found in the flow tables",
2153 onfail="Changes were found in the flow tables" )
2154
2155 main.Mininet2.pingLongKill()
Jon Hallf37d44d2017-05-24 10:37:30 -07002156 """
Jon Hall5cf14d52015-07-16 12:15:19 -07002157 # main.step( "Check the continuous pings to ensure that no packets " +
2158 # "were dropped during component failure" )
2159 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2160 main.params[ 'TESTONIP' ] )
2161 LossInPings = main.FALSE
2162 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2163 for i in range( 8, 18 ):
2164 main.log.info(
2165 "Checking for a loss in pings along flow from s" +
2166 str( i ) )
2167 LossInPings = main.Mininet2.checkForLoss(
2168 "/tmp/ping.h" +
2169 str( i ) ) or LossInPings
2170 if LossInPings == main.TRUE:
2171 main.log.info( "Loss in ping detected" )
2172 elif LossInPings == main.ERROR:
2173 main.log.info( "There are multiple mininet process running" )
2174 elif LossInPings == main.FALSE:
2175 main.log.info( "No Loss in the pings" )
2176 main.log.info( "No loss of dataplane connectivity" )
2177 # utilities.assert_equals(
2178 # expect=main.FALSE,
2179 # actual=LossInPings,
2180 # onpass="No Loss of connectivity",
2181 # onfail="Loss of dataplane connectivity detected" )
2182
2183 # NOTE: Since intents are not persisted with IntnentStore,
2184 # we expect loss in dataplane connectivity
2185 LossInPings = main.FALSE
Jon Hallf37d44d2017-05-24 10:37:30 -07002186 """
Jon Hall5cf14d52015-07-16 12:15:19 -07002187 main.step( "Leadership Election is still functional" )
2188 # Test of LeadershipElection
2189 leaderList = []
2190 leaderResult = main.TRUE
Jon Halla440e872016-03-31 15:15:50 -07002191
2192 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002193 cli = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002194 leaderN = cli.electionTestLeader()
2195 leaderList.append( leaderN )
2196 if leaderN == main.FALSE:
2197 # error in response
2198 main.log.error( "Something is wrong with " +
2199 "electionTestLeader function, check the" +
2200 " error logs" )
2201 leaderResult = main.FALSE
2202 elif leaderN is None:
2203 main.log.error( cli.name +
2204 " shows no leader for the election-app." )
2205 leaderResult = main.FALSE
2206 if len( set( leaderList ) ) != 1:
2207 leaderResult = main.FALSE
2208 main.log.error(
2209 "Inconsistent view of leader for the election test app" )
2210 # TODO: print the list
2211 utilities.assert_equals(
2212 expect=main.TRUE,
2213 actual=leaderResult,
2214 onpass="Leadership election passed",
2215 onfail="Something went wrong with Leadership election" )
2216
2217 def CASE8( self, main ):
2218 """
2219 Compare topo
2220 """
2221 import json
2222 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002223 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002224 assert main, "main not defined"
2225 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002226 assert main.CLIs, "main.CLIs not defined"
2227 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002228
2229 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002230 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002231 " and ONOS"
Jon Hall5cf14d52015-07-16 12:15:19 -07002232 topoResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002233 topoFailMsg = "ONOS topology don't match Mininet"
Jon Hall5cf14d52015-07-16 12:15:19 -07002234 elapsed = 0
2235 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08002236 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002237 startTime = time.time()
2238 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08002239 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hallba609822015-09-18 12:00:21 -07002240 devicesResults = main.TRUE
2241 linksResults = main.TRUE
2242 hostsResults = main.TRUE
2243 hostAttachmentResults = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002244 count += 1
2245 cliStart = time.time()
2246 devices = []
2247 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002248 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002249 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002250 name="devices-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002251 args=[ main.CLIs[ i ].devices, [ None ] ],
2252 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002253 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002254 threads.append( t )
2255 t.start()
2256
2257 for t in threads:
2258 t.join()
2259 devices.append( t.result )
2260 hosts = []
2261 ipResult = main.TRUE
2262 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002263 for i in main.activeNodes:
Jon Halld8f6de82015-12-17 17:04:34 -08002264 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002265 name="hosts-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002266 args=[ main.CLIs[ i ].hosts, [ None ] ],
2267 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Halld8f6de82015-12-17 17:04:34 -08002268 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002269 threads.append( t )
2270 t.start()
2271
2272 for t in threads:
2273 t.join()
2274 try:
2275 hosts.append( json.loads( t.result ) )
2276 except ( ValueError, TypeError ):
2277 main.log.exception( "Error parsing hosts results" )
2278 main.log.error( repr( t.result ) )
Jon Hall3afe4c92015-12-14 19:30:38 -08002279 hosts.append( None )
Jon Hall5cf14d52015-07-16 12:15:19 -07002280 for controller in range( 0, len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002281 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallacd1b182015-12-17 11:43:20 -08002282 if hosts[ controller ]:
2283 for host in hosts[ controller ]:
2284 if host is None or host.get( 'ipAddresses', [] ) == []:
2285 main.log.error(
2286 "Error with host ipAddresses on controller" +
2287 controllerStr + ": " + str( host ) )
2288 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002289 ports = []
2290 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002291 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002292 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002293 name="ports-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002294 args=[ main.CLIs[ i ].ports, [ None ] ],
2295 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002296 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002297 threads.append( t )
2298 t.start()
2299
2300 for t in threads:
2301 t.join()
2302 ports.append( t.result )
2303 links = []
2304 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002305 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002306 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002307 name="links-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002308 args=[ main.CLIs[ i ].links, [ None ] ],
2309 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002310 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002311 threads.append( t )
2312 t.start()
2313
2314 for t in threads:
2315 t.join()
2316 links.append( t.result )
2317 clusters = []
2318 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002319 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002320 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002321 name="clusters-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002322 args=[ main.CLIs[ i ].clusters, [ None ] ],
2323 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002324 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002325 threads.append( t )
2326 t.start()
2327
2328 for t in threads:
2329 t.join()
2330 clusters.append( t.result )
2331
2332 elapsed = time.time() - startTime
2333 cliTime = time.time() - cliStart
2334 print "Elapsed time: " + str( elapsed )
2335 print "CLI time: " + str( cliTime )
2336
Jon Hall6e709752016-02-01 13:38:46 -08002337 if all( e is None for e in devices ) and\
2338 all( e is None for e in hosts ) and\
2339 all( e is None for e in ports ) and\
2340 all( e is None for e in links ) and\
2341 all( e is None for e in clusters ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002342 topoFailMsg = "Could not get topology from ONOS"
2343 main.log.error( topoFailMsg )
2344 continue # Try again, No use trying to compare
Jon Hall6e709752016-02-01 13:38:46 -08002345
Jon Hall5cf14d52015-07-16 12:15:19 -07002346 mnSwitches = main.Mininet1.getSwitches()
2347 mnLinks = main.Mininet1.getLinks()
2348 mnHosts = main.Mininet1.getHosts()
Jon Halla440e872016-03-31 15:15:50 -07002349 for controller in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002350 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002351 if devices[ controller ] and ports[ controller ] and\
Jon Hallf37d44d2017-05-24 10:37:30 -07002352 "Error" not in devices[ controller ] and\
2353 "Error" not in ports[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002354
Jon Hallc6793552016-01-19 14:18:37 -08002355 try:
2356 currentDevicesResult = main.Mininet1.compareSwitches(
2357 mnSwitches,
2358 json.loads( devices[ controller ] ),
2359 json.loads( ports[ controller ] ) )
2360 except ( TypeError, ValueError ) as e:
2361 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
2362 devices[ controller ], ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002363 else:
2364 currentDevicesResult = main.FALSE
2365 utilities.assert_equals( expect=main.TRUE,
2366 actual=currentDevicesResult,
2367 onpass="ONOS" + controllerStr +
2368 " Switches view is correct",
2369 onfail="ONOS" + controllerStr +
2370 " Switches view is incorrect" )
2371
2372 if links[ controller ] and "Error" not in links[ controller ]:
2373 currentLinksResult = main.Mininet1.compareLinks(
2374 mnSwitches, mnLinks,
2375 json.loads( links[ controller ] ) )
2376 else:
2377 currentLinksResult = main.FALSE
2378 utilities.assert_equals( expect=main.TRUE,
2379 actual=currentLinksResult,
2380 onpass="ONOS" + controllerStr +
2381 " links view is correct",
2382 onfail="ONOS" + controllerStr +
2383 " links view is incorrect" )
Jon Hall657cdf62015-12-17 14:40:51 -08002384 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002385 currentHostsResult = main.Mininet1.compareHosts(
2386 mnHosts,
2387 hosts[ controller ] )
Jon Hall13b446e2016-01-05 12:17:01 -08002388 elif hosts[ controller ] == []:
2389 currentHostsResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002390 else:
2391 currentHostsResult = main.FALSE
2392 utilities.assert_equals( expect=main.TRUE,
2393 actual=currentHostsResult,
2394 onpass="ONOS" + controllerStr +
2395 " hosts exist in Mininet",
2396 onfail="ONOS" + controllerStr +
2397 " hosts don't match Mininet" )
2398 # CHECKING HOST ATTACHMENT POINTS
2399 hostAttachment = True
Jon Halla440e872016-03-31 15:15:50 -07002400 zeroHosts = False
Jon Hall5cf14d52015-07-16 12:15:19 -07002401 # FIXME: topo-HA/obelisk specific mappings:
2402 # key is mac and value is dpid
2403 mappings = {}
2404 for i in range( 1, 29 ): # hosts 1 through 28
2405 # set up correct variables:
Jon Hallf37d44d2017-05-24 10:37:30 -07002406 macId = "00:" * 5 + hex( i ).split( "0x" )[ 1 ].upper().zfill( 2 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002407 if i == 1:
Jon Hallf37d44d2017-05-24 10:37:30 -07002408 deviceId = "1000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002409 elif i == 2:
Jon Hallf37d44d2017-05-24 10:37:30 -07002410 deviceId = "2000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002411 elif i == 3:
Jon Hallf37d44d2017-05-24 10:37:30 -07002412 deviceId = "3000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002413 elif i == 4:
Jon Hallf37d44d2017-05-24 10:37:30 -07002414 deviceId = "3004".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002415 elif i == 5:
Jon Hallf37d44d2017-05-24 10:37:30 -07002416 deviceId = "5000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002417 elif i == 6:
Jon Hallf37d44d2017-05-24 10:37:30 -07002418 deviceId = "6000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002419 elif i == 7:
Jon Hallf37d44d2017-05-24 10:37:30 -07002420 deviceId = "6007".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002421 elif i >= 8 and i <= 17:
2422 dpid = '3' + str( i ).zfill( 3 )
Jon Hallf37d44d2017-05-24 10:37:30 -07002423 deviceId = dpid.zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002424 elif i >= 18 and i <= 27:
2425 dpid = '6' + str( i ).zfill( 3 )
Jon Hallf37d44d2017-05-24 10:37:30 -07002426 deviceId = dpid.zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002427 elif i == 28:
Jon Hallf37d44d2017-05-24 10:37:30 -07002428 deviceId = "2800".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002429 mappings[ macId ] = deviceId
Jon Halld8f6de82015-12-17 17:04:34 -08002430 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002431 if hosts[ controller ] == []:
2432 main.log.warn( "There are no hosts discovered" )
Jon Halla440e872016-03-31 15:15:50 -07002433 zeroHosts = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002434 else:
2435 for host in hosts[ controller ]:
2436 mac = None
2437 location = None
2438 device = None
2439 port = None
2440 try:
2441 mac = host.get( 'mac' )
2442 assert mac, "mac field could not be found for this host object"
2443
2444 location = host.get( 'location' )
2445 assert location, "location field could not be found for this host object"
2446
2447 # Trim the protocol identifier off deviceId
Jon Hallf37d44d2017-05-24 10:37:30 -07002448 device = str( location.get( 'elementId' ) ).split( ':' )[ 1 ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002449 assert device, "elementId field could not be found for this host location object"
2450
2451 port = location.get( 'port' )
2452 assert port, "port field could not be found for this host location object"
2453
2454 # Now check if this matches where they should be
2455 if mac and device and port:
2456 if str( port ) != "1":
2457 main.log.error( "The attachment port is incorrect for " +
2458 "host " + str( mac ) +
Jon Hallf37d44d2017-05-24 10:37:30 -07002459 ". Expected: 1 Actual: " + str( port ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002460 hostAttachment = False
2461 if device != mappings[ str( mac ) ]:
2462 main.log.error( "The attachment device is incorrect for " +
2463 "host " + str( mac ) +
2464 ". Expected: " + mappings[ str( mac ) ] +
2465 " Actual: " + device )
2466 hostAttachment = False
2467 else:
2468 hostAttachment = False
2469 except AssertionError:
2470 main.log.exception( "Json object not as expected" )
2471 main.log.error( repr( host ) )
2472 hostAttachment = False
2473 else:
2474 main.log.error( "No hosts json output or \"Error\"" +
2475 " in output. hosts = " +
2476 repr( hosts[ controller ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002477 if zeroHosts is False:
Jon Hall5cf14d52015-07-16 12:15:19 -07002478 # TODO: Find a way to know if there should be hosts in a
2479 # given point of the test
2480 hostAttachment = True
2481
2482 # END CHECKING HOST ATTACHMENT POINTS
2483 devicesResults = devicesResults and currentDevicesResult
2484 linksResults = linksResults and currentLinksResult
2485 hostsResults = hostsResults and currentHostsResult
2486 hostAttachmentResults = hostAttachmentResults and\
2487 hostAttachment
2488 topoResult = ( devicesResults and linksResults
2489 and hostsResults and ipResult and
2490 hostAttachmentResults )
Jon Halle9b1fa32015-12-08 15:32:21 -08002491 utilities.assert_equals( expect=True,
2492 actual=topoResult,
2493 onpass="ONOS topology matches Mininet",
Jon Hall6e709752016-02-01 13:38:46 -08002494 onfail=topoFailMsg )
Jon Halle9b1fa32015-12-08 15:32:21 -08002495 # End of While loop to pull ONOS state
Jon Hall5cf14d52015-07-16 12:15:19 -07002496
2497 # Compare json objects for hosts and dataplane clusters
2498
2499 # hosts
2500 main.step( "Hosts view is consistent across all ONOS nodes" )
2501 consistentHostsResult = main.TRUE
2502 for controller in range( len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002503 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall13b446e2016-01-05 12:17:01 -08002504 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002505 if hosts[ controller ] == hosts[ 0 ]:
2506 continue
2507 else: # hosts not consistent
2508 main.log.error( "hosts from ONOS" + controllerStr +
2509 " is inconsistent with ONOS1" )
2510 main.log.warn( repr( hosts[ controller ] ) )
2511 consistentHostsResult = main.FALSE
2512
2513 else:
2514 main.log.error( "Error in getting ONOS hosts from ONOS" +
2515 controllerStr )
2516 consistentHostsResult = main.FALSE
2517 main.log.warn( "ONOS" + controllerStr +
2518 " hosts response: " +
2519 repr( hosts[ controller ] ) )
2520 utilities.assert_equals(
2521 expect=main.TRUE,
2522 actual=consistentHostsResult,
2523 onpass="Hosts view is consistent across all ONOS nodes",
2524 onfail="ONOS nodes have different views of hosts" )
2525
2526 main.step( "Hosts information is correct" )
2527 hostsResults = hostsResults and ipResult
2528 utilities.assert_equals(
2529 expect=main.TRUE,
2530 actual=hostsResults,
2531 onpass="Host information is correct",
2532 onfail="Host information is incorrect" )
2533
2534 main.step( "Host attachment points to the network" )
2535 utilities.assert_equals(
2536 expect=True,
2537 actual=hostAttachmentResults,
2538 onpass="Hosts are correctly attached to the network",
2539 onfail="ONOS did not correctly attach hosts to the network" )
2540
2541 # Strongly connected clusters of devices
2542 main.step( "Clusters view is consistent across all ONOS nodes" )
2543 consistentClustersResult = main.TRUE
2544 for controller in range( len( clusters ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002545 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002546 if "Error" not in clusters[ controller ]:
2547 if clusters[ controller ] == clusters[ 0 ]:
2548 continue
2549 else: # clusters not consistent
2550 main.log.error( "clusters from ONOS" +
2551 controllerStr +
2552 " is inconsistent with ONOS1" )
2553 consistentClustersResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002554 else:
2555 main.log.error( "Error in getting dataplane clusters " +
2556 "from ONOS" + controllerStr )
2557 consistentClustersResult = main.FALSE
2558 main.log.warn( "ONOS" + controllerStr +
2559 " clusters response: " +
2560 repr( clusters[ controller ] ) )
2561 utilities.assert_equals(
2562 expect=main.TRUE,
2563 actual=consistentClustersResult,
2564 onpass="Clusters view is consistent across all ONOS nodes",
2565 onfail="ONOS nodes have different views of clusters" )
Jon Hall64948022016-05-12 13:38:50 -07002566 if not consistentClustersResult:
2567 main.log.debug( clusters )
Jon Hall5cf14d52015-07-16 12:15:19 -07002568
2569 main.step( "There is only one SCC" )
2570 # there should always only be one cluster
2571 try:
2572 numClusters = len( json.loads( clusters[ 0 ] ) )
2573 except ( ValueError, TypeError ):
2574 main.log.exception( "Error parsing clusters[0]: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07002575 repr( clusters[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002576 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07002577 clusterResults = main.FALSE
2578 if numClusters == 1:
2579 clusterResults = main.TRUE
2580 utilities.assert_equals(
2581 expect=1,
2582 actual=numClusters,
2583 onpass="ONOS shows 1 SCC",
2584 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2585
2586 topoResult = ( devicesResults and linksResults
2587 and hostsResults and consistentHostsResult
2588 and consistentClustersResult and clusterResults
2589 and ipResult and hostAttachmentResults )
2590
2591 topoResult = topoResult and int( count <= 2 )
2592 note = "note it takes about " + str( int( cliTime ) ) + \
2593 " seconds for the test to make all the cli calls to fetch " +\
2594 "the topology from each ONOS instance"
2595 main.log.info(
2596 "Very crass estimate for topology discovery/convergence( " +
2597 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2598 str( count ) + " tries" )
2599
2600 main.step( "Device information is correct" )
2601 utilities.assert_equals(
2602 expect=main.TRUE,
2603 actual=devicesResults,
2604 onpass="Device information is correct",
2605 onfail="Device information is incorrect" )
2606
2607 main.step( "Links are correct" )
2608 utilities.assert_equals(
2609 expect=main.TRUE,
2610 actual=linksResults,
2611 onpass="Link are correct",
2612 onfail="Links are incorrect" )
2613
Jon Halla440e872016-03-31 15:15:50 -07002614 main.step( "Hosts are correct" )
2615 utilities.assert_equals(
2616 expect=main.TRUE,
2617 actual=hostsResults,
2618 onpass="Hosts are correct",
2619 onfail="Hosts are incorrect" )
2620
Jon Hall5cf14d52015-07-16 12:15:19 -07002621 # FIXME: move this to an ONOS state case
2622 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -07002623 nodeResults = utilities.retry( main.HA.nodesCheck,
2624 False,
Jon Hallf37d44d2017-05-24 10:37:30 -07002625 args=[ main.activeNodes ],
Jon Hall41d39f12016-04-11 22:54:35 -07002626 attempts=5 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002627
Jon Hall41d39f12016-04-11 22:54:35 -07002628 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Hall5cf14d52015-07-16 12:15:19 -07002629 onpass="Nodes check successful",
2630 onfail="Nodes check NOT successful" )
Jon Halla440e872016-03-31 15:15:50 -07002631 if not nodeResults:
Jon Hall41d39f12016-04-11 22:54:35 -07002632 for i in main.activeNodes:
Jon Halla440e872016-03-31 15:15:50 -07002633 main.log.debug( "{} components not ACTIVE: \n{}".format(
Jon Hallf37d44d2017-05-24 10:37:30 -07002634 main.CLIs[ i ].name,
2635 main.CLIs[ i ].sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002636
Jon Halld2871c22016-07-26 11:01:14 -07002637 if not topoResult:
2638 main.cleanup()
2639 main.exit()
2640
Jon Hall5cf14d52015-07-16 12:15:19 -07002641 def CASE9( self, main ):
2642 """
2643 Link s3-s28 down
2644 """
2645 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002646 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002647 assert main, "main not defined"
2648 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002649 assert main.CLIs, "main.CLIs not defined"
2650 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002651 # NOTE: You should probably run a topology check after this
2652
2653 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2654
2655 description = "Turn off a link to ensure that Link Discovery " +\
2656 "is working properly"
2657 main.case( description )
2658
2659 main.step( "Kill Link between s3 and s28" )
2660 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2661 main.log.info( "Waiting " + str( linkSleep ) +
2662 " seconds for link down to be discovered" )
2663 time.sleep( linkSleep )
2664 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2665 onpass="Link down successful",
2666 onfail="Failed to bring link down" )
2667 # TODO do some sort of check here
2668
2669 def CASE10( self, main ):
2670 """
2671 Link s3-s28 up
2672 """
2673 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002674 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002675 assert main, "main not defined"
2676 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002677 assert main.CLIs, "main.CLIs not defined"
2678 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002679 # NOTE: You should probably run a topology check after this
2680
2681 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2682
2683 description = "Restore a link to ensure that Link Discovery is " + \
2684 "working properly"
2685 main.case( description )
2686
2687 main.step( "Bring link between s3 and s28 back up" )
2688 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2689 main.log.info( "Waiting " + str( linkSleep ) +
2690 " seconds for link up to be discovered" )
2691 time.sleep( linkSleep )
2692 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2693 onpass="Link up successful",
2694 onfail="Failed to bring link up" )
2695 # TODO do some sort of check here
2696
2697 def CASE11( self, main ):
2698 """
2699 Switch Down
2700 """
2701 # NOTE: You should probably run a topology check after this
2702 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002703 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002704 assert main, "main not defined"
2705 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002706 assert main.CLIs, "main.CLIs not defined"
2707 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002708
2709 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2710
2711 description = "Killing a switch to ensure it is discovered correctly"
Jon Hallf37d44d2017-05-24 10:37:30 -07002712 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002713 main.case( description )
2714 switch = main.params[ 'kill' ][ 'switch' ]
2715 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2716
2717 # TODO: Make this switch parameterizable
2718 main.step( "Kill " + switch )
2719 main.log.info( "Deleting " + switch )
2720 main.Mininet1.delSwitch( switch )
2721 main.log.info( "Waiting " + str( switchSleep ) +
2722 " seconds for switch down to be discovered" )
2723 time.sleep( switchSleep )
Jon Halla440e872016-03-31 15:15:50 -07002724 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002725 # Peek at the deleted switch
2726 main.log.warn( str( device ) )
2727 result = main.FALSE
2728 if device and device[ 'available' ] is False:
2729 result = main.TRUE
2730 utilities.assert_equals( expect=main.TRUE, actual=result,
2731 onpass="Kill switch successful",
2732 onfail="Failed to kill switch?" )
2733
2734 def CASE12( self, main ):
2735 """
2736 Switch Up
2737 """
2738 # NOTE: You should probably run a topology check after this
2739 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002740 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002741 assert main, "main not defined"
2742 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002743 assert main.CLIs, "main.CLIs not defined"
2744 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002745 assert ONOS1Port, "ONOS1Port not defined"
2746 assert ONOS2Port, "ONOS2Port not defined"
2747 assert ONOS3Port, "ONOS3Port not defined"
2748 assert ONOS4Port, "ONOS4Port not defined"
2749 assert ONOS5Port, "ONOS5Port not defined"
2750 assert ONOS6Port, "ONOS6Port not defined"
2751 assert ONOS7Port, "ONOS7Port not defined"
2752
2753 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2754 switch = main.params[ 'kill' ][ 'switch' ]
2755 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2756 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hallf37d44d2017-05-24 10:37:30 -07002757 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002758 description = "Adding a switch to ensure it is discovered correctly"
2759 main.case( description )
2760
2761 main.step( "Add back " + switch )
2762 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2763 for peer in links:
2764 main.Mininet1.addLink( switch, peer )
Jon Halla440e872016-03-31 15:15:50 -07002765 ipList = [ node.ip_address for node in main.nodes ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002766 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2767 main.log.info( "Waiting " + str( switchSleep ) +
2768 " seconds for switch up to be discovered" )
2769 time.sleep( switchSleep )
Jon Halla440e872016-03-31 15:15:50 -07002770 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002771 # Peek at the deleted switch
2772 main.log.warn( str( device ) )
2773 result = main.FALSE
2774 if device and device[ 'available' ]:
2775 result = main.TRUE
2776 utilities.assert_equals( expect=main.TRUE, actual=result,
2777 onpass="add switch successful",
2778 onfail="Failed to add switch?" )
2779
2780 def CASE13( self, main ):
2781 """
2782 Clean up
2783 """
2784 import os
2785 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002786 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002787 assert main, "main not defined"
2788 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002789 assert main.CLIs, "main.CLIs not defined"
2790 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002791
2792 # printing colors to terminal
2793 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2794 'blue': '\033[94m', 'green': '\033[92m',
2795 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2796 main.case( "Test Cleanup" )
2797 main.step( "Killing tcpdumps" )
2798 main.Mininet2.stopTcpdump()
2799
2800 testname = main.TEST
Jon Hall5ec6b1b2015-09-17 18:20:14 -07002801 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall5cf14d52015-07-16 12:15:19 -07002802 main.step( "Copying MN pcap and ONOS log files to test station" )
2803 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2804 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002805 # NOTE: MN Pcap file is being saved to logdir.
2806 # We scp this file as MN and TestON aren't necessarily the same vm
2807
2808 # FIXME: To be replaced with a Jenkin's post script
Jon Hall5cf14d52015-07-16 12:15:19 -07002809 # TODO: Load these from params
2810 # NOTE: must end in /
2811 logFolder = "/opt/onos/log/"
2812 logFiles = [ "karaf.log", "karaf.log.1" ]
2813 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002814 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002815 for node in main.nodes:
Jon Hall6e709752016-02-01 13:38:46 -08002816 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002817 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2818 logFolder + f, dstName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002819 # std*.log's
2820 # NOTE: must end in /
2821 logFolder = "/opt/onos/var/"
2822 logFiles = [ "stderr.log", "stdout.log" ]
2823 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002824 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002825 for node in main.nodes:
Jon Hall6e709752016-02-01 13:38:46 -08002826 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002827 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2828 logFolder + f, dstName )
Jon Hall5ec6b1b2015-09-17 18:20:14 -07002829 else:
2830 main.log.debug( "skipping saving log files" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002831
2832 main.step( "Stopping Mininet" )
2833 mnResult = main.Mininet1.stopNet()
2834 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2835 onpass="Mininet stopped",
2836 onfail="MN cleanup NOT successful" )
2837
2838 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002839 for node in main.nodes:
Jon Hall5ec6b1b2015-09-17 18:20:14 -07002840 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2841 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002842
2843 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07002844 timerLog = open( main.logdir + "/Timers.csv", 'w' )
Jon Hall5cf14d52015-07-16 12:15:19 -07002845 main.log.error( ", ".join( labels ) + "\n" + ", ".join( data ) )
2846 timerLog.write( ", ".join( labels ) + "\n" + ", ".join( data ) )
2847 timerLog.close()
Jon Hallf37d44d2017-05-24 10:37:30 -07002848 except NameError as e:
2849 main.log.exception( e )
Jon Hall5cf14d52015-07-16 12:15:19 -07002850
2851 def CASE14( self, main ):
2852 """
2853 start election app on all onos nodes
2854 """
Jon Halle1a3b752015-07-22 13:02:46 -07002855 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002856 assert main, "main not defined"
2857 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002858 assert main.CLIs, "main.CLIs not defined"
2859 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002860
Jon Hallf37d44d2017-05-24 10:37:30 -07002861 main.case( "Start Leadership Election app" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002862 main.step( "Install leadership election app" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002863 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Halla440e872016-03-31 15:15:50 -07002864 appResult = onosCli.activateApp( "org.onosproject.election" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002865 utilities.assert_equals(
2866 expect=main.TRUE,
2867 actual=appResult,
2868 onpass="Election app installed",
2869 onfail="Something went wrong with installing Leadership election" )
2870
2871 main.step( "Run for election on each node" )
Jon Halla440e872016-03-31 15:15:50 -07002872 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002873 main.CLIs[ i ].electionTestRun()
2874 time.sleep( 5 )
2875 activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
Jon Hall25463a82016-04-13 14:03:52 -07002876 sameResult, leaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall5cf14d52015-07-16 12:15:19 -07002877 utilities.assert_equals(
Jon Hall25463a82016-04-13 14:03:52 -07002878 expect=True,
2879 actual=sameResult,
2880 onpass="All nodes see the same leaderboards",
2881 onfail="Inconsistent leaderboards" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002882
Jon Hall25463a82016-04-13 14:03:52 -07002883 if sameResult:
2884 leader = leaders[ 0 ][ 0 ]
Jon Hallf37d44d2017-05-24 10:37:30 -07002885 if main.nodes[ main.activeNodes[ 0 ] ].ip_address in leader:
Jon Hall25463a82016-04-13 14:03:52 -07002886 correctLeader = True
2887 else:
2888 correctLeader = False
2889 main.step( "First node was elected leader" )
2890 utilities.assert_equals(
2891 expect=True,
2892 actual=correctLeader,
2893 onpass="Correct leader was elected",
2894 onfail="Incorrect leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002895
2896 def CASE15( self, main ):
2897 """
2898 Check that Leadership Election is still functional
acsmars9475b1c2015-08-28 18:02:08 -07002899 15.1 Run election on each node
2900 15.2 Check that each node has the same leaders and candidates
2901 15.3 Find current leader and withdraw
2902 15.4 Check that a new node was elected leader
2903 15.5 Check that that new leader was the candidate of old leader
2904 15.6 Run for election on old leader
2905 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2906 15.8 Make sure that the old leader was added to the candidate list
2907
2908 old and new variable prefixes refer to data from before vs after
2909 withdrawl and later before withdrawl vs after re-election
Jon Hall5cf14d52015-07-16 12:15:19 -07002910 """
2911 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002912 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002913 assert main, "main not defined"
2914 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002915 assert main.CLIs, "main.CLIs not defined"
2916 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002917
Jon Hall5cf14d52015-07-16 12:15:19 -07002918 description = "Check that Leadership Election is still functional"
2919 main.case( description )
Jon Halla440e872016-03-31 15:15:50 -07002920 # NOTE: Need to re-run after restarts since being a canidate is not persistant
acsmars9475b1c2015-08-28 18:02:08 -07002921
Jon Halla440e872016-03-31 15:15:50 -07002922 oldLeaders = [] # list of lists of each nodes' candidates before
2923 newLeaders = [] # list of lists of each nodes' candidates after
acsmars9475b1c2015-08-28 18:02:08 -07002924 oldLeader = '' # the old leader from oldLeaders, None if not same
2925 newLeader = '' # the new leaders fron newLoeaders, None if not same
2926 oldLeaderCLI = None # the CLI of the old leader used for re-electing
acsmars71adceb2015-08-31 15:09:26 -07002927 expectNoLeader = False # True when there is only one leader
2928 if main.numCtrls == 1:
2929 expectNoLeader = True
acsmars9475b1c2015-08-28 18:02:08 -07002930
Jon Hall5cf14d52015-07-16 12:15:19 -07002931 main.step( "Run for election on each node" )
acsmars9475b1c2015-08-28 18:02:08 -07002932 electionResult = main.TRUE
2933
Jon Halla440e872016-03-31 15:15:50 -07002934 for i in main.activeNodes: # run test election on each node
Jon Hallf37d44d2017-05-24 10:37:30 -07002935 if main.CLIs[ i ].electionTestRun() == main.FALSE:
acsmars9475b1c2015-08-28 18:02:08 -07002936 electionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002937 utilities.assert_equals(
2938 expect=main.TRUE,
acsmars9475b1c2015-08-28 18:02:08 -07002939 actual=electionResult,
2940 onpass="All nodes successfully ran for leadership",
2941 onfail="At least one node failed to run for leadership" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002942
acsmars3a72bde2015-09-02 14:16:22 -07002943 if electionResult == main.FALSE:
2944 main.log.error(
2945 "Skipping Test Case because Election Test App isn't loaded" )
2946 main.skipCase()
2947
acsmars9475b1c2015-08-28 18:02:08 -07002948 main.step( "Check that each node shows the same leader and candidates" )
Jon Halla440e872016-03-31 15:15:50 -07002949 failMessage = "Nodes have different leaderboards"
Jon Hallf37d44d2017-05-24 10:37:30 -07002950 activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
Jon Hall41d39f12016-04-11 22:54:35 -07002951 sameResult, oldLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Halla440e872016-03-31 15:15:50 -07002952 if sameResult:
2953 oldLeader = oldLeaders[ 0 ][ 0 ]
2954 main.log.warn( oldLeader )
acsmars9475b1c2015-08-28 18:02:08 -07002955 else:
Jon Halla440e872016-03-31 15:15:50 -07002956 oldLeader = None
Jon Hall5cf14d52015-07-16 12:15:19 -07002957 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002958 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002959 actual=sameResult,
Jon Halla440e872016-03-31 15:15:50 -07002960 onpass="Leaderboards are consistent for the election topic",
acsmars9475b1c2015-08-28 18:02:08 -07002961 onfail=failMessage )
Jon Hall5cf14d52015-07-16 12:15:19 -07002962
2963 main.step( "Find current leader and withdraw" )
acsmars9475b1c2015-08-28 18:02:08 -07002964 withdrawResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002965 # do some sanity checking on leader before using it
acsmars9475b1c2015-08-28 18:02:08 -07002966 if oldLeader is None:
2967 main.log.error( "Leadership isn't consistent." )
2968 withdrawResult = main.FALSE
2969 # Get the CLI of the oldLeader
Jon Halla440e872016-03-31 15:15:50 -07002970 for i in main.activeNodes:
acsmars9475b1c2015-08-28 18:02:08 -07002971 if oldLeader == main.nodes[ i ].ip_address:
2972 oldLeaderCLI = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002973 break
2974 else: # FOR/ELSE statement
2975 main.log.error( "Leader election, could not find current leader" )
2976 if oldLeader:
acsmars9475b1c2015-08-28 18:02:08 -07002977 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall5cf14d52015-07-16 12:15:19 -07002978 utilities.assert_equals(
2979 expect=main.TRUE,
2980 actual=withdrawResult,
2981 onpass="Node was withdrawn from election",
2982 onfail="Node was not withdrawn from election" )
2983
acsmars9475b1c2015-08-28 18:02:08 -07002984 main.step( "Check that a new node was elected leader" )
acsmars9475b1c2015-08-28 18:02:08 -07002985 failMessage = "Nodes have different leaders"
acsmars9475b1c2015-08-28 18:02:08 -07002986 # Get new leaders and candidates
Jon Hall41d39f12016-04-11 22:54:35 -07002987 newLeaderResult, newLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall3a7843a2016-04-12 03:01:09 -07002988 newLeader = None
Jon Halla440e872016-03-31 15:15:50 -07002989 if newLeaderResult:
Jon Hall3a7843a2016-04-12 03:01:09 -07002990 if newLeaders[ 0 ][ 0 ] == 'none':
2991 main.log.error( "No leader was elected on at least 1 node" )
2992 if not expectNoLeader:
2993 newLeaderResult = False
Jon Hall25463a82016-04-13 14:03:52 -07002994 newLeader = newLeaders[ 0 ][ 0 ]
acsmars71adceb2015-08-31 15:09:26 -07002995
acsmars9475b1c2015-08-28 18:02:08 -07002996 # Check that the new leader is not the older leader, which was withdrawn
2997 if newLeader == oldLeader:
Jon Halla440e872016-03-31 15:15:50 -07002998 newLeaderResult = False
Jon Hall6e709752016-02-01 13:38:46 -08002999 main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
Jon Hallf37d44d2017-05-24 10:37:30 -07003000 " as the current leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003001 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003002 expect=True,
acsmars9475b1c2015-08-28 18:02:08 -07003003 actual=newLeaderResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003004 onpass="Leadership election passed",
3005 onfail="Something went wrong with Leadership election" )
3006
Jon Halla440e872016-03-31 15:15:50 -07003007 main.step( "Check that that new leader was the candidate of old leader" )
Jon Hall6e709752016-02-01 13:38:46 -08003008 # candidates[ 2 ] should become the top candidate after withdrawl
acsmars9475b1c2015-08-28 18:02:08 -07003009 correctCandidateResult = main.TRUE
acsmars71adceb2015-08-31 15:09:26 -07003010 if expectNoLeader:
3011 if newLeader == 'none':
3012 main.log.info( "No leader expected. None found. Pass" )
3013 correctCandidateResult = main.TRUE
3014 else:
3015 main.log.info( "Expected no leader, got: " + str( newLeader ) )
3016 correctCandidateResult = main.FALSE
Jon Hallf37d44d2017-05-24 10:37:30 -07003017 elif len( oldLeaders[ 0 ] ) >= 3:
Jon Halla440e872016-03-31 15:15:50 -07003018 if newLeader == oldLeaders[ 0 ][ 2 ]:
3019 # correct leader was elected
3020 correctCandidateResult = main.TRUE
3021 else:
3022 correctCandidateResult = main.FALSE
3023 main.log.error( "Candidate {} was elected. {} should have had priority.".format(
3024 newLeader, oldLeaders[ 0 ][ 2 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08003025 else:
3026 main.log.warn( "Could not determine who should be the correct leader" )
Jon Halla440e872016-03-31 15:15:50 -07003027 main.log.debug( oldLeaders[ 0 ] )
Jon Hall6e709752016-02-01 13:38:46 -08003028 correctCandidateResult = main.FALSE
acsmars9475b1c2015-08-28 18:02:08 -07003029 utilities.assert_equals(
3030 expect=main.TRUE,
3031 actual=correctCandidateResult,
3032 onpass="Correct Candidate Elected",
3033 onfail="Incorrect Candidate Elected" )
3034
Jon Hall5cf14d52015-07-16 12:15:19 -07003035 main.step( "Run for election on old leader( just so everyone " +
3036 "is in the hat )" )
acsmars9475b1c2015-08-28 18:02:08 -07003037 if oldLeaderCLI is not None:
3038 runResult = oldLeaderCLI.electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07003039 else:
acsmars9475b1c2015-08-28 18:02:08 -07003040 main.log.error( "No old leader to re-elect" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003041 runResult = main.FALSE
3042 utilities.assert_equals(
3043 expect=main.TRUE,
3044 actual=runResult,
3045 onpass="App re-ran for election",
3046 onfail="App failed to run for election" )
Jon Halla440e872016-03-31 15:15:50 -07003047
acsmars9475b1c2015-08-28 18:02:08 -07003048 main.step(
3049 "Check that oldLeader is a candidate, and leader if only 1 node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003050 # verify leader didn't just change
Jon Halla440e872016-03-31 15:15:50 -07003051 # Get new leaders and candidates
3052 reRunLeaders = []
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003053 time.sleep( 5 ) # Paremterize
Jon Hall41d39f12016-04-11 22:54:35 -07003054 positionResult, reRunLeaders = main.HA.consistentLeaderboards( activeCLIs )
acsmars71adceb2015-08-31 15:09:26 -07003055
acsmars9475b1c2015-08-28 18:02:08 -07003056 # Check that the re-elected node is last on the candidate List
Jon Hallf37d44d2017-05-24 10:37:30 -07003057 if not reRunLeaders[ 0 ]:
Jon Hall3a7843a2016-04-12 03:01:09 -07003058 positionResult = main.FALSE
3059 elif oldLeader != reRunLeaders[ 0 ][ -1 ]:
Jon Hallf37d44d2017-05-24 10:37:30 -07003060 main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader ),
Jon Halla440e872016-03-31 15:15:50 -07003061 str( reRunLeaders[ 0 ] ) ) )
acsmars9475b1c2015-08-28 18:02:08 -07003062 positionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07003063 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003064 expect=True,
acsmars9475b1c2015-08-28 18:02:08 -07003065 actual=positionResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003066 onpass="Old leader successfully re-ran for election",
3067 onfail="Something went wrong with Leadership election after " +
3068 "the old leader re-ran for election" )
3069
3070 def CASE16( self, main ):
3071 """
3072 Install Distributed Primitives app
3073 """
3074 import time
Jon Halle1a3b752015-07-22 13:02:46 -07003075 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003076 assert main, "main not defined"
3077 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003078 assert main.CLIs, "main.CLIs not defined"
3079 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003080
3081 # Variables for the distributed primitives tests
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003082 main.pCounterName = "TestON-Partitions"
3083 main.pCounterValue = 0
Jon Hallf37d44d2017-05-24 10:37:30 -07003084 main.onosSet = set( [] )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003085 main.onosSetName = "TestON-set"
Jon Hall5cf14d52015-07-16 12:15:19 -07003086
3087 description = "Install Primitives app"
3088 main.case( description )
3089 main.step( "Install Primitives app" )
3090 appName = "org.onosproject.distributedprimitives"
Jon Hallf37d44d2017-05-24 10:37:30 -07003091 node = main.activeNodes[ 0 ]
3092 appResults = main.CLIs[ node ].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07003093 utilities.assert_equals( expect=main.TRUE,
3094 actual=appResults,
3095 onpass="Primitives app activated",
3096 onfail="Primitives app not activated" )
3097 time.sleep( 5 ) # To allow all nodes to activate
3098
3099 def CASE17( self, main ):
3100 """
3101 Check for basic functionality with distributed primitives
3102 """
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003103 main.HA.CASE17( main )