blob: 6b863787118ae33137022d011827546ffcf6bfb7 [file] [log] [blame]
Jon Hall5cf14d52015-07-16 12:15:19 -07001"""
2Description: This test is to determine if ONOS can handle
3 a minority of it's nodes restarting
4
5List of test cases:
6CASE1: Compile ONOS and push it to the test machines
7CASE2: Assign devices to controllers
8CASE21: Assign mastership to controllers
9CASE3: Assign intents
10CASE4: Ping across added host intents
11CASE5: Reading state of ONOS
Jon Hallb3ed8ed2015-10-28 16:43:55 -070012CASE61: The Failure inducing case.
13CASE62: The Failure recovery case.
Jon Hall5cf14d52015-07-16 12:15:19 -070014CASE7: Check state after control plane failure
15CASE8: Compare topo
16CASE9: Link s3-s28 down
17CASE10: Link s3-s28 up
18CASE11: Switch down
19CASE12: Switch up
20CASE13: Clean up
21CASE14: start election app on all onos nodes
22CASE15: Check that Leadership Election is still functional
23CASE16: Install Distributed Primitives app
24CASE17: Check for basic functionality with distributed primitives
25"""
Jon Hallb3ed8ed2015-10-28 16:43:55 -070026class HAstopNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -070027
28 def __init__( self ):
29 self.default = ''
30
31 def CASE1( self, main ):
32 """
33 CASE1 is to compile ONOS and push it to the test machines
34
35 Startup sequence:
36 cell <name>
37 onos-verify-cell
38 NOTE: temporary - onos-remove-raft-logs
39 onos-uninstall
40 start mininet
41 git pull
42 mvn clean install
43 onos-package
44 onos-install -f
45 onos-wait-for-start
46 start cli sessions
47 start tcpdump
48 """
Jon Halle1a3b752015-07-22 13:02:46 -070049 import imp
Jon Hall3b489db2015-10-05 14:38:37 -070050 import pexpect
Jon Hallf3d16e72015-12-16 17:45:08 -080051 import time
Jon Halla440e872016-03-31 15:15:50 -070052 import json
Jon Hallb3ed8ed2015-10-28 16:43:55 -070053 main.log.info( "ONOS HA test: Stop a minority of ONOS nodes - " +
Jon Hall5cf14d52015-07-16 12:15:19 -070054 "initialization" )
55 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070056 main.caseExplanation = "Setup the test environment including " +\
Jon Hall5cf14d52015-07-16 12:15:19 -070057 "installing ONOS, starting Mininet and ONOS" +\
58 "cli sessions."
Jon Hall5cf14d52015-07-16 12:15:19 -070059
60 # load some variables from the params file
61 PULLCODE = False
62 if main.params[ 'Git' ] == 'True':
63 PULLCODE = True
64 gitBranch = main.params[ 'branch' ]
65 cellName = main.params[ 'ENV' ][ 'cellName' ]
66
Jon Halle1a3b752015-07-22 13:02:46 -070067 main.numCtrls = int( main.params[ 'num_controllers' ] )
Jon Hall5cf14d52015-07-16 12:15:19 -070068 if main.ONOSbench.maxNodes:
Jon Halle1a3b752015-07-22 13:02:46 -070069 if main.ONOSbench.maxNodes < main.numCtrls:
70 main.numCtrls = int( main.ONOSbench.maxNodes )
71 # set global variables
Jon Hall5cf14d52015-07-16 12:15:19 -070072 global ONOS1Port
73 global ONOS2Port
74 global ONOS3Port
75 global ONOS4Port
76 global ONOS5Port
77 global ONOS6Port
78 global ONOS7Port
Jon Halla440e872016-03-31 15:15:50 -070079 # These are for csv plotting in jenkins
80 global labels
81 global data
82 labels = []
83 data = []
Jon Hall5cf14d52015-07-16 12:15:19 -070084
85 # FIXME: just get controller port from params?
86 # TODO: do we really need all these?
87 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
88 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
89 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
90 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
91 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
92 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
93 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
94
Jon Halle1a3b752015-07-22 13:02:46 -070095 try:
Jon Hall53c5e662016-04-13 16:06:56 -070096 from tests.HA.dependencies.HA import HA
Jon Hall41d39f12016-04-11 22:54:35 -070097 main.HA = HA()
Jon Halle1a3b752015-07-22 13:02:46 -070098 except Exception as e:
99 main.log.exception( e )
100 main.cleanup()
101 main.exit()
102
103 main.CLIs = []
104 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700105 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700106 for i in range( 1, main.numCtrls + 1 ):
107 try:
108 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
109 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
110 ipList.append( main.nodes[ -1 ].ip_address )
111 except AttributeError:
112 break
Jon Hall5cf14d52015-07-16 12:15:19 -0700113
114 main.step( "Create cell file" )
115 cellAppString = main.params[ 'ENV' ][ 'appString' ]
116 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
117 main.Mininet1.ip_address,
Devin Lim461f0872017-06-05 16:49:33 -0700118 cellAppString, ipList, main.ONOScli1.user_name )
Jon Hall5cf14d52015-07-16 12:15:19 -0700119 main.step( "Applying cell variable to environment" )
120 cellResult = main.ONOSbench.setCell( cellName )
121 verifyResult = main.ONOSbench.verifyCell()
122
123 # FIXME:this is short term fix
124 main.log.info( "Removing raft logs" )
125 main.ONOSbench.onosRemoveRaftLogs()
126
127 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700128 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700129 main.ONOSbench.onosUninstall( node.ip_address )
130
131 # Make sure ONOS is DEAD
132 main.log.info( "Killing any ONOS processes" )
133 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700134 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700135 killed = main.ONOSbench.onosKill( node.ip_address )
136 killResults = killResults and killed
137
Jon Hall5cf14d52015-07-16 12:15:19 -0700138 gitPullResult = main.TRUE
139
140 main.step( "Starting Mininet" )
141 # scp topo file to mininet
142 # TODO: move to params?
143 topoName = "obelisk.py"
144 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700145 main.ONOSbench.scp( main.Mininet1,
146 filePath + topoName,
147 main.Mininet1.home,
148 direction="to" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700149 mnResult = main.Mininet1.startNet()
Jon Hall5cf14d52015-07-16 12:15:19 -0700150 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
151 onpass="Mininet Started",
152 onfail="Error starting Mininet" )
153
154 main.step( "Git checkout and pull " + gitBranch )
155 if PULLCODE:
156 main.ONOSbench.gitCheckout( gitBranch )
157 gitPullResult = main.ONOSbench.gitPull()
158 # values of 1 or 3 are good
159 utilities.assert_lesser( expect=0, actual=gitPullResult,
160 onpass="Git pull successful",
161 onfail="Git pull failed" )
162 main.ONOSbench.getVersion( report=True )
163
Jon Hall5cf14d52015-07-16 12:15:19 -0700164 # GRAPHS
165 # NOTE: important params here:
166 # job = name of Jenkins job
167 # Plot Name = Plot-HA, only can be used if multiple plots
168 # index = The number of the graph under plot name
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700169 job = "HAstopNodes"
Jon Hall5cf14d52015-07-16 12:15:19 -0700170 plotName = "Plot-HA"
Jon Hall843f8bc2016-03-18 14:28:13 -0700171 index = "2"
Jon Hall5cf14d52015-07-16 12:15:19 -0700172 graphs = '<ac:structured-macro ac:name="html">\n'
173 graphs += '<ac:plain-text-body><![CDATA[\n'
174 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Halla9845df2016-01-15 14:55:58 -0800175 '/plot/' + plotName + '/getPlot?index=' + index +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700176 '&width=500&height=300"' +\
177 'noborder="0" width="500" height="300" scrolling="yes" ' +\
178 'seamless="seamless"></iframe>\n'
179 graphs += ']]></ac:plain-text-body>\n'
180 graphs += '</ac:structured-macro>\n'
Jon Hallf37d44d2017-05-24 10:37:30 -0700181 main.log.wiki( graphs )
Jon Hall5cf14d52015-07-16 12:15:19 -0700182
183 main.step( "Creating ONOS package" )
Jon Hall3b489db2015-10-05 14:38:37 -0700184 # copy gen-partions file to ONOS
185 # NOTE: this assumes TestON and ONOS are on the same machine
Jon Hall53c5e662016-04-13 16:06:56 -0700186 srcFile = main.testDir + "/HA/dependencies/onos-gen-partitions"
Jon Hall3b489db2015-10-05 14:38:37 -0700187 dstDir = main.ONOSbench.home + "/tools/test/bin/onos-gen-partitions"
188 cpResult = main.ONOSbench.secureCopy( main.ONOSbench.user_name,
189 main.ONOSbench.ip_address,
190 srcFile,
191 dstDir,
192 pwd=main.ONOSbench.pwd,
193 direction="from" )
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" )
Jon Hall3b489db2015-10-05 14:38:37 -0700208 # clean up gen-partitions file
209 try:
210 main.ONOSbench.handle.sendline( "cd " + main.ONOSbench.home )
211 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
212 main.ONOSbench.handle.sendline( "git checkout -- tools/test/bin/onos-gen-partitions" )
213 main.ONOSbench.handle.expect( main.ONOSbench.home + "\$" )
214 main.log.info( " Cleaning custom gen partitions file, response was: \n" +
215 str( main.ONOSbench.handle.before ) )
216 except ( pexpect.TIMEOUT, pexpect.EOF ):
217 main.log.exception( "ONOSbench: pexpect exception found:" +
218 main.ONOSbench.handle.before )
219 main.cleanup()
220 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -0700221
You Wangf5de25b2017-01-06 15:13:01 -0800222 main.step( "Set up ONOS secure SSH" )
223 secureSshResult = main.TRUE
224 for node in main.nodes:
225 secureSshResult = secureSshResult and main.ONOSbench.onosSecureSSH( node=node.ip_address )
226 utilities.assert_equals( expect=main.TRUE, actual=secureSshResult,
227 onpass="Test step PASS",
228 onfail="Test step FAIL" )
229
Jon Hall5cf14d52015-07-16 12:15:19 -0700230 main.step( "Checking if ONOS is up yet" )
231 for i in range( 2 ):
232 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700233 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700234 started = main.ONOSbench.isup( node.ip_address )
235 if not started:
Jon Hallc6793552016-01-19 14:18:37 -0800236 main.log.error( node.name + " hasn't started" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700237 onosIsupResult = onosIsupResult and started
238 if onosIsupResult == main.TRUE:
239 break
240 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
241 onpass="ONOS startup successful",
242 onfail="ONOS startup failed" )
243
Jon Hall6509dbf2016-06-21 17:01:17 -0700244 main.step( "Starting ONOS CLI sessions" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700245 cliResults = main.TRUE
246 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700247 for i in range( main.numCtrls ):
Jon Hallf37d44d2017-05-24 10:37:30 -0700248 t = main.Thread( target=main.CLIs[ i ].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -0700249 name="startOnosCli-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -0700250 args=[ main.nodes[ i ].ip_address ] )
Jon Hall5cf14d52015-07-16 12:15:19 -0700251 threads.append( t )
252 t.start()
253
254 for t in threads:
255 t.join()
256 cliResults = cliResults and t.result
257 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
258 onpass="ONOS cli startup successful",
259 onfail="ONOS cli startup failed" )
260
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700261 # Create a list of active nodes for use when some nodes are stopped
262 main.activeNodes = [ i for i in range( 0, len( main.CLIs ) ) ]
263
Jon Hall5cf14d52015-07-16 12:15:19 -0700264 if main.params[ 'tcpdump' ].lower() == "true":
265 main.step( "Start Packet Capture MN" )
266 main.Mininet2.startTcpdump(
267 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
268 + "-MN.pcap",
269 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
270 port=main.params[ 'MNtcpdump' ][ 'port' ] )
271
Jon Halla440e872016-03-31 15:15:50 -0700272 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -0700273 nodeResults = utilities.retry( main.HA.nodesCheck,
274 False,
Jon Hallf37d44d2017-05-24 10:37:30 -0700275 args=[ main.activeNodes ],
Jon Hall41d39f12016-04-11 22:54:35 -0700276 attempts=5 )
Jon Halla440e872016-03-31 15:15:50 -0700277
Jon Hall41d39f12016-04-11 22:54:35 -0700278 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Halla440e872016-03-31 15:15:50 -0700279 onpass="Nodes check successful",
280 onfail="Nodes check NOT successful" )
281
282 if not nodeResults:
Jon Hall7ac7bc32016-05-05 10:57:02 -0700283 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700284 cli = main.CLIs[ i ]
Jon Halla440e872016-03-31 15:15:50 -0700285 main.log.debug( "{} components not ACTIVE: \n{}".format(
286 cli.name,
287 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700288 main.log.error( "Failed to start ONOS, stopping test" )
289 main.cleanup()
290 main.exit()
291
Jon Hall172b7ba2016-04-07 18:12:20 -0700292 main.step( "Activate apps defined in the params file" )
293 # get data from the params
294 apps = main.params.get( 'apps' )
295 if apps:
Jon Hallf37d44d2017-05-24 10:37:30 -0700296 apps = apps.split( ',' )
Jon Hall172b7ba2016-04-07 18:12:20 -0700297 main.log.warn( apps )
298 activateResult = True
299 for app in apps:
300 main.CLIs[ 0 ].app( app, "Activate" )
301 # TODO: check this worked
302 time.sleep( 10 ) # wait for apps to activate
303 for app in apps:
304 state = main.CLIs[ 0 ].appStatus( app )
305 if state == "ACTIVE":
Jon Hall937bc812017-01-31 16:44:10 -0800306 activateResult = activateResult and True
Jon Hall172b7ba2016-04-07 18:12:20 -0700307 else:
308 main.log.error( "{} is in {} state".format( app, state ) )
Jon Hall937bc812017-01-31 16:44:10 -0800309 activateResult = False
Jon Hall172b7ba2016-04-07 18:12:20 -0700310 utilities.assert_equals( expect=True,
311 actual=activateResult,
312 onpass="Successfully activated apps",
313 onfail="Failed to activate apps" )
314 else:
315 main.log.warn( "No apps were specified to be loaded after startup" )
316
317 main.step( "Set ONOS configurations" )
318 config = main.params.get( 'ONOS_Configuration' )
319 if config:
320 main.log.debug( config )
321 checkResult = main.TRUE
322 for component in config:
Jon Hallf37d44d2017-05-24 10:37:30 -0700323 for setting in config[ component ]:
324 value = config[ component ][ setting ]
Jon Hall172b7ba2016-04-07 18:12:20 -0700325 check = main.CLIs[ 0 ].setCfg( component, setting, value )
326 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
327 checkResult = check and checkResult
328 utilities.assert_equals( expect=main.TRUE,
329 actual=checkResult,
330 onpass="Successfully set config",
331 onfail="Failed to set config" )
332 else:
333 main.log.warn( "No configurations were specified to be changed after startup" )
334
Jon Hall9d2dcad2016-04-08 10:15:20 -0700335 main.step( "App Ids check" )
336 appCheck = main.TRUE
337 threads = []
338 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700339 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall9d2dcad2016-04-08 10:15:20 -0700340 name="appToIDCheck-" + str( i ),
341 args=[] )
342 threads.append( t )
343 t.start()
344
345 for t in threads:
346 t.join()
347 appCheck = appCheck and t.result
348 if appCheck != main.TRUE:
Jon Hallf37d44d2017-05-24 10:37:30 -0700349 node = main.activeNodes[ 0 ]
350 main.log.warn( main.CLIs[ node ].apps() )
351 main.log.warn( main.CLIs[ node ].appIDs() )
Jon Hall9d2dcad2016-04-08 10:15:20 -0700352 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
353 onpass="App Ids seem to be correct",
354 onfail="Something is wrong with app Ids" )
355
Jon Hall5cf14d52015-07-16 12:15:19 -0700356 def CASE2( self, main ):
357 """
358 Assign devices to controllers
359 """
360 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700361 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700362 assert main, "main not defined"
363 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700364 assert main.CLIs, "main.CLIs not defined"
365 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700366 assert ONOS1Port, "ONOS1Port not defined"
367 assert ONOS2Port, "ONOS2Port not defined"
368 assert ONOS3Port, "ONOS3Port not defined"
369 assert ONOS4Port, "ONOS4Port not defined"
370 assert ONOS5Port, "ONOS5Port not defined"
371 assert ONOS6Port, "ONOS6Port not defined"
372 assert ONOS7Port, "ONOS7Port not defined"
373
374 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700375 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700376 "and check that an ONOS node becomes the " +\
377 "master of the device."
378 main.step( "Assign switches to controllers" )
379
380 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700381 for i in range( main.numCtrls ):
382 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700383 swList = []
384 for i in range( 1, 29 ):
385 swList.append( "s" + str( i ) )
386 main.Mininet1.assignSwController( sw=swList, ip=ipList )
387
388 mastershipCheck = main.TRUE
389 for i in range( 1, 29 ):
390 response = main.Mininet1.getSwController( "s" + str( i ) )
391 try:
392 main.log.info( str( response ) )
393 except Exception:
394 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700395 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700396 if re.search( "tcp:" + node.ip_address, response ):
397 mastershipCheck = mastershipCheck and main.TRUE
398 else:
399 main.log.error( "Error, node " + node.ip_address + " is " +
400 "not in the list of controllers s" +
401 str( i ) + " is connecting to." )
402 mastershipCheck = main.FALSE
403 utilities.assert_equals(
404 expect=main.TRUE,
405 actual=mastershipCheck,
406 onpass="Switch mastership assigned correctly",
407 onfail="Switches not assigned correctly to controllers" )
408
409 def CASE21( self, main ):
410 """
411 Assign mastership to controllers
412 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700413 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700414 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700415 assert main, "main not defined"
416 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700417 assert main.CLIs, "main.CLIs not defined"
418 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700419 assert ONOS1Port, "ONOS1Port not defined"
420 assert ONOS2Port, "ONOS2Port not defined"
421 assert ONOS3Port, "ONOS3Port not defined"
422 assert ONOS4Port, "ONOS4Port not defined"
423 assert ONOS5Port, "ONOS5Port not defined"
424 assert ONOS6Port, "ONOS6Port not defined"
425 assert ONOS7Port, "ONOS7Port not defined"
426
427 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700428 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700429 "device. Then manually assign" +\
430 " mastership to specific ONOS nodes using" +\
431 " 'device-role'"
432 main.step( "Assign mastership of switches to specific controllers" )
433 # Manually assign mastership to the controller we want
434 roleCall = main.TRUE
435
Jon Hallf37d44d2017-05-24 10:37:30 -0700436 ipList = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700437 deviceList = []
Jon Hallf37d44d2017-05-24 10:37:30 -0700438 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700439 try:
440 # Assign mastership to specific controllers. This assignment was
441 # determined for a 7 node cluser, but will work with any sized
442 # cluster
443 for i in range( 1, 29 ): # switches 1 through 28
444 # set up correct variables:
445 if i == 1:
446 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700447 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700448 deviceId = onosCli.getDevice( "1000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700449 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700450 c = 1 % main.numCtrls
451 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700452 deviceId = onosCli.getDevice( "2000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700453 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700454 c = 1 % main.numCtrls
455 ip = main.nodes[ c ].ip_address # ONOS2
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700456 deviceId = onosCli.getDevice( "3000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700457 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700458 c = 3 % main.numCtrls
459 ip = main.nodes[ c ].ip_address # ONOS4
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700460 deviceId = onosCli.getDevice( "3004" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700461 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700462 c = 2 % main.numCtrls
463 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700464 deviceId = onosCli.getDevice( "5000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700465 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700466 c = 2 % main.numCtrls
467 ip = main.nodes[ c ].ip_address # ONOS3
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700468 deviceId = onosCli.getDevice( "6000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700469 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700470 c = 5 % main.numCtrls
471 ip = main.nodes[ c ].ip_address # ONOS6
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700472 deviceId = onosCli.getDevice( "6007" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700473 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700474 c = 4 % main.numCtrls
475 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700476 dpid = '3' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700477 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700478 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700479 c = 6 % main.numCtrls
480 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700481 dpid = '6' + str( i ).zfill( 3 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700482 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700483 elif i == 28:
484 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700485 ip = main.nodes[ c ].ip_address # ONOS1
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700486 deviceId = onosCli.getDevice( "2800" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700487 else:
488 main.log.error( "You didn't write an else statement for " +
489 "switch s" + str( i ) )
490 roleCall = main.FALSE
491 # Assign switch
492 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
493 # TODO: make this controller dynamic
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700494 roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
Jon Hall5cf14d52015-07-16 12:15:19 -0700495 ipList.append( ip )
496 deviceList.append( deviceId )
497 except ( AttributeError, AssertionError ):
498 main.log.exception( "Something is wrong with ONOS device view" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700499 main.log.info( onosCli.devices() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700500 utilities.assert_equals(
501 expect=main.TRUE,
502 actual=roleCall,
503 onpass="Re-assigned switch mastership to designated controller",
504 onfail="Something wrong with deviceRole calls" )
505
506 main.step( "Check mastership was correctly assigned" )
507 roleCheck = main.TRUE
508 # NOTE: This is due to the fact that device mastership change is not
509 # atomic and is actually a multi step process
510 time.sleep( 5 )
511 for i in range( len( ipList ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -0700512 ip = ipList[ i ]
513 deviceId = deviceList[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700514 # Check assignment
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700515 master = onosCli.getRole( deviceId ).get( 'master' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700516 if ip in master:
517 roleCheck = roleCheck and main.TRUE
518 else:
519 roleCheck = roleCheck and main.FALSE
520 main.log.error( "Error, controller " + ip + " is not" +
521 " master " + "of device " +
522 str( deviceId ) + ". Master is " +
523 repr( master ) + "." )
524 utilities.assert_equals(
525 expect=main.TRUE,
526 actual=roleCheck,
527 onpass="Switches were successfully reassigned to designated " +
528 "controller",
529 onfail="Switches were not successfully reassigned" )
530
531 def CASE3( self, main ):
532 """
533 Assign intents
534 """
535 import time
536 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700537 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700538 assert main, "main not defined"
539 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700540 assert main.CLIs, "main.CLIs not defined"
541 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700542 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700543 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700544 "assign predetermined host-to-host intents." +\
545 " After installation, check that the intent" +\
546 " is distributed to all nodes and the state" +\
547 " is INSTALLED"
548
549 # install onos-app-fwd
550 main.step( "Install reactive forwarding app" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700551 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700552 installResults = onosCli.activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700553 utilities.assert_equals( expect=main.TRUE, actual=installResults,
554 onpass="Install fwd successful",
555 onfail="Install fwd failed" )
556
557 main.step( "Check app ids" )
558 appCheck = main.TRUE
559 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700560 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700561 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700562 name="appToIDCheck-" + str( i ),
563 args=[] )
564 threads.append( t )
565 t.start()
566
567 for t in threads:
568 t.join()
569 appCheck = appCheck and t.result
570 if appCheck != main.TRUE:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700571 main.log.warn( onosCli.apps() )
572 main.log.warn( onosCli.appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700573 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
574 onpass="App Ids seem to be correct",
575 onfail="Something is wrong with app Ids" )
576
577 main.step( "Discovering Hosts( Via pingall for now )" )
578 # FIXME: Once we have a host discovery mechanism, use that instead
579 # REACTIVE FWD test
580 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700581 passMsg = "Reactive Pingall test passed"
582 time1 = time.time()
583 pingResult = main.Mininet1.pingall()
584 time2 = time.time()
585 if not pingResult:
Jon Hallf37d44d2017-05-24 10:37:30 -0700586 main.log.warn( "First pingall failed. Trying again..." )
Jon Hall5cf14d52015-07-16 12:15:19 -0700587 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700588 passMsg += " on the second try"
589 utilities.assert_equals(
590 expect=main.TRUE,
591 actual=pingResult,
Jon Hallf37d44d2017-05-24 10:37:30 -0700592 onpass=passMsg,
Jon Hall96091e62015-09-21 17:34:17 -0700593 onfail="Reactive Pingall failed, " +
594 "one or more ping pairs failed" )
595 main.log.info( "Time for pingall: %2f seconds" %
596 ( time2 - time1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700597 # timeout for fwd flows
598 time.sleep( 11 )
599 # uninstall onos-app-fwd
600 main.step( "Uninstall reactive forwarding app" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700601 node = main.activeNodes[ 0 ]
602 uninstallResult = main.CLIs[ node ].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700603 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
604 onpass="Uninstall fwd successful",
605 onfail="Uninstall fwd failed" )
606
607 main.step( "Check app ids" )
608 threads = []
609 appCheck2 = main.TRUE
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700610 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700611 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700612 name="appToIDCheck-" + str( i ),
613 args=[] )
614 threads.append( t )
615 t.start()
616
617 for t in threads:
618 t.join()
619 appCheck2 = appCheck2 and t.result
620 if appCheck2 != main.TRUE:
Jon Hallf37d44d2017-05-24 10:37:30 -0700621 node = main.activeNodes[ 0 ]
622 main.log.warn( main.CLIs[ node ].apps() )
623 main.log.warn( main.CLIs[ node ].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700624 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
625 onpass="App Ids seem to be correct",
626 onfail="Something is wrong with app Ids" )
627
628 main.step( "Add host intents via cli" )
629 intentIds = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700630 # TODO: move the host numbers to params
631 # Maybe look at all the paths we ping?
Jon Hall5cf14d52015-07-16 12:15:19 -0700632 intentAddResult = True
633 hostResult = main.TRUE
634 for i in range( 8, 18 ):
635 main.log.info( "Adding host intent between h" + str( i ) +
636 " and h" + str( i + 10 ) )
637 host1 = "00:00:00:00:00:" + \
638 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
639 host2 = "00:00:00:00:00:" + \
640 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
641 # NOTE: getHost can return None
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700642 host1Dict = onosCli.getHost( host1 )
643 host2Dict = onosCli.getHost( host2 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700644 host1Id = None
645 host2Id = None
646 if host1Dict and host2Dict:
647 host1Id = host1Dict.get( 'id', None )
648 host2Id = host2Dict.get( 'id', None )
649 if host1Id and host2Id:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700650 nodeNum = ( i % len( main.activeNodes ) )
Jon Hallf37d44d2017-05-24 10:37:30 -0700651 node = main.activeNodes[ nodeNum ]
652 tmpId = main.CLIs[ node ].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700653 if tmpId:
654 main.log.info( "Added intent with id: " + tmpId )
655 intentIds.append( tmpId )
656 else:
657 main.log.error( "addHostIntent returned: " +
658 repr( tmpId ) )
659 else:
660 main.log.error( "Error, getHost() failed for h" + str( i ) +
661 " and/or h" + str( i + 10 ) )
Jon Hallf37d44d2017-05-24 10:37:30 -0700662 node = main.activeNodes[ 0 ]
663 hosts = main.CLIs[ node ].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700664 main.log.warn( "Hosts output: " )
665 try:
666 main.log.warn( json.dumps( json.loads( hosts ),
667 sort_keys=True,
668 indent=4,
669 separators=( ',', ': ' ) ) )
670 except ( ValueError, TypeError ):
671 main.log.warn( repr( hosts ) )
672 hostResult = main.FALSE
673 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
674 onpass="Found a host id for each host",
675 onfail="Error looking up host ids" )
676
677 intentStart = time.time()
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700678 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700679 main.log.info( "Submitted intents: " + str( intentIds ) )
680 main.log.info( "Intents in ONOS: " + str( onosIds ) )
681 for intent in intentIds:
682 if intent in onosIds:
683 pass # intent submitted is in onos
684 else:
685 intentAddResult = False
686 if intentAddResult:
687 intentStop = time.time()
688 else:
689 intentStop = None
690 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700691 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700692 intentStates = []
693 installedCheck = True
694 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
695 count = 0
696 try:
697 for intent in json.loads( intents ):
698 state = intent.get( 'state', None )
699 if "INSTALLED" not in state:
700 installedCheck = False
701 intentId = intent.get( 'id', None )
702 intentStates.append( ( intentId, state ) )
703 except ( ValueError, TypeError ):
704 main.log.exception( "Error parsing intents" )
705 # add submitted intents not in the store
706 tmplist = [ i for i, s in intentStates ]
707 missingIntents = False
708 for i in intentIds:
709 if i not in tmplist:
710 intentStates.append( ( i, " - " ) )
711 missingIntents = True
712 intentStates.sort()
713 for i, s in intentStates:
714 count += 1
715 main.log.info( "%-6s%-15s%-15s" %
716 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700717 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700718 try:
719 missing = False
720 if leaders:
721 parsedLeaders = json.loads( leaders )
722 main.log.warn( json.dumps( parsedLeaders,
723 sort_keys=True,
724 indent=4,
725 separators=( ',', ': ' ) ) )
726 # check for all intent partitions
727 topics = []
728 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700729 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700730 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -0700731 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700732 for topic in topics:
733 if topic not in ONOStopics:
734 main.log.error( "Error: " + topic +
735 " not in leaders" )
736 missing = True
737 else:
738 main.log.error( "leaders() returned None" )
739 except ( ValueError, TypeError ):
740 main.log.exception( "Error parsing leaders" )
741 main.log.error( repr( leaders ) )
742 # Check all nodes
743 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700744 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700745 response = main.CLIs[ i ].leaders( jsonFormat=False )
746 main.log.warn( str( main.CLIs[ i ].name ) + " leaders output: \n" +
Jon Hall5cf14d52015-07-16 12:15:19 -0700747 str( response ) )
748
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700749 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700750 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700751 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -0700752 parsedPartitions = json.loads( partitions )
753 main.log.warn( json.dumps( parsedPartitions,
754 sort_keys=True,
755 indent=4,
756 separators=( ',', ': ' ) ) )
757 # TODO check for a leader in all paritions
758 # TODO check for consistency among nodes
759 else:
760 main.log.error( "partitions() returned None" )
761 except ( ValueError, TypeError ):
762 main.log.exception( "Error parsing partitions" )
763 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700764 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700765 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700766 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -0700767 parsedPending = json.loads( pendingMap )
768 main.log.warn( json.dumps( parsedPending,
769 sort_keys=True,
770 indent=4,
771 separators=( ',', ': ' ) ) )
772 # TODO check something here?
773 else:
774 main.log.error( "pendingMap() returned None" )
775 except ( ValueError, TypeError ):
776 main.log.exception( "Error parsing pending map" )
777 main.log.error( repr( pendingMap ) )
778
779 intentAddResult = bool( intentAddResult and not missingIntents and
780 installedCheck )
781 if not intentAddResult:
782 main.log.error( "Error in pushing host intents to ONOS" )
783
784 main.step( "Intent Anti-Entropy dispersion" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700785 for j in range( 100 ):
Jon Hall5cf14d52015-07-16 12:15:19 -0700786 correct = True
787 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700788 for i in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700789 onosIds = []
Jon Hallf37d44d2017-05-24 10:37:30 -0700790 ids = main.CLIs[ i ].getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700791 onosIds.append( ids )
Jon Hallf37d44d2017-05-24 10:37:30 -0700792 main.log.debug( "Intents in " + main.CLIs[ i ].name + ": " +
Jon Hall5cf14d52015-07-16 12:15:19 -0700793 str( sorted( onosIds ) ) )
794 if sorted( ids ) != sorted( intentIds ):
795 main.log.warn( "Set of intent IDs doesn't match" )
796 correct = False
797 break
798 else:
Jon Hallf37d44d2017-05-24 10:37:30 -0700799 intents = json.loads( main.CLIs[ i ].intents() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700800 for intent in intents:
801 if intent[ 'state' ] != "INSTALLED":
802 main.log.warn( "Intent " + intent[ 'id' ] +
803 " is " + intent[ 'state' ] )
804 correct = False
805 break
806 if correct:
807 break
808 else:
Jon Hallf37d44d2017-05-24 10:37:30 -0700809 time.sleep( 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700810 if not intentStop:
811 intentStop = time.time()
812 global gossipTime
813 gossipTime = intentStop - intentStart
814 main.log.info( "It took about " + str( gossipTime ) +
815 " seconds for all intents to appear in each node" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700816 gossipPeriod = int( main.params[ 'timers' ][ 'gossip' ] )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700817 maxGossipTime = gossipPeriod * len( main.activeNodes )
Jon Hall5cf14d52015-07-16 12:15:19 -0700818 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700819 expect=maxGossipTime, actual=gossipTime,
Jon Hall5cf14d52015-07-16 12:15:19 -0700820 onpass="ECM anti-entropy for intents worked within " +
821 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700822 onfail="Intent ECM anti-entropy took too long. " +
823 "Expected time:{}, Actual time:{}".format( maxGossipTime,
824 gossipTime ) )
825 if gossipTime <= maxGossipTime:
Jon Hall5cf14d52015-07-16 12:15:19 -0700826 intentAddResult = True
827
828 if not intentAddResult or "key" in pendingMap:
829 import time
830 installedCheck = True
831 main.log.info( "Sleeping 60 seconds to see if intents are found" )
832 time.sleep( 60 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700833 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700834 main.log.info( "Submitted intents: " + str( intentIds ) )
835 main.log.info( "Intents in ONOS: " + str( onosIds ) )
836 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700837 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700838 intentStates = []
839 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
840 count = 0
841 try:
842 for intent in json.loads( intents ):
843 # Iter through intents of a node
844 state = intent.get( 'state', None )
845 if "INSTALLED" not in state:
846 installedCheck = False
847 intentId = intent.get( 'id', None )
848 intentStates.append( ( intentId, state ) )
849 except ( ValueError, TypeError ):
850 main.log.exception( "Error parsing intents" )
851 # add submitted intents not in the store
852 tmplist = [ i for i, s in intentStates ]
853 for i in intentIds:
854 if i not in tmplist:
855 intentStates.append( ( i, " - " ) )
856 intentStates.sort()
857 for i, s in intentStates:
858 count += 1
859 main.log.info( "%-6s%-15s%-15s" %
860 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700861 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700862 try:
863 missing = False
864 if leaders:
865 parsedLeaders = json.loads( leaders )
866 main.log.warn( json.dumps( parsedLeaders,
867 sort_keys=True,
868 indent=4,
869 separators=( ',', ': ' ) ) )
870 # check for all intent partitions
871 # check for election
872 topics = []
873 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700874 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700875 # FIXME: this should only be after we start the app
876 topics.append( "org.onosproject.election" )
877 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -0700878 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700879 for topic in topics:
880 if topic not in ONOStopics:
881 main.log.error( "Error: " + topic +
882 " not in leaders" )
883 missing = True
884 else:
885 main.log.error( "leaders() returned None" )
886 except ( ValueError, TypeError ):
887 main.log.exception( "Error parsing leaders" )
888 main.log.error( repr( leaders ) )
889 # Check all nodes
890 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700891 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700892 node = main.CLIs[ i ]
893 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -0700894 main.log.warn( str( node.name ) + " leaders output: \n" +
895 str( response ) )
896
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700897 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700898 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700899 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -0700900 parsedPartitions = json.loads( partitions )
901 main.log.warn( json.dumps( parsedPartitions,
902 sort_keys=True,
903 indent=4,
904 separators=( ',', ': ' ) ) )
905 # TODO check for a leader in all paritions
906 # TODO check for consistency among nodes
907 else:
908 main.log.error( "partitions() returned None" )
909 except ( ValueError, TypeError ):
910 main.log.exception( "Error parsing partitions" )
911 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700912 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700913 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700914 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -0700915 parsedPending = json.loads( pendingMap )
916 main.log.warn( json.dumps( parsedPending,
917 sort_keys=True,
918 indent=4,
919 separators=( ',', ': ' ) ) )
920 # TODO check something here?
921 else:
922 main.log.error( "pendingMap() returned None" )
923 except ( ValueError, TypeError ):
924 main.log.exception( "Error parsing pending map" )
925 main.log.error( repr( pendingMap ) )
926
927 def CASE4( self, main ):
928 """
929 Ping across added host intents
930 """
931 import json
932 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700933 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700934 assert main, "main not defined"
935 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700936 assert main.CLIs, "main.CLIs not defined"
937 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700938 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700939 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700940 "functionality and check the state of " +\
941 "the intent"
Jon Hall5cf14d52015-07-16 12:15:19 -0700942
Jon Hallf37d44d2017-05-24 10:37:30 -0700943 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700944 main.step( "Check Intent state" )
945 installedCheck = False
946 loopCount = 0
947 while not installedCheck and loopCount < 40:
948 installedCheck = True
949 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700950 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700951 intentStates = []
952 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
953 count = 0
954 # Iter through intents of a node
955 try:
956 for intent in json.loads( intents ):
957 state = intent.get( 'state', None )
958 if "INSTALLED" not in state:
959 installedCheck = False
960 intentId = intent.get( 'id', None )
961 intentStates.append( ( intentId, state ) )
962 except ( ValueError, TypeError ):
963 main.log.exception( "Error parsing intents." )
964 # Print states
965 intentStates.sort()
966 for i, s in intentStates:
967 count += 1
968 main.log.info( "%-6s%-15s%-15s" %
969 ( str( count ), str( i ), str( s ) ) )
970 if not installedCheck:
971 time.sleep( 1 )
972 loopCount += 1
973 utilities.assert_equals( expect=True, actual=installedCheck,
974 onpass="Intents are all INSTALLED",
975 onfail="Intents are not all in " +
976 "INSTALLED state" )
977
Jon Hall9d2dcad2016-04-08 10:15:20 -0700978 main.step( "Ping across added host intents" )
Jon Hall9d2dcad2016-04-08 10:15:20 -0700979 PingResult = main.TRUE
980 for i in range( 8, 18 ):
981 ping = main.Mininet1.pingHost( src="h" + str( i ),
982 target="h" + str( i + 10 ) )
983 PingResult = PingResult and ping
984 if ping == main.FALSE:
985 main.log.warn( "Ping failed between h" + str( i ) +
986 " and h" + str( i + 10 ) )
987 elif ping == main.TRUE:
988 main.log.info( "Ping test passed!" )
989 # Don't set PingResult or you'd override failures
990 if PingResult == main.FALSE:
991 main.log.error(
992 "Intents have not been installed correctly, pings failed." )
993 # TODO: pretty print
994 main.log.warn( "ONOS1 intents: " )
995 try:
996 tmpIntents = onosCli.intents()
997 main.log.warn( json.dumps( json.loads( tmpIntents ),
998 sort_keys=True,
999 indent=4,
1000 separators=( ',', ': ' ) ) )
1001 except ( ValueError, TypeError ):
1002 main.log.warn( repr( tmpIntents ) )
1003 utilities.assert_equals(
1004 expect=main.TRUE,
1005 actual=PingResult,
1006 onpass="Intents have been installed correctly and pings work",
1007 onfail="Intents have not been installed correctly, pings failed." )
1008
Jon Hall5cf14d52015-07-16 12:15:19 -07001009 main.step( "Check leadership of topics" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001010 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001011 topicCheck = main.TRUE
1012 try:
1013 if leaders:
1014 parsedLeaders = json.loads( leaders )
1015 main.log.warn( json.dumps( parsedLeaders,
1016 sort_keys=True,
1017 indent=4,
1018 separators=( ',', ': ' ) ) )
1019 # check for all intent partitions
1020 # check for election
1021 # TODO: Look at Devices as topics now that it uses this system
1022 topics = []
1023 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -07001024 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001025 # FIXME: this should only be after we start the app
1026 # FIXME: topics.append( "org.onosproject.election" )
1027 # Print leaders output
1028 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -07001029 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -07001030 for topic in topics:
1031 if topic not in ONOStopics:
1032 main.log.error( "Error: " + topic +
1033 " not in leaders" )
1034 topicCheck = main.FALSE
1035 else:
1036 main.log.error( "leaders() returned None" )
1037 topicCheck = main.FALSE
1038 except ( ValueError, TypeError ):
1039 topicCheck = main.FALSE
1040 main.log.exception( "Error parsing leaders" )
1041 main.log.error( repr( leaders ) )
1042 # TODO: Check for a leader of these topics
1043 # Check all nodes
1044 if topicCheck:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001045 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001046 node = main.CLIs[ i ]
1047 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -07001048 main.log.warn( str( node.name ) + " leaders output: \n" +
1049 str( response ) )
1050
1051 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
1052 onpass="intent Partitions is in leaders",
1053 onfail="Some topics were lost " )
1054 # Print partitions
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001055 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001056 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001057 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -07001058 parsedPartitions = json.loads( partitions )
1059 main.log.warn( json.dumps( parsedPartitions,
1060 sort_keys=True,
1061 indent=4,
1062 separators=( ',', ': ' ) ) )
1063 # TODO check for a leader in all paritions
1064 # TODO check for consistency among nodes
1065 else:
1066 main.log.error( "partitions() returned None" )
1067 except ( ValueError, TypeError ):
1068 main.log.exception( "Error parsing partitions" )
1069 main.log.error( repr( partitions ) )
1070 # Print Pending Map
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001071 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001072 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001073 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -07001074 parsedPending = json.loads( pendingMap )
1075 main.log.warn( json.dumps( parsedPending,
1076 sort_keys=True,
1077 indent=4,
1078 separators=( ',', ': ' ) ) )
1079 # TODO check something here?
1080 else:
1081 main.log.error( "pendingMap() returned None" )
1082 except ( ValueError, TypeError ):
1083 main.log.exception( "Error parsing pending map" )
1084 main.log.error( repr( pendingMap ) )
1085
1086 if not installedCheck:
1087 main.log.info( "Waiting 60 seconds to see if the state of " +
1088 "intents change" )
1089 time.sleep( 60 )
1090 # Print the intent states
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001091 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001092 intentStates = []
1093 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1094 count = 0
1095 # Iter through intents of a node
1096 try:
1097 for intent in json.loads( intents ):
1098 state = intent.get( 'state', None )
1099 if "INSTALLED" not in state:
1100 installedCheck = False
1101 intentId = intent.get( 'id', None )
1102 intentStates.append( ( intentId, state ) )
1103 except ( ValueError, TypeError ):
1104 main.log.exception( "Error parsing intents." )
1105 intentStates.sort()
1106 for i, s in intentStates:
1107 count += 1
1108 main.log.info( "%-6s%-15s%-15s" %
1109 ( str( count ), str( i ), str( s ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001110 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001111 try:
1112 missing = False
1113 if leaders:
1114 parsedLeaders = json.loads( leaders )
1115 main.log.warn( json.dumps( parsedLeaders,
1116 sort_keys=True,
1117 indent=4,
1118 separators=( ',', ': ' ) ) )
1119 # check for all intent partitions
1120 # check for election
1121 topics = []
1122 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -07001123 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001124 # FIXME: this should only be after we start the app
1125 topics.append( "org.onosproject.election" )
1126 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -07001127 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -07001128 for topic in topics:
1129 if topic not in ONOStopics:
1130 main.log.error( "Error: " + topic +
1131 " not in leaders" )
1132 missing = True
1133 else:
1134 main.log.error( "leaders() returned None" )
1135 except ( ValueError, TypeError ):
1136 main.log.exception( "Error parsing leaders" )
1137 main.log.error( repr( leaders ) )
1138 if missing:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001139 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001140 node = main.CLIs[ i ]
1141 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -07001142 main.log.warn( str( node.name ) + " leaders output: \n" +
1143 str( response ) )
1144
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001145 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001146 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001147 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -07001148 parsedPartitions = json.loads( partitions )
1149 main.log.warn( json.dumps( parsedPartitions,
1150 sort_keys=True,
1151 indent=4,
1152 separators=( ',', ': ' ) ) )
1153 # TODO check for a leader in all paritions
1154 # TODO check for consistency among nodes
1155 else:
1156 main.log.error( "partitions() returned None" )
1157 except ( ValueError, TypeError ):
1158 main.log.exception( "Error parsing partitions" )
1159 main.log.error( repr( partitions ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001160 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001161 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001162 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -07001163 parsedPending = json.loads( pendingMap )
1164 main.log.warn( json.dumps( parsedPending,
1165 sort_keys=True,
1166 indent=4,
1167 separators=( ',', ': ' ) ) )
1168 # TODO check something here?
1169 else:
1170 main.log.error( "pendingMap() returned None" )
1171 except ( ValueError, TypeError ):
1172 main.log.exception( "Error parsing pending map" )
1173 main.log.error( repr( pendingMap ) )
1174 # Print flowrules
Jon Hall41d39f12016-04-11 22:54:35 -07001175 main.log.debug( onosCli.flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001176 main.step( "Wait a minute then ping again" )
1177 # the wait is above
1178 PingResult = main.TRUE
1179 for i in range( 8, 18 ):
1180 ping = main.Mininet1.pingHost( src="h" + str( i ),
1181 target="h" + str( i + 10 ) )
1182 PingResult = PingResult and ping
1183 if ping == main.FALSE:
1184 main.log.warn( "Ping failed between h" + str( i ) +
1185 " and h" + str( i + 10 ) )
1186 elif ping == main.TRUE:
1187 main.log.info( "Ping test passed!" )
1188 # Don't set PingResult or you'd override failures
1189 if PingResult == main.FALSE:
1190 main.log.error(
1191 "Intents have not been installed correctly, pings failed." )
1192 # TODO: pretty print
1193 main.log.warn( "ONOS1 intents: " )
1194 try:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001195 tmpIntents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001196 main.log.warn( json.dumps( json.loads( tmpIntents ),
1197 sort_keys=True,
1198 indent=4,
1199 separators=( ',', ': ' ) ) )
1200 except ( ValueError, TypeError ):
1201 main.log.warn( repr( tmpIntents ) )
1202 utilities.assert_equals(
1203 expect=main.TRUE,
1204 actual=PingResult,
1205 onpass="Intents have been installed correctly and pings work",
1206 onfail="Intents have not been installed correctly, pings failed." )
1207
1208 def CASE5( self, main ):
1209 """
1210 Reading state of ONOS
1211 """
1212 import json
1213 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001214 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001215 assert main, "main not defined"
1216 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001217 assert main.CLIs, "main.CLIs not defined"
1218 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001219
1220 main.case( "Setting up and gathering data for current state" )
1221 # The general idea for this test case is to pull the state of
1222 # ( intents,flows, topology,... ) from each ONOS node
1223 # We can then compare them with each other and also with past states
1224
1225 main.step( "Check that each switch has a master" )
1226 global mastershipState
1227 mastershipState = '[]'
1228
1229 # Assert that each device has a master
1230 rolesNotNull = main.TRUE
1231 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001232 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001233 t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001234 name="rolesNotNull-" + str( i ),
1235 args=[] )
1236 threads.append( t )
1237 t.start()
1238
1239 for t in threads:
1240 t.join()
1241 rolesNotNull = rolesNotNull and t.result
1242 utilities.assert_equals(
1243 expect=main.TRUE,
1244 actual=rolesNotNull,
1245 onpass="Each device has a master",
1246 onfail="Some devices don't have a master assigned" )
1247
1248 main.step( "Get the Mastership of each switch from each controller" )
1249 ONOSMastership = []
1250 mastershipCheck = main.FALSE
1251 consistentMastership = True
1252 rolesResults = True
1253 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001254 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001255 t = main.Thread( target=main.CLIs[ i ].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001256 name="roles-" + str( i ),
1257 args=[] )
1258 threads.append( t )
1259 t.start()
1260
1261 for t in threads:
1262 t.join()
1263 ONOSMastership.append( t.result )
1264
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001265 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001266 node = str( main.activeNodes[ i ] + 1 )
1267 if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001268 main.log.error( "Error in getting ONOS" + node + " roles" )
1269 main.log.warn( "ONOS" + node + " mastership response: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001270 repr( ONOSMastership[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001271 rolesResults = False
1272 utilities.assert_equals(
1273 expect=True,
1274 actual=rolesResults,
1275 onpass="No error in reading roles output",
1276 onfail="Error in reading roles from ONOS" )
1277
1278 main.step( "Check for consistency in roles from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001279 if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001280 main.log.info(
1281 "Switch roles are consistent across all ONOS nodes" )
1282 else:
1283 consistentMastership = False
1284 utilities.assert_equals(
1285 expect=True,
1286 actual=consistentMastership,
1287 onpass="Switch roles are consistent across all ONOS nodes",
1288 onfail="ONOS nodes have different views of switch roles" )
1289
1290 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001291 for i in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001292 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001293 try:
1294 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001295 "ONOS" + node + " roles: ",
Jon Hall5cf14d52015-07-16 12:15:19 -07001296 json.dumps(
1297 json.loads( ONOSMastership[ i ] ),
1298 sort_keys=True,
1299 indent=4,
1300 separators=( ',', ': ' ) ) )
1301 except ( ValueError, TypeError ):
1302 main.log.warn( repr( ONOSMastership[ i ] ) )
1303 elif rolesResults and consistentMastership:
1304 mastershipCheck = main.TRUE
1305 mastershipState = ONOSMastership[ 0 ]
1306
1307 main.step( "Get the intents from each controller" )
1308 global intentState
1309 intentState = []
1310 ONOSIntents = []
1311 intentCheck = main.FALSE
1312 consistentIntents = True
1313 intentsResults = True
1314 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001315 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001316 t = main.Thread( target=main.CLIs[ i ].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001317 name="intents-" + str( i ),
1318 args=[],
1319 kwargs={ 'jsonFormat': True } )
1320 threads.append( t )
1321 t.start()
1322
1323 for t in threads:
1324 t.join()
1325 ONOSIntents.append( t.result )
1326
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001327 for i in range( len( ONOSIntents ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001328 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001329 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001330 main.log.error( "Error in getting ONOS" + node + " intents" )
1331 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001332 repr( ONOSIntents[ i ] ) )
1333 intentsResults = False
1334 utilities.assert_equals(
1335 expect=True,
1336 actual=intentsResults,
1337 onpass="No error in reading intents output",
1338 onfail="Error in reading intents from ONOS" )
1339
1340 main.step( "Check for consistency in Intents from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001341 if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001342 main.log.info( "Intents are consistent across all ONOS " +
1343 "nodes" )
1344 else:
1345 consistentIntents = False
1346 main.log.error( "Intents not consistent" )
1347 utilities.assert_equals(
1348 expect=True,
1349 actual=consistentIntents,
1350 onpass="Intents are consistent across all ONOS nodes",
1351 onfail="ONOS nodes have different views of intents" )
1352
1353 if intentsResults:
1354 # Try to make it easy to figure out what is happening
1355 #
1356 # Intent ONOS1 ONOS2 ...
1357 # 0x01 INSTALLED INSTALLING
1358 # ... ... ...
1359 # ... ... ...
1360 title = " Id"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001361 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001362 title += " " * 10 + "ONOS" + str( n + 1 )
1363 main.log.warn( title )
1364 # get all intent keys in the cluster
1365 keys = []
Jon Halla440e872016-03-31 15:15:50 -07001366 try:
1367 # Get the set of all intent keys
Jon Hall5cf14d52015-07-16 12:15:19 -07001368 for nodeStr in ONOSIntents:
1369 node = json.loads( nodeStr )
1370 for intent in node:
Jon Halla440e872016-03-31 15:15:50 -07001371 keys.append( intent.get( 'id' ) )
1372 keys = set( keys )
1373 # For each intent key, print the state on each node
1374 for key in keys:
1375 row = "%-13s" % key
1376 for nodeStr in ONOSIntents:
1377 node = json.loads( nodeStr )
1378 for intent in node:
1379 if intent.get( 'id', "Error" ) == key:
1380 row += "%-15s" % intent.get( 'state' )
1381 main.log.warn( row )
1382 # End of intent state table
1383 except ValueError as e:
1384 main.log.exception( e )
1385 main.log.debug( "nodeStr was: " + repr( nodeStr ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001386
1387 if intentsResults and not consistentIntents:
1388 # print the json objects
Jon Hallf37d44d2017-05-24 10:37:30 -07001389 n = str( main.activeNodes[ -1 ] + 1 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001390 main.log.debug( "ONOS" + n + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001391 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1392 sort_keys=True,
1393 indent=4,
1394 separators=( ',', ': ' ) ) )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001395 for i in range( len( ONOSIntents ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001396 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001397 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001398 main.log.debug( "ONOS" + node + " intents: " )
Jon Hallf37d44d2017-05-24 10:37:30 -07001399 main.log.debug( json.dumps( json.loads( ONOSIntents[ i ] ),
Jon Hall5cf14d52015-07-16 12:15:19 -07001400 sort_keys=True,
1401 indent=4,
1402 separators=( ',', ': ' ) ) )
1403 else:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001404 main.log.debug( "ONOS" + node + " intents match ONOS" +
1405 n + " intents" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001406 elif intentsResults and consistentIntents:
1407 intentCheck = main.TRUE
1408 intentState = ONOSIntents[ 0 ]
1409
1410 main.step( "Get the flows from each controller" )
1411 global flowState
1412 flowState = []
1413 ONOSFlows = []
1414 ONOSFlowsJson = []
1415 flowCheck = main.FALSE
1416 consistentFlows = True
1417 flowsResults = True
1418 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001419 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001420 t = main.Thread( target=main.CLIs[ i ].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001421 name="flows-" + str( i ),
1422 args=[],
1423 kwargs={ 'jsonFormat': True } )
1424 threads.append( t )
1425 t.start()
1426
1427 # NOTE: Flows command can take some time to run
Jon Hallf37d44d2017-05-24 10:37:30 -07001428 time.sleep( 30 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001429 for t in threads:
1430 t.join()
1431 result = t.result
1432 ONOSFlows.append( result )
1433
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001434 for i in range( len( ONOSFlows ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001435 num = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001436 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1437 main.log.error( "Error in getting ONOS" + num + " flows" )
1438 main.log.warn( "ONOS" + num + " flows response: " +
1439 repr( ONOSFlows[ i ] ) )
1440 flowsResults = False
1441 ONOSFlowsJson.append( None )
1442 else:
1443 try:
1444 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1445 except ( ValueError, TypeError ):
1446 # FIXME: change this to log.error?
1447 main.log.exception( "Error in parsing ONOS" + num +
1448 " response as json." )
1449 main.log.error( repr( ONOSFlows[ i ] ) )
1450 ONOSFlowsJson.append( None )
1451 flowsResults = False
1452 utilities.assert_equals(
1453 expect=True,
1454 actual=flowsResults,
1455 onpass="No error in reading flows output",
1456 onfail="Error in reading flows from ONOS" )
1457
1458 main.step( "Check for consistency in Flows from each controller" )
1459 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1460 if all( tmp ):
1461 main.log.info( "Flow count is consistent across all ONOS nodes" )
1462 else:
1463 consistentFlows = False
1464 utilities.assert_equals(
1465 expect=True,
1466 actual=consistentFlows,
1467 onpass="The flow count is consistent across all ONOS nodes",
1468 onfail="ONOS nodes have different flow counts" )
1469
1470 if flowsResults and not consistentFlows:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001471 for i in range( len( ONOSFlows ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001472 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001473 try:
1474 main.log.warn(
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001475 "ONOS" + node + " flows: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001476 json.dumps( json.loads( ONOSFlows[ i ] ), sort_keys=True,
Jon Hall5cf14d52015-07-16 12:15:19 -07001477 indent=4, separators=( ',', ': ' ) ) )
1478 except ( ValueError, TypeError ):
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001479 main.log.warn( "ONOS" + node + " flows: " +
1480 repr( ONOSFlows[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001481 elif flowsResults and consistentFlows:
1482 flowCheck = main.TRUE
1483 flowState = ONOSFlows[ 0 ]
1484
1485 main.step( "Get the OF Table entries" )
1486 global flows
1487 flows = []
1488 for i in range( 1, 29 ):
GlennRC68467eb2015-11-16 18:01:01 -08001489 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001490 if flowCheck == main.FALSE:
1491 for table in flows:
1492 main.log.warn( table )
1493 # TODO: Compare switch flow tables with ONOS flow tables
1494
1495 main.step( "Start continuous pings" )
1496 main.Mininet2.pingLong(
1497 src=main.params[ 'PING' ][ 'source1' ],
1498 target=main.params[ 'PING' ][ 'target1' ],
1499 pingTime=500 )
1500 main.Mininet2.pingLong(
1501 src=main.params[ 'PING' ][ 'source2' ],
1502 target=main.params[ 'PING' ][ 'target2' ],
1503 pingTime=500 )
1504 main.Mininet2.pingLong(
1505 src=main.params[ 'PING' ][ 'source3' ],
1506 target=main.params[ 'PING' ][ 'target3' ],
1507 pingTime=500 )
1508 main.Mininet2.pingLong(
1509 src=main.params[ 'PING' ][ 'source4' ],
1510 target=main.params[ 'PING' ][ 'target4' ],
1511 pingTime=500 )
1512 main.Mininet2.pingLong(
1513 src=main.params[ 'PING' ][ 'source5' ],
1514 target=main.params[ 'PING' ][ 'target5' ],
1515 pingTime=500 )
1516 main.Mininet2.pingLong(
1517 src=main.params[ 'PING' ][ 'source6' ],
1518 target=main.params[ 'PING' ][ 'target6' ],
1519 pingTime=500 )
1520 main.Mininet2.pingLong(
1521 src=main.params[ 'PING' ][ 'source7' ],
1522 target=main.params[ 'PING' ][ 'target7' ],
1523 pingTime=500 )
1524 main.Mininet2.pingLong(
1525 src=main.params[ 'PING' ][ 'source8' ],
1526 target=main.params[ 'PING' ][ 'target8' ],
1527 pingTime=500 )
1528 main.Mininet2.pingLong(
1529 src=main.params[ 'PING' ][ 'source9' ],
1530 target=main.params[ 'PING' ][ 'target9' ],
1531 pingTime=500 )
1532 main.Mininet2.pingLong(
1533 src=main.params[ 'PING' ][ 'source10' ],
1534 target=main.params[ 'PING' ][ 'target10' ],
1535 pingTime=500 )
1536
1537 main.step( "Collecting topology information from ONOS" )
1538 devices = []
1539 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001540 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001541 t = main.Thread( target=main.CLIs[ i ].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001542 name="devices-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001543 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001544 threads.append( t )
1545 t.start()
1546
1547 for t in threads:
1548 t.join()
1549 devices.append( t.result )
1550 hosts = []
1551 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001552 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001553 t = main.Thread( target=main.CLIs[ i ].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001554 name="hosts-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001555 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001556 threads.append( t )
1557 t.start()
1558
1559 for t in threads:
1560 t.join()
1561 try:
1562 hosts.append( json.loads( t.result ) )
1563 except ( ValueError, TypeError ):
1564 # FIXME: better handling of this, print which node
1565 # Maybe use thread name?
1566 main.log.exception( "Error parsing json output of hosts" )
Jon Hallf3d16e72015-12-16 17:45:08 -08001567 main.log.warn( repr( t.result ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001568 hosts.append( None )
1569
1570 ports = []
1571 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001572 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001573 t = main.Thread( target=main.CLIs[ i ].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001574 name="ports-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001575 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001576 threads.append( t )
1577 t.start()
1578
1579 for t in threads:
1580 t.join()
1581 ports.append( t.result )
1582 links = []
1583 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001584 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001585 t = main.Thread( target=main.CLIs[ i ].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001586 name="links-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001587 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001588 threads.append( t )
1589 t.start()
1590
1591 for t in threads:
1592 t.join()
1593 links.append( t.result )
1594 clusters = []
1595 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001596 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001597 t = main.Thread( target=main.CLIs[ i ].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001598 name="clusters-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001599 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001600 threads.append( t )
1601 t.start()
1602
1603 for t in threads:
1604 t.join()
1605 clusters.append( t.result )
1606 # Compare json objects for hosts and dataplane clusters
1607
1608 # hosts
1609 main.step( "Host view is consistent across ONOS nodes" )
1610 consistentHostsResult = main.TRUE
1611 for controller in range( len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001612 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001613 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001614 if hosts[ controller ] == hosts[ 0 ]:
1615 continue
1616 else: # hosts not consistent
1617 main.log.error( "hosts from ONOS" +
1618 controllerStr +
1619 " is inconsistent with ONOS1" )
1620 main.log.warn( repr( hosts[ controller ] ) )
1621 consistentHostsResult = main.FALSE
1622
1623 else:
1624 main.log.error( "Error in getting ONOS hosts from ONOS" +
1625 controllerStr )
1626 consistentHostsResult = main.FALSE
1627 main.log.warn( "ONOS" + controllerStr +
1628 " hosts response: " +
1629 repr( hosts[ controller ] ) )
1630 utilities.assert_equals(
1631 expect=main.TRUE,
1632 actual=consistentHostsResult,
1633 onpass="Hosts view is consistent across all ONOS nodes",
1634 onfail="ONOS nodes have different views of hosts" )
1635
1636 main.step( "Each host has an IP address" )
1637 ipResult = main.TRUE
1638 for controller in range( 0, len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001639 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001640 if hosts[ controller ]:
1641 for host in hosts[ controller ]:
Jon Hallf37d44d2017-05-24 10:37:30 -07001642 if not host.get( 'ipAddresses', [] ):
Jon Hallf3d16e72015-12-16 17:45:08 -08001643 main.log.error( "Error with host ips on controller" +
1644 controllerStr + ": " + str( host ) )
1645 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001646 utilities.assert_equals(
1647 expect=main.TRUE,
1648 actual=ipResult,
1649 onpass="The ips of the hosts aren't empty",
1650 onfail="The ip of at least one host is missing" )
1651
1652 # Strongly connected clusters of devices
1653 main.step( "Cluster view is consistent across ONOS nodes" )
1654 consistentClustersResult = main.TRUE
1655 for controller in range( len( clusters ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001656 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001657 if "Error" not in clusters[ controller ]:
1658 if clusters[ controller ] == clusters[ 0 ]:
1659 continue
1660 else: # clusters not consistent
1661 main.log.error( "clusters from ONOS" + controllerStr +
1662 " is inconsistent with ONOS1" )
1663 consistentClustersResult = main.FALSE
1664
1665 else:
1666 main.log.error( "Error in getting dataplane clusters " +
1667 "from ONOS" + controllerStr )
1668 consistentClustersResult = main.FALSE
1669 main.log.warn( "ONOS" + controllerStr +
1670 " clusters response: " +
1671 repr( clusters[ controller ] ) )
1672 utilities.assert_equals(
1673 expect=main.TRUE,
1674 actual=consistentClustersResult,
1675 onpass="Clusters view is consistent across all ONOS nodes",
1676 onfail="ONOS nodes have different views of clusters" )
Jon Hall64948022016-05-12 13:38:50 -07001677 if not consistentClustersResult:
Jon Hall172b7ba2016-04-07 18:12:20 -07001678 main.log.debug( clusters )
Jon Hall64948022016-05-12 13:38:50 -07001679
Jon Hall5cf14d52015-07-16 12:15:19 -07001680 # there should always only be one cluster
1681 main.step( "Cluster view correct across ONOS nodes" )
1682 try:
1683 numClusters = len( json.loads( clusters[ 0 ] ) )
1684 except ( ValueError, TypeError ):
1685 main.log.exception( "Error parsing clusters[0]: " +
1686 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001687 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07001688 clusterResults = main.FALSE
1689 if numClusters == 1:
1690 clusterResults = main.TRUE
1691 utilities.assert_equals(
1692 expect=1,
1693 actual=numClusters,
1694 onpass="ONOS shows 1 SCC",
1695 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1696
1697 main.step( "Comparing ONOS topology to MN" )
1698 devicesResults = main.TRUE
1699 linksResults = main.TRUE
1700 hostsResults = main.TRUE
1701 mnSwitches = main.Mininet1.getSwitches()
1702 mnLinks = main.Mininet1.getLinks()
1703 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001704 for controller in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001705 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001706 if devices[ controller ] and ports[ controller ] and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001707 "Error" not in devices[ controller ] and\
1708 "Error" not in ports[ controller ]:
1709 currentDevicesResult = main.Mininet1.compareSwitches(
1710 mnSwitches,
1711 json.loads( devices[ controller ] ),
1712 json.loads( ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001713 else:
1714 currentDevicesResult = main.FALSE
1715 utilities.assert_equals( expect=main.TRUE,
1716 actual=currentDevicesResult,
1717 onpass="ONOS" + controllerStr +
1718 " Switches view is correct",
1719 onfail="ONOS" + controllerStr +
1720 " Switches view is incorrect" )
1721 if links[ controller ] and "Error" not in links[ controller ]:
1722 currentLinksResult = main.Mininet1.compareLinks(
1723 mnSwitches, mnLinks,
1724 json.loads( links[ controller ] ) )
1725 else:
1726 currentLinksResult = main.FALSE
1727 utilities.assert_equals( expect=main.TRUE,
1728 actual=currentLinksResult,
1729 onpass="ONOS" + controllerStr +
1730 " links view is correct",
1731 onfail="ONOS" + controllerStr +
1732 " links view is incorrect" )
1733
Jon Hall657cdf62015-12-17 14:40:51 -08001734 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001735 currentHostsResult = main.Mininet1.compareHosts(
1736 mnHosts,
1737 hosts[ controller ] )
1738 else:
1739 currentHostsResult = main.FALSE
1740 utilities.assert_equals( expect=main.TRUE,
1741 actual=currentHostsResult,
1742 onpass="ONOS" + controllerStr +
1743 " hosts exist in Mininet",
1744 onfail="ONOS" + controllerStr +
1745 " hosts don't match Mininet" )
1746
1747 devicesResults = devicesResults and currentDevicesResult
1748 linksResults = linksResults and currentLinksResult
1749 hostsResults = hostsResults and currentHostsResult
1750
1751 main.step( "Device information is correct" )
1752 utilities.assert_equals(
1753 expect=main.TRUE,
1754 actual=devicesResults,
1755 onpass="Device information is correct",
1756 onfail="Device information is incorrect" )
1757
1758 main.step( "Links are correct" )
1759 utilities.assert_equals(
1760 expect=main.TRUE,
1761 actual=linksResults,
1762 onpass="Link are correct",
1763 onfail="Links are incorrect" )
1764
1765 main.step( "Hosts are correct" )
1766 utilities.assert_equals(
1767 expect=main.TRUE,
1768 actual=hostsResults,
1769 onpass="Hosts are correct",
1770 onfail="Hosts are incorrect" )
1771
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001772 def CASE61( self, main ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001773 """
1774 The Failure case.
1775 """
Jon Halle1a3b752015-07-22 13:02:46 -07001776 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001777 assert main, "main not defined"
1778 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001779 assert main.CLIs, "main.CLIs not defined"
1780 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001781 main.case( "Stop minority of ONOS nodes" )
Jon Hall96091e62015-09-21 17:34:17 -07001782
1783 main.step( "Checking ONOS Logs for errors" )
1784 for node in main.nodes:
1785 main.log.debug( "Checking logs for errors on " + node.name + ":" )
1786 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
1787
Jon Hall3b489db2015-10-05 14:38:37 -07001788 n = len( main.nodes ) # Number of nodes
1789 p = ( ( n + 1 ) / 2 ) + 1 # Number of partitions
1790 main.kill = [ 0 ] # ONOS node to kill, listed by index in main.nodes
1791 if n > 3:
1792 main.kill.append( p - 1 )
1793 # NOTE: This only works for cluster sizes of 3,5, or 7.
1794
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001795 main.step( "Stopping " + str( len( main.kill ) ) + " ONOS nodes" )
Jon Hall3b489db2015-10-05 14:38:37 -07001796 killResults = main.TRUE
1797 for i in main.kill:
1798 killResults = killResults and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001799 main.ONOSbench.onosStop( main.nodes[ i ].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001800 main.activeNodes.remove( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001801 utilities.assert_equals( expect=main.TRUE, actual=killResults,
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001802 onpass="ONOS nodes stopped successfully",
1803 onfail="ONOS nodes NOT successfully stopped" )
1804
Jon Halld2871c22016-07-26 11:01:14 -07001805 main.step( "Checking ONOS nodes" )
1806 nodeResults = utilities.retry( main.HA.nodesCheck,
1807 False,
Jon Hallf37d44d2017-05-24 10:37:30 -07001808 args=[ main.activeNodes ],
Jon Halld2871c22016-07-26 11:01:14 -07001809 sleep=15,
1810 attempts=5 )
1811
1812 utilities.assert_equals( expect=True, actual=nodeResults,
1813 onpass="Nodes check successful",
1814 onfail="Nodes check NOT successful" )
1815
1816 if not nodeResults:
1817 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001818 cli = main.CLIs[ i ]
Jon Halld2871c22016-07-26 11:01:14 -07001819 main.log.debug( "{} components not ACTIVE: \n{}".format(
1820 cli.name,
1821 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
1822 main.log.error( "Failed to start ONOS, stopping test" )
1823 main.cleanup()
1824 main.exit()
1825
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001826 def CASE62( self, main ):
1827 """
1828 The bring up stopped nodes
1829 """
1830 import time
1831 assert main.numCtrls, "main.numCtrls not defined"
1832 assert main, "main not defined"
1833 assert utilities.assert_equals, "utilities.assert_equals not defined"
1834 assert main.CLIs, "main.CLIs not defined"
1835 assert main.nodes, "main.nodes not defined"
1836 assert main.kill, "main.kill not defined"
1837 main.case( "Restart minority of ONOS nodes" )
1838
1839 main.step( "Restarting " + str( len( main.kill ) ) + " ONOS nodes" )
1840 startResults = main.TRUE
1841 restartTime = time.time()
1842 for i in main.kill:
1843 startResults = startResults and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001844 main.ONOSbench.onosStart( main.nodes[ i ].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001845 utilities.assert_equals( expect=main.TRUE, actual=startResults,
1846 onpass="ONOS nodes started successfully",
1847 onfail="ONOS nodes NOT successfully started" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001848
1849 main.step( "Checking if ONOS is up yet" )
1850 count = 0
1851 onosIsupResult = main.FALSE
1852 while onosIsupResult == main.FALSE and count < 10:
Jon Hall3b489db2015-10-05 14:38:37 -07001853 onosIsupResult = main.TRUE
1854 for i in main.kill:
1855 onosIsupResult = onosIsupResult and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001856 main.ONOSbench.isup( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07001857 count = count + 1
Jon Hall5cf14d52015-07-16 12:15:19 -07001858 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1859 onpass="ONOS restarted successfully",
1860 onfail="ONOS restart NOT successful" )
1861
Jon Halle1a3b752015-07-22 13:02:46 -07001862 main.step( "Restarting ONOS main.CLIs" )
Jon Hall3b489db2015-10-05 14:38:37 -07001863 cliResults = main.TRUE
1864 for i in main.kill:
1865 cliResults = cliResults and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001866 main.CLIs[ i ].startOnosCli( main.nodes[ i ].ip_address )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001867 main.activeNodes.append( i )
Jon Hall5cf14d52015-07-16 12:15:19 -07001868 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1869 onpass="ONOS cli restarted",
1870 onfail="ONOS cli did not restart" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001871 main.activeNodes.sort()
1872 try:
1873 assert list( set( main.activeNodes ) ) == main.activeNodes,\
1874 "List of active nodes has duplicates, this likely indicates something was run out of order"
1875 except AssertionError:
1876 main.log.exception( "" )
1877 main.cleanup()
1878 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -07001879
1880 # Grab the time of restart so we chan check how long the gossip
1881 # protocol has had time to work
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001882 main.restartTime = time.time() - restartTime
Jon Hall5cf14d52015-07-16 12:15:19 -07001883 main.log.debug( "Restart time: " + str( main.restartTime ) )
Jon Halld2871c22016-07-26 11:01:14 -07001884
1885 main.step( "Checking ONOS nodes" )
1886 nodeResults = utilities.retry( main.HA.nodesCheck,
1887 False,
Jon Hallf37d44d2017-05-24 10:37:30 -07001888 args=[ main.activeNodes ],
Jon Halld2871c22016-07-26 11:01:14 -07001889 sleep=15,
1890 attempts=5 )
1891
1892 utilities.assert_equals( expect=True, actual=nodeResults,
1893 onpass="Nodes check successful",
1894 onfail="Nodes check NOT successful" )
1895
1896 if not nodeResults:
1897 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001898 cli = main.CLIs[ i ]
Jon Halld2871c22016-07-26 11:01:14 -07001899 main.log.debug( "{} components not ACTIVE: \n{}".format(
1900 cli.name,
1901 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
1902 main.log.error( "Failed to start ONOS, stopping test" )
1903 main.cleanup()
1904 main.exit()
Jon Hallf37d44d2017-05-24 10:37:30 -07001905 node = main.activeNodes[ 0 ]
1906 main.log.debug( main.CLIs[ node ].nodes( jsonFormat=False ) )
1907 main.log.debug( main.CLIs[ node ].leaders( jsonFormat=False ) )
1908 main.log.debug( main.CLIs[ node ].partitions( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001909
Jon Halla440e872016-03-31 15:15:50 -07001910 main.step( "Rerun for election on the node(s) that were killed" )
1911 runResults = main.TRUE
1912 for i in main.kill:
1913 runResults = runResults and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001914 main.CLIs[ i ].electionTestRun()
Jon Halla440e872016-03-31 15:15:50 -07001915 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1916 onpass="ONOS nodes reran for election topic",
1917 onfail="Errror rerunning for election" )
1918
Jon Hall5cf14d52015-07-16 12:15:19 -07001919 def CASE7( self, main ):
1920 """
1921 Check state after ONOS failure
1922 """
1923 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001924 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001925 assert main, "main not defined"
1926 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001927 assert main.CLIs, "main.CLIs not defined"
1928 assert main.nodes, "main.nodes not defined"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001929 try:
1930 main.kill
1931 except AttributeError:
1932 main.kill = []
1933
Jon Hall5cf14d52015-07-16 12:15:19 -07001934 main.case( "Running ONOS Constant State Tests" )
1935
1936 main.step( "Check that each switch has a master" )
1937 # Assert that each device has a master
1938 rolesNotNull = main.TRUE
1939 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001940 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001941 t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001942 name="rolesNotNull-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001943 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001944 threads.append( t )
1945 t.start()
1946
1947 for t in threads:
1948 t.join()
1949 rolesNotNull = rolesNotNull and t.result
1950 utilities.assert_equals(
1951 expect=main.TRUE,
1952 actual=rolesNotNull,
1953 onpass="Each device has a master",
1954 onfail="Some devices don't have a master assigned" )
1955
1956 main.step( "Read device roles from ONOS" )
1957 ONOSMastership = []
Jon Halla440e872016-03-31 15:15:50 -07001958 mastershipCheck = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001959 consistentMastership = True
1960 rolesResults = True
1961 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001962 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001963 t = main.Thread( target=main.CLIs[ i ].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001964 name="roles-" + str( i ),
1965 args=[] )
1966 threads.append( t )
1967 t.start()
1968
1969 for t in threads:
1970 t.join()
1971 ONOSMastership.append( t.result )
1972
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001973 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001974 node = str( main.activeNodes[ i ] + 1 )
1975 if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001976 main.log.error( "Error in getting ONOS" + node + " roles" )
1977 main.log.warn( "ONOS" + node + " mastership response: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001978 repr( ONOSMastership[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001979 rolesResults = False
1980 utilities.assert_equals(
1981 expect=True,
1982 actual=rolesResults,
1983 onpass="No error in reading roles output",
1984 onfail="Error in reading roles from ONOS" )
1985
1986 main.step( "Check for consistency in roles from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001987 if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001988 main.log.info(
1989 "Switch roles are consistent across all ONOS nodes" )
1990 else:
1991 consistentMastership = False
1992 utilities.assert_equals(
1993 expect=True,
1994 actual=consistentMastership,
1995 onpass="Switch roles are consistent across all ONOS nodes",
1996 onfail="ONOS nodes have different views of switch roles" )
1997
1998 if rolesResults and not consistentMastership:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07001999 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002000 node = str( main.activeNodes[ i ] + 1 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002001 main.log.warn( "ONOS" + node + " roles: ",
2002 json.dumps( json.loads( ONOSMastership[ i ] ),
2003 sort_keys=True,
2004 indent=4,
2005 separators=( ',', ': ' ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002006
2007 # NOTE: we expect mastership to change on controller failure
Jon Hall5cf14d52015-07-16 12:15:19 -07002008
2009 main.step( "Get the intents and compare across all nodes" )
2010 ONOSIntents = []
2011 intentCheck = main.FALSE
2012 consistentIntents = True
2013 intentsResults = True
2014 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002015 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002016 t = main.Thread( target=main.CLIs[ i ].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07002017 name="intents-" + str( i ),
2018 args=[],
2019 kwargs={ 'jsonFormat': True } )
2020 threads.append( t )
2021 t.start()
2022
2023 for t in threads:
2024 t.join()
2025 ONOSIntents.append( t.result )
2026
Jon Hallf37d44d2017-05-24 10:37:30 -07002027 for i in range( len( ONOSIntents ) ):
2028 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002029 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002030 main.log.error( "Error in getting ONOS" + node + " intents" )
2031 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07002032 repr( ONOSIntents[ i ] ) )
2033 intentsResults = False
2034 utilities.assert_equals(
2035 expect=True,
2036 actual=intentsResults,
2037 onpass="No error in reading intents output",
2038 onfail="Error in reading intents from ONOS" )
2039
2040 main.step( "Check for consistency in Intents from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002041 if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07002042 main.log.info( "Intents are consistent across all ONOS " +
2043 "nodes" )
2044 else:
2045 consistentIntents = False
2046
2047 # Try to make it easy to figure out what is happening
2048 #
2049 # Intent ONOS1 ONOS2 ...
2050 # 0x01 INSTALLED INSTALLING
2051 # ... ... ...
2052 # ... ... ...
2053 title = " ID"
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002054 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07002055 title += " " * 10 + "ONOS" + str( n + 1 )
2056 main.log.warn( title )
2057 # get all intent keys in the cluster
2058 keys = []
2059 for nodeStr in ONOSIntents:
2060 node = json.loads( nodeStr )
2061 for intent in node:
2062 keys.append( intent.get( 'id' ) )
2063 keys = set( keys )
2064 for key in keys:
2065 row = "%-13s" % key
2066 for nodeStr in ONOSIntents:
2067 node = json.loads( nodeStr )
2068 for intent in node:
2069 if intent.get( 'id' ) == key:
2070 row += "%-15s" % intent.get( 'state' )
2071 main.log.warn( row )
2072 # End table view
2073
2074 utilities.assert_equals(
2075 expect=True,
2076 actual=consistentIntents,
2077 onpass="Intents are consistent across all ONOS nodes",
2078 onfail="ONOS nodes have different views of intents" )
2079 intentStates = []
2080 for node in ONOSIntents: # Iter through ONOS nodes
2081 nodeStates = []
2082 # Iter through intents of a node
2083 try:
2084 for intent in json.loads( node ):
2085 nodeStates.append( intent[ 'state' ] )
2086 except ( ValueError, TypeError ):
2087 main.log.exception( "Error in parsing intents" )
2088 main.log.error( repr( node ) )
2089 intentStates.append( nodeStates )
Jon Hallf37d44d2017-05-24 10:37:30 -07002090 out = [ ( i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002091 main.log.info( dict( out ) )
2092
2093 if intentsResults and not consistentIntents:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002094 for i in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002095 node = str( main.activeNodes[ i ] + 1 )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002096 main.log.warn( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07002097 main.log.warn( json.dumps(
2098 json.loads( ONOSIntents[ i ] ),
2099 sort_keys=True,
2100 indent=4,
2101 separators=( ',', ': ' ) ) )
2102 elif intentsResults and consistentIntents:
2103 intentCheck = main.TRUE
2104
2105 # NOTE: Store has no durability, so intents are lost across system
2106 # restarts
2107 main.step( "Compare current intents with intents before the failure" )
2108 # NOTE: this requires case 5 to pass for intentState to be set.
2109 # maybe we should stop the test if that fails?
2110 sameIntents = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002111 try:
2112 intentState
2113 except NameError:
2114 main.log.warn( "No previous intent state was saved" )
2115 else:
2116 if intentState and intentState == ONOSIntents[ 0 ]:
2117 sameIntents = main.TRUE
2118 main.log.info( "Intents are consistent with before failure" )
2119 # TODO: possibly the states have changed? we may need to figure out
2120 # what the acceptable states are
2121 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
2122 sameIntents = main.TRUE
2123 try:
2124 before = json.loads( intentState )
2125 after = json.loads( ONOSIntents[ 0 ] )
2126 for intent in before:
2127 if intent not in after:
2128 sameIntents = main.FALSE
2129 main.log.debug( "Intent is not currently in ONOS " +
2130 "(at least in the same form):" )
2131 main.log.debug( json.dumps( intent ) )
2132 except ( ValueError, TypeError ):
2133 main.log.exception( "Exception printing intents" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002134 main.log.debug( repr( ONOSIntents[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002135 main.log.debug( repr( intentState ) )
2136 if sameIntents == main.FALSE:
2137 try:
2138 main.log.debug( "ONOS intents before: " )
2139 main.log.debug( json.dumps( json.loads( intentState ),
2140 sort_keys=True, indent=4,
2141 separators=( ',', ': ' ) ) )
2142 main.log.debug( "Current ONOS intents: " )
2143 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2144 sort_keys=True, indent=4,
2145 separators=( ',', ': ' ) ) )
2146 except ( ValueError, TypeError ):
2147 main.log.exception( "Exception printing intents" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002148 main.log.debug( repr( ONOSIntents[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002149 main.log.debug( repr( intentState ) )
2150 utilities.assert_equals(
2151 expect=main.TRUE,
2152 actual=sameIntents,
2153 onpass="Intents are consistent with before failure",
2154 onfail="The Intents changed during failure" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002155 intentCheck = intentCheck and sameIntents
2156
2157 main.step( "Get the OF Table entries and compare to before " +
2158 "component failure" )
2159 FlowTables = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002160 for i in range( 28 ):
2161 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08002162 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
Jon Hallf37d44d2017-05-24 10:37:30 -07002163 curSwitch = main.Mininet1.flowTableComp( flows[ i ], tmpFlows )
Jon Hall41d39f12016-04-11 22:54:35 -07002164 FlowTables = FlowTables and curSwitch
2165 if curSwitch == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08002166 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002167 utilities.assert_equals(
2168 expect=main.TRUE,
2169 actual=FlowTables,
2170 onpass="No changes were found in the flow tables",
2171 onfail="Changes were found in the flow tables" )
2172
2173 main.Mininet2.pingLongKill()
Jon Hallf37d44d2017-05-24 10:37:30 -07002174 """
Jon Hall5cf14d52015-07-16 12:15:19 -07002175 main.step( "Check the continuous pings to ensure that no packets " +
2176 "were dropped during component failure" )
2177 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2178 main.params[ 'TESTONIP' ] )
2179 LossInPings = main.FALSE
2180 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2181 for i in range( 8, 18 ):
2182 main.log.info(
2183 "Checking for a loss in pings along flow from s" +
2184 str( i ) )
2185 LossInPings = main.Mininet2.checkForLoss(
2186 "/tmp/ping.h" +
2187 str( i ) ) or LossInPings
2188 if LossInPings == main.TRUE:
2189 main.log.info( "Loss in ping detected" )
2190 elif LossInPings == main.ERROR:
2191 main.log.info( "There are multiple mininet process running" )
2192 elif LossInPings == main.FALSE:
2193 main.log.info( "No Loss in the pings" )
2194 main.log.info( "No loss of dataplane connectivity" )
2195 utilities.assert_equals(
2196 expect=main.FALSE,
2197 actual=LossInPings,
2198 onpass="No Loss of connectivity",
2199 onfail="Loss of dataplane connectivity detected" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002200 """
Jon Hall5cf14d52015-07-16 12:15:19 -07002201 main.step( "Leadership Election is still functional" )
2202 # Test of LeadershipElection
2203 leaderList = []
Jon Hall5cf14d52015-07-16 12:15:19 -07002204
Jon Hall3b489db2015-10-05 14:38:37 -07002205 restarted = []
2206 for i in main.kill:
Jon Hallf37d44d2017-05-24 10:37:30 -07002207 restarted.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -07002208 leaderResult = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -07002209
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002210 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002211 cli = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002212 leaderN = cli.electionTestLeader()
2213 leaderList.append( leaderN )
2214 if leaderN == main.FALSE:
2215 # error in response
2216 main.log.error( "Something is wrong with " +
2217 "electionTestLeader function, check the" +
2218 " error logs" )
2219 leaderResult = main.FALSE
2220 elif leaderN is None:
2221 main.log.error( cli.name +
2222 " shows no leader for the election-app was" +
2223 " elected after the old one died" )
2224 leaderResult = main.FALSE
2225 elif leaderN in restarted:
2226 main.log.error( cli.name + " shows " + str( leaderN ) +
2227 " as leader for the election-app, but it " +
2228 "was restarted" )
2229 leaderResult = main.FALSE
2230 if len( set( leaderList ) ) != 1:
2231 leaderResult = main.FALSE
2232 main.log.error(
2233 "Inconsistent view of leader for the election test app" )
2234 # TODO: print the list
2235 utilities.assert_equals(
2236 expect=main.TRUE,
2237 actual=leaderResult,
2238 onpass="Leadership election passed",
2239 onfail="Something went wrong with Leadership election" )
2240
2241 def CASE8( self, main ):
2242 """
2243 Compare topo
2244 """
2245 import json
2246 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002247 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002248 assert main, "main not defined"
2249 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002250 assert main.CLIs, "main.CLIs not defined"
2251 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002252
2253 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002254 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002255 " and ONOS"
Jon Hall5cf14d52015-07-16 12:15:19 -07002256 topoResult = main.FALSE
Jon Hall6e709752016-02-01 13:38:46 -08002257 topoFailMsg = "ONOS topology don't match Mininet"
Jon Hall5cf14d52015-07-16 12:15:19 -07002258 elapsed = 0
2259 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08002260 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002261 startTime = time.time()
2262 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08002263 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hall96091e62015-09-21 17:34:17 -07002264 devicesResults = main.TRUE
2265 linksResults = main.TRUE
2266 hostsResults = main.TRUE
2267 hostAttachmentResults = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002268 count += 1
2269 cliStart = time.time()
2270 devices = []
2271 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002272 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002273 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002274 name="devices-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002275 args=[ main.CLIs[ i ].devices, [ None ] ],
2276 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002277 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002278 threads.append( t )
2279 t.start()
2280
2281 for t in threads:
2282 t.join()
2283 devices.append( t.result )
2284 hosts = []
2285 ipResult = main.TRUE
2286 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002287 for i in main.activeNodes:
Jon Halld8f6de82015-12-17 17:04:34 -08002288 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002289 name="hosts-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002290 args=[ main.CLIs[ i ].hosts, [ None ] ],
2291 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Halld8f6de82015-12-17 17:04:34 -08002292 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002293 threads.append( t )
2294 t.start()
2295
2296 for t in threads:
2297 t.join()
2298 try:
2299 hosts.append( json.loads( t.result ) )
2300 except ( ValueError, TypeError ):
2301 main.log.exception( "Error parsing hosts results" )
2302 main.log.error( repr( t.result ) )
Jon Hallf3d16e72015-12-16 17:45:08 -08002303 hosts.append( None )
Jon Hall5cf14d52015-07-16 12:15:19 -07002304 for controller in range( 0, len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002305 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallacd1b182015-12-17 11:43:20 -08002306 if hosts[ controller ]:
2307 for host in hosts[ controller ]:
2308 if host is None or host.get( 'ipAddresses', [] ) == []:
2309 main.log.error(
2310 "Error with host ipAddresses on controller" +
2311 controllerStr + ": " + str( host ) )
2312 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002313 ports = []
2314 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002315 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002316 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002317 name="ports-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002318 args=[ main.CLIs[ i ].ports, [ None ] ],
2319 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002320 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002321 threads.append( t )
2322 t.start()
2323
2324 for t in threads:
2325 t.join()
2326 ports.append( t.result )
2327 links = []
2328 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002329 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002330 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002331 name="links-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002332 args=[ main.CLIs[ i ].links, [ None ] ],
2333 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002334 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002335 threads.append( t )
2336 t.start()
2337
2338 for t in threads:
2339 t.join()
2340 links.append( t.result )
2341 clusters = []
2342 threads = []
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002343 for i in main.activeNodes:
Jon Hall6e709752016-02-01 13:38:46 -08002344 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002345 name="clusters-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002346 args=[ main.CLIs[ i ].clusters, [ None ] ],
2347 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Hall6e709752016-02-01 13:38:46 -08002348 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002349 threads.append( t )
2350 t.start()
2351
2352 for t in threads:
2353 t.join()
2354 clusters.append( t.result )
2355
2356 elapsed = time.time() - startTime
2357 cliTime = time.time() - cliStart
2358 print "Elapsed time: " + str( elapsed )
2359 print "CLI time: " + str( cliTime )
2360
Jon Hall6e709752016-02-01 13:38:46 -08002361 if all( e is None for e in devices ) and\
2362 all( e is None for e in hosts ) and\
2363 all( e is None for e in ports ) and\
2364 all( e is None for e in links ) and\
2365 all( e is None for e in clusters ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002366 topoFailMsg = "Could not get topology from ONOS"
2367 main.log.error( topoFailMsg )
2368 continue # Try again, No use trying to compare
Jon Hall6e709752016-02-01 13:38:46 -08002369
Jon Hall5cf14d52015-07-16 12:15:19 -07002370 mnSwitches = main.Mininet1.getSwitches()
2371 mnLinks = main.Mininet1.getLinks()
2372 mnHosts = main.Mininet1.getHosts()
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002373 for controller in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002374 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002375 if devices[ controller ] and ports[ controller ] and\
Jon Hallf37d44d2017-05-24 10:37:30 -07002376 "Error" not in devices[ controller ] and\
2377 "Error" not in ports[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002378
Jon Hallc6793552016-01-19 14:18:37 -08002379 try:
2380 currentDevicesResult = main.Mininet1.compareSwitches(
2381 mnSwitches,
2382 json.loads( devices[ controller ] ),
2383 json.loads( ports[ controller ] ) )
2384 except ( TypeError, ValueError ) as e:
2385 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
2386 devices[ controller ], ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002387 else:
2388 currentDevicesResult = main.FALSE
2389 utilities.assert_equals( expect=main.TRUE,
2390 actual=currentDevicesResult,
2391 onpass="ONOS" + controllerStr +
2392 " Switches view is correct",
2393 onfail="ONOS" + controllerStr +
2394 " Switches view is incorrect" )
2395
2396 if links[ controller ] and "Error" not in links[ controller ]:
2397 currentLinksResult = main.Mininet1.compareLinks(
2398 mnSwitches, mnLinks,
2399 json.loads( links[ controller ] ) )
2400 else:
2401 currentLinksResult = main.FALSE
2402 utilities.assert_equals( expect=main.TRUE,
2403 actual=currentLinksResult,
2404 onpass="ONOS" + controllerStr +
2405 " links view is correct",
2406 onfail="ONOS" + controllerStr +
2407 " links view is incorrect" )
Jon Hall657cdf62015-12-17 14:40:51 -08002408 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002409 currentHostsResult = main.Mininet1.compareHosts(
2410 mnHosts,
2411 hosts[ controller ] )
Jon Hall13b446e2016-01-05 12:17:01 -08002412 elif hosts[ controller ] == []:
2413 currentHostsResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002414 else:
2415 currentHostsResult = main.FALSE
2416 utilities.assert_equals( expect=main.TRUE,
2417 actual=currentHostsResult,
2418 onpass="ONOS" + controllerStr +
2419 " hosts exist in Mininet",
2420 onfail="ONOS" + controllerStr +
2421 " hosts don't match Mininet" )
2422 # CHECKING HOST ATTACHMENT POINTS
2423 hostAttachment = True
2424 zeroHosts = False
2425 # FIXME: topo-HA/obelisk specific mappings:
2426 # key is mac and value is dpid
2427 mappings = {}
2428 for i in range( 1, 29 ): # hosts 1 through 28
2429 # set up correct variables:
Jon Hallf37d44d2017-05-24 10:37:30 -07002430 macId = "00:" * 5 + hex( i ).split( "0x" )[ 1 ].upper().zfill( 2 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002431 if i == 1:
Jon Hallf37d44d2017-05-24 10:37:30 -07002432 deviceId = "1000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002433 elif i == 2:
Jon Hallf37d44d2017-05-24 10:37:30 -07002434 deviceId = "2000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002435 elif i == 3:
Jon Hallf37d44d2017-05-24 10:37:30 -07002436 deviceId = "3000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002437 elif i == 4:
Jon Hallf37d44d2017-05-24 10:37:30 -07002438 deviceId = "3004".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002439 elif i == 5:
Jon Hallf37d44d2017-05-24 10:37:30 -07002440 deviceId = "5000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002441 elif i == 6:
Jon Hallf37d44d2017-05-24 10:37:30 -07002442 deviceId = "6000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002443 elif i == 7:
Jon Hallf37d44d2017-05-24 10:37:30 -07002444 deviceId = "6007".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002445 elif i >= 8 and i <= 17:
2446 dpid = '3' + str( i ).zfill( 3 )
Jon Hallf37d44d2017-05-24 10:37:30 -07002447 deviceId = dpid.zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002448 elif i >= 18 and i <= 27:
2449 dpid = '6' + str( i ).zfill( 3 )
Jon Hallf37d44d2017-05-24 10:37:30 -07002450 deviceId = dpid.zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002451 elif i == 28:
Jon Hallf37d44d2017-05-24 10:37:30 -07002452 deviceId = "2800".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002453 mappings[ macId ] = deviceId
Jon Halld8f6de82015-12-17 17:04:34 -08002454 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002455 if hosts[ controller ] == []:
2456 main.log.warn( "There are no hosts discovered" )
2457 zeroHosts = True
2458 else:
2459 for host in hosts[ controller ]:
2460 mac = None
2461 location = None
2462 device = None
2463 port = None
2464 try:
2465 mac = host.get( 'mac' )
2466 assert mac, "mac field could not be found for this host object"
2467
2468 location = host.get( 'location' )
2469 assert location, "location field could not be found for this host object"
2470
2471 # Trim the protocol identifier off deviceId
Jon Hallf37d44d2017-05-24 10:37:30 -07002472 device = str( location.get( 'elementId' ) ).split( ':' )[ 1 ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002473 assert device, "elementId field could not be found for this host location object"
2474
2475 port = location.get( 'port' )
2476 assert port, "port field could not be found for this host location object"
2477
2478 # Now check if this matches where they should be
2479 if mac and device and port:
2480 if str( port ) != "1":
2481 main.log.error( "The attachment port is incorrect for " +
2482 "host " + str( mac ) +
Jon Hallf37d44d2017-05-24 10:37:30 -07002483 ". Expected: 1 Actual: " + str( port ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002484 hostAttachment = False
2485 if device != mappings[ str( mac ) ]:
2486 main.log.error( "The attachment device is incorrect for " +
2487 "host " + str( mac ) +
2488 ". Expected: " + mappings[ str( mac ) ] +
2489 " Actual: " + device )
2490 hostAttachment = False
2491 else:
2492 hostAttachment = False
2493 except AssertionError:
2494 main.log.exception( "Json object not as expected" )
2495 main.log.error( repr( host ) )
2496 hostAttachment = False
2497 else:
2498 main.log.error( "No hosts json output or \"Error\"" +
2499 " in output. hosts = " +
2500 repr( hosts[ controller ] ) )
2501 if zeroHosts is False:
2502 hostAttachment = True
2503
2504 # END CHECKING HOST ATTACHMENT POINTS
2505 devicesResults = devicesResults and currentDevicesResult
2506 linksResults = linksResults and currentLinksResult
2507 hostsResults = hostsResults and currentHostsResult
2508 hostAttachmentResults = hostAttachmentResults and\
2509 hostAttachment
Jon Halla440e872016-03-31 15:15:50 -07002510 topoResult = ( devicesResults and linksResults
2511 and hostsResults and ipResult and
2512 hostAttachmentResults )
Jon Halle9b1fa32015-12-08 15:32:21 -08002513 utilities.assert_equals( expect=True,
2514 actual=topoResult,
2515 onpass="ONOS topology matches Mininet",
Jon Hall6e709752016-02-01 13:38:46 -08002516 onfail=topoFailMsg )
Jon Halle9b1fa32015-12-08 15:32:21 -08002517 # End of While loop to pull ONOS state
Jon Hall5cf14d52015-07-16 12:15:19 -07002518
2519 # Compare json objects for hosts and dataplane clusters
2520
2521 # hosts
2522 main.step( "Hosts view is consistent across all ONOS nodes" )
2523 consistentHostsResult = main.TRUE
2524 for controller in range( len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002525 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall13b446e2016-01-05 12:17:01 -08002526 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002527 if hosts[ controller ] == hosts[ 0 ]:
2528 continue
2529 else: # hosts not consistent
2530 main.log.error( "hosts from ONOS" + controllerStr +
2531 " is inconsistent with ONOS1" )
2532 main.log.warn( repr( hosts[ controller ] ) )
2533 consistentHostsResult = main.FALSE
2534
2535 else:
2536 main.log.error( "Error in getting ONOS hosts from ONOS" +
2537 controllerStr )
2538 consistentHostsResult = main.FALSE
2539 main.log.warn( "ONOS" + controllerStr +
2540 " hosts response: " +
2541 repr( hosts[ controller ] ) )
2542 utilities.assert_equals(
2543 expect=main.TRUE,
2544 actual=consistentHostsResult,
2545 onpass="Hosts view is consistent across all ONOS nodes",
2546 onfail="ONOS nodes have different views of hosts" )
2547
2548 main.step( "Hosts information is correct" )
2549 hostsResults = hostsResults and ipResult
2550 utilities.assert_equals(
2551 expect=main.TRUE,
2552 actual=hostsResults,
2553 onpass="Host information is correct",
2554 onfail="Host information is incorrect" )
2555
2556 main.step( "Host attachment points to the network" )
2557 utilities.assert_equals(
2558 expect=True,
2559 actual=hostAttachmentResults,
2560 onpass="Hosts are correctly attached to the network",
2561 onfail="ONOS did not correctly attach hosts to the network" )
2562
2563 # Strongly connected clusters of devices
2564 main.step( "Clusters view is consistent across all ONOS nodes" )
2565 consistentClustersResult = main.TRUE
2566 for controller in range( len( clusters ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002567 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002568 if "Error" not in clusters[ controller ]:
2569 if clusters[ controller ] == clusters[ 0 ]:
2570 continue
2571 else: # clusters not consistent
2572 main.log.error( "clusters from ONOS" +
2573 controllerStr +
2574 " is inconsistent with ONOS1" )
2575 consistentClustersResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002576 else:
2577 main.log.error( "Error in getting dataplane clusters " +
2578 "from ONOS" + controllerStr )
2579 consistentClustersResult = main.FALSE
2580 main.log.warn( "ONOS" + controllerStr +
2581 " clusters response: " +
2582 repr( clusters[ controller ] ) )
2583 utilities.assert_equals(
2584 expect=main.TRUE,
2585 actual=consistentClustersResult,
2586 onpass="Clusters view is consistent across all ONOS nodes",
2587 onfail="ONOS nodes have different views of clusters" )
Jon Hall64948022016-05-12 13:38:50 -07002588 if not consistentClustersResult:
2589 main.log.debug( clusters )
Jon Hall5cf14d52015-07-16 12:15:19 -07002590
2591 main.step( "There is only one SCC" )
2592 # there should always only be one cluster
2593 try:
2594 numClusters = len( json.loads( clusters[ 0 ] ) )
2595 except ( ValueError, TypeError ):
2596 main.log.exception( "Error parsing clusters[0]: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07002597 repr( clusters[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002598 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07002599 clusterResults = main.FALSE
2600 if numClusters == 1:
2601 clusterResults = main.TRUE
2602 utilities.assert_equals(
2603 expect=1,
2604 actual=numClusters,
2605 onpass="ONOS shows 1 SCC",
2606 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2607
2608 topoResult = ( devicesResults and linksResults
2609 and hostsResults and consistentHostsResult
2610 and consistentClustersResult and clusterResults
2611 and ipResult and hostAttachmentResults )
2612
2613 topoResult = topoResult and int( count <= 2 )
2614 note = "note it takes about " + str( int( cliTime ) ) + \
2615 " seconds for the test to make all the cli calls to fetch " +\
2616 "the topology from each ONOS instance"
2617 main.log.info(
2618 "Very crass estimate for topology discovery/convergence( " +
2619 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2620 str( count ) + " tries" )
2621
2622 main.step( "Device information is correct" )
2623 utilities.assert_equals(
2624 expect=main.TRUE,
2625 actual=devicesResults,
2626 onpass="Device information is correct",
2627 onfail="Device information is incorrect" )
2628
2629 main.step( "Links are correct" )
2630 utilities.assert_equals(
2631 expect=main.TRUE,
2632 actual=linksResults,
2633 onpass="Link are correct",
2634 onfail="Links are incorrect" )
2635
Jon Halla440e872016-03-31 15:15:50 -07002636 main.step( "Hosts are correct" )
2637 utilities.assert_equals(
2638 expect=main.TRUE,
2639 actual=hostsResults,
2640 onpass="Hosts are correct",
2641 onfail="Hosts are incorrect" )
2642
Jon Hall5cf14d52015-07-16 12:15:19 -07002643 # FIXME: move this to an ONOS state case
2644 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -07002645 nodeResults = utilities.retry( main.HA.nodesCheck,
2646 False,
Jon Hallf37d44d2017-05-24 10:37:30 -07002647 args=[ main.activeNodes ],
Jon Hall41d39f12016-04-11 22:54:35 -07002648 attempts=5 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002649
Jon Hall41d39f12016-04-11 22:54:35 -07002650 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Hall5cf14d52015-07-16 12:15:19 -07002651 onpass="Nodes check successful",
2652 onfail="Nodes check NOT successful" )
Jon Halla440e872016-03-31 15:15:50 -07002653 if not nodeResults:
Jon Hall41d39f12016-04-11 22:54:35 -07002654 for i in main.activeNodes:
Jon Halla440e872016-03-31 15:15:50 -07002655 main.log.debug( "{} components not ACTIVE: \n{}".format(
Jon Hallf37d44d2017-05-24 10:37:30 -07002656 main.CLIs[ i ].name,
2657 main.CLIs[ i ].sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002658
Jon Halld2871c22016-07-26 11:01:14 -07002659 if not topoResult:
2660 main.cleanup()
2661 main.exit()
2662
Jon Hall5cf14d52015-07-16 12:15:19 -07002663 def CASE9( self, main ):
2664 """
2665 Link s3-s28 down
2666 """
2667 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002668 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002669 assert main, "main not defined"
2670 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002671 assert main.CLIs, "main.CLIs not defined"
2672 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002673 # NOTE: You should probably run a topology check after this
2674
2675 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2676
2677 description = "Turn off a link to ensure that Link Discovery " +\
2678 "is working properly"
2679 main.case( description )
2680
2681 main.step( "Kill Link between s3 and s28" )
2682 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2683 main.log.info( "Waiting " + str( linkSleep ) +
2684 " seconds for link down to be discovered" )
2685 time.sleep( linkSleep )
2686 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2687 onpass="Link down successful",
2688 onfail="Failed to bring link down" )
2689 # TODO do some sort of check here
2690
2691 def CASE10( self, main ):
2692 """
2693 Link s3-s28 up
2694 """
2695 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002696 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002697 assert main, "main not defined"
2698 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002699 assert main.CLIs, "main.CLIs not defined"
2700 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002701 # NOTE: You should probably run a topology check after this
2702
2703 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2704
2705 description = "Restore a link to ensure that Link Discovery is " + \
2706 "working properly"
2707 main.case( description )
2708
2709 main.step( "Bring link between s3 and s28 back up" )
2710 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2711 main.log.info( "Waiting " + str( linkSleep ) +
2712 " seconds for link up to be discovered" )
2713 time.sleep( linkSleep )
2714 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2715 onpass="Link up successful",
2716 onfail="Failed to bring link up" )
2717 # TODO do some sort of check here
2718
2719 def CASE11( self, main ):
2720 """
2721 Switch Down
2722 """
2723 # NOTE: You should probably run a topology check after this
2724 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002725 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002726 assert main, "main not defined"
2727 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002728 assert main.CLIs, "main.CLIs not defined"
2729 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002730
2731 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2732
2733 description = "Killing a switch to ensure it is discovered correctly"
Jon Hallf37d44d2017-05-24 10:37:30 -07002734 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002735 main.case( description )
2736 switch = main.params[ 'kill' ][ 'switch' ]
2737 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2738
2739 # TODO: Make this switch parameterizable
2740 main.step( "Kill " + switch )
2741 main.log.info( "Deleting " + switch )
2742 main.Mininet1.delSwitch( switch )
2743 main.log.info( "Waiting " + str( switchSleep ) +
2744 " seconds for switch down to be discovered" )
2745 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002746 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002747 # Peek at the deleted switch
2748 main.log.warn( str( device ) )
2749 result = main.FALSE
2750 if device and device[ 'available' ] is False:
2751 result = main.TRUE
2752 utilities.assert_equals( expect=main.TRUE, actual=result,
2753 onpass="Kill switch successful",
2754 onfail="Failed to kill switch?" )
2755
2756 def CASE12( self, main ):
2757 """
2758 Switch Up
2759 """
2760 # NOTE: You should probably run a topology check after this
2761 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002762 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002763 assert main, "main not defined"
2764 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002765 assert main.CLIs, "main.CLIs not defined"
2766 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002767 assert ONOS1Port, "ONOS1Port not defined"
2768 assert ONOS2Port, "ONOS2Port not defined"
2769 assert ONOS3Port, "ONOS3Port not defined"
2770 assert ONOS4Port, "ONOS4Port not defined"
2771 assert ONOS5Port, "ONOS5Port not defined"
2772 assert ONOS6Port, "ONOS6Port not defined"
2773 assert ONOS7Port, "ONOS7Port not defined"
2774
2775 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2776 switch = main.params[ 'kill' ][ 'switch' ]
2777 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2778 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hallf37d44d2017-05-24 10:37:30 -07002779 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002780 description = "Adding a switch to ensure it is discovered correctly"
2781 main.case( description )
2782
2783 main.step( "Add back " + switch )
2784 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2785 for peer in links:
2786 main.Mininet1.addLink( switch, peer )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002787 ipList = [ node.ip_address for node in main.nodes ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002788 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2789 main.log.info( "Waiting " + str( switchSleep ) +
2790 " seconds for switch up to be discovered" )
2791 time.sleep( switchSleep )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002792 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002793 # Peek at the deleted switch
2794 main.log.warn( str( device ) )
2795 result = main.FALSE
2796 if device and device[ 'available' ]:
2797 result = main.TRUE
2798 utilities.assert_equals( expect=main.TRUE, actual=result,
2799 onpass="add switch successful",
2800 onfail="Failed to add switch?" )
2801
2802 def CASE13( self, main ):
2803 """
2804 Clean up
2805 """
2806 import os
2807 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002808 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002809 assert main, "main not defined"
2810 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002811 assert main.CLIs, "main.CLIs not defined"
2812 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002813
2814 # printing colors to terminal
2815 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2816 'blue': '\033[94m', 'green': '\033[92m',
2817 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2818 main.case( "Test Cleanup" )
2819 main.step( "Killing tcpdumps" )
2820 main.Mininet2.stopTcpdump()
2821
2822 testname = main.TEST
Jon Hall96091e62015-09-21 17:34:17 -07002823 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall5cf14d52015-07-16 12:15:19 -07002824 main.step( "Copying MN pcap and ONOS log files to test station" )
2825 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2826 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002827 # NOTE: MN Pcap file is being saved to logdir.
2828 # We scp this file as MN and TestON aren't necessarily the same vm
2829
2830 # FIXME: To be replaced with a Jenkin's post script
Jon Hall5cf14d52015-07-16 12:15:19 -07002831 # TODO: Load these from params
2832 # NOTE: must end in /
2833 logFolder = "/opt/onos/log/"
2834 logFiles = [ "karaf.log", "karaf.log.1" ]
2835 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002836 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002837 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002838 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002839 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2840 logFolder + f, dstName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002841 # std*.log's
2842 # NOTE: must end in /
2843 logFolder = "/opt/onos/var/"
2844 logFiles = [ "stderr.log", "stdout.log" ]
2845 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002846 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002847 for node in main.nodes:
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002848 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002849 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2850 logFolder + f, dstName )
2851 else:
2852 main.log.debug( "skipping saving log files" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002853
2854 main.step( "Stopping Mininet" )
2855 mnResult = main.Mininet1.stopNet()
2856 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2857 onpass="Mininet stopped",
2858 onfail="MN cleanup NOT successful" )
2859
2860 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002861 for node in main.nodes:
Jon Hall96091e62015-09-21 17:34:17 -07002862 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2863 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002864
2865 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07002866 timerLog = open( main.logdir + "/Timers.csv", 'w' )
Jon Hall5cf14d52015-07-16 12:15:19 -07002867 # Overwrite with empty line and close
2868 labels = "Gossip Intents, Restart"
2869 data = str( gossipTime ) + ", " + str( main.restartTime )
2870 timerLog.write( labels + "\n" + data )
2871 timerLog.close()
Jon Hallf37d44d2017-05-24 10:37:30 -07002872 except NameError as e:
2873 main.log.exception( e )
Jon Hall5cf14d52015-07-16 12:15:19 -07002874
2875 def CASE14( self, main ):
2876 """
2877 start election app on all onos nodes
2878 """
Jon Halle1a3b752015-07-22 13:02:46 -07002879 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002880 assert main, "main not defined"
2881 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002882 assert main.CLIs, "main.CLIs not defined"
2883 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002884
Jon Hallf37d44d2017-05-24 10:37:30 -07002885 main.case( "Start Leadership Election app" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002886 main.step( "Install leadership election app" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002887 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002888 appResult = onosCli.activateApp( "org.onosproject.election" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002889 utilities.assert_equals(
2890 expect=main.TRUE,
2891 actual=appResult,
2892 onpass="Election app installed",
2893 onfail="Something went wrong with installing Leadership election" )
2894
2895 main.step( "Run for election on each node" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002896 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002897 main.CLIs[ i ].electionTestRun()
2898 time.sleep( 5 )
2899 activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
Jon Hall25463a82016-04-13 14:03:52 -07002900 sameResult, leaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall5cf14d52015-07-16 12:15:19 -07002901 utilities.assert_equals(
Jon Hall25463a82016-04-13 14:03:52 -07002902 expect=True,
2903 actual=sameResult,
2904 onpass="All nodes see the same leaderboards",
2905 onfail="Inconsistent leaderboards" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002906
Jon Hall25463a82016-04-13 14:03:52 -07002907 if sameResult:
2908 leader = leaders[ 0 ][ 0 ]
Jon Hallf37d44d2017-05-24 10:37:30 -07002909 if main.nodes[ main.activeNodes[ 0 ] ].ip_address in leader:
Jon Hall25463a82016-04-13 14:03:52 -07002910 correctLeader = True
2911 else:
2912 correctLeader = False
2913 main.step( "First node was elected leader" )
2914 utilities.assert_equals(
2915 expect=True,
2916 actual=correctLeader,
2917 onpass="Correct leader was elected",
2918 onfail="Incorrect leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002919
2920 def CASE15( self, main ):
2921 """
2922 Check that Leadership Election is still functional
acsmars71adceb2015-08-31 15:09:26 -07002923 15.1 Run election on each node
2924 15.2 Check that each node has the same leaders and candidates
2925 15.3 Find current leader and withdraw
2926 15.4 Check that a new node was elected leader
2927 15.5 Check that that new leader was the candidate of old leader
2928 15.6 Run for election on old leader
2929 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2930 15.8 Make sure that the old leader was added to the candidate list
2931
2932 old and new variable prefixes refer to data from before vs after
2933 withdrawl and later before withdrawl vs after re-election
Jon Hall5cf14d52015-07-16 12:15:19 -07002934 """
2935 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002936 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002937 assert main, "main not defined"
2938 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002939 assert main.CLIs, "main.CLIs not defined"
2940 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002941
Jon Hall5cf14d52015-07-16 12:15:19 -07002942 description = "Check that Leadership Election is still functional"
2943 main.case( description )
Jon Halla440e872016-03-31 15:15:50 -07002944 # NOTE: Need to re-run after restarts since being a canidate is not persistant
Jon Hall5cf14d52015-07-16 12:15:19 -07002945
Jon Halla440e872016-03-31 15:15:50 -07002946 oldLeaders = [] # list of lists of each nodes' candidates before
2947 newLeaders = [] # list of lists of each nodes' candidates after
acsmars71adceb2015-08-31 15:09:26 -07002948 oldLeader = '' # the old leader from oldLeaders, None if not same
2949 newLeader = '' # the new leaders fron newLoeaders, None if not same
2950 oldLeaderCLI = None # the CLI of the old leader used for re-electing
2951 expectNoLeader = False # True when there is only one leader
2952 if main.numCtrls == 1:
2953 expectNoLeader = True
2954
2955 main.step( "Run for election on each node" )
2956 electionResult = main.TRUE
2957
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002958 for i in main.activeNodes: # run test election on each node
Jon Hallf37d44d2017-05-24 10:37:30 -07002959 if main.CLIs[ i ].electionTestRun() == main.FALSE:
acsmars71adceb2015-08-31 15:09:26 -07002960 electionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002961 utilities.assert_equals(
2962 expect=main.TRUE,
acsmars71adceb2015-08-31 15:09:26 -07002963 actual=electionResult,
2964 onpass="All nodes successfully ran for leadership",
2965 onfail="At least one node failed to run for leadership" )
2966
acsmars3a72bde2015-09-02 14:16:22 -07002967 if electionResult == main.FALSE:
2968 main.log.error(
2969 "Skipping Test Case because Election Test App isn't loaded" )
2970 main.skipCase()
2971
acsmars71adceb2015-08-31 15:09:26 -07002972 main.step( "Check that each node shows the same leader and candidates" )
Jon Halla440e872016-03-31 15:15:50 -07002973 failMessage = "Nodes have different leaderboards"
Jon Hallf37d44d2017-05-24 10:37:30 -07002974 activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
Jon Hall41d39f12016-04-11 22:54:35 -07002975 sameResult, oldLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Halla440e872016-03-31 15:15:50 -07002976 if sameResult:
2977 oldLeader = oldLeaders[ 0 ][ 0 ]
2978 main.log.warn( oldLeader )
acsmars71adceb2015-08-31 15:09:26 -07002979 else:
Jon Halla440e872016-03-31 15:15:50 -07002980 oldLeader = None
acsmars71adceb2015-08-31 15:09:26 -07002981 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002982 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002983 actual=sameResult,
Jon Halla440e872016-03-31 15:15:50 -07002984 onpass="Leaderboards are consistent for the election topic",
acsmars71adceb2015-08-31 15:09:26 -07002985 onfail=failMessage )
Jon Hall5cf14d52015-07-16 12:15:19 -07002986
2987 main.step( "Find current leader and withdraw" )
acsmars71adceb2015-08-31 15:09:26 -07002988 withdrawResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002989 # do some sanity checking on leader before using it
acsmars71adceb2015-08-31 15:09:26 -07002990 if oldLeader is None:
2991 main.log.error( "Leadership isn't consistent." )
2992 withdrawResult = main.FALSE
2993 # Get the CLI of the oldLeader
Jon Hallb3ed8ed2015-10-28 16:43:55 -07002994 for i in main.activeNodes:
acsmars71adceb2015-08-31 15:09:26 -07002995 if oldLeader == main.nodes[ i ].ip_address:
2996 oldLeaderCLI = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002997 break
2998 else: # FOR/ELSE statement
2999 main.log.error( "Leader election, could not find current leader" )
3000 if oldLeader:
acsmars71adceb2015-08-31 15:09:26 -07003001 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall5cf14d52015-07-16 12:15:19 -07003002 utilities.assert_equals(
3003 expect=main.TRUE,
3004 actual=withdrawResult,
3005 onpass="Node was withdrawn from election",
3006 onfail="Node was not withdrawn from election" )
3007
acsmars71adceb2015-08-31 15:09:26 -07003008 main.step( "Check that a new node was elected leader" )
acsmars71adceb2015-08-31 15:09:26 -07003009 failMessage = "Nodes have different leaders"
acsmars71adceb2015-08-31 15:09:26 -07003010 # Get new leaders and candidates
Jon Hall41d39f12016-04-11 22:54:35 -07003011 newLeaderResult, newLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall3a7843a2016-04-12 03:01:09 -07003012 newLeader = None
Jon Halla440e872016-03-31 15:15:50 -07003013 if newLeaderResult:
Jon Hall3a7843a2016-04-12 03:01:09 -07003014 if newLeaders[ 0 ][ 0 ] == 'none':
3015 main.log.error( "No leader was elected on at least 1 node" )
3016 if not expectNoLeader:
3017 newLeaderResult = False
Jon Hall25463a82016-04-13 14:03:52 -07003018 newLeader = newLeaders[ 0 ][ 0 ]
acsmars71adceb2015-08-31 15:09:26 -07003019
3020 # Check that the new leader is not the older leader, which was withdrawn
3021 if newLeader == oldLeader:
Jon Halla440e872016-03-31 15:15:50 -07003022 newLeaderResult = False
Jon Hall6e709752016-02-01 13:38:46 -08003023 main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
Jon Hallf37d44d2017-05-24 10:37:30 -07003024 " as the current leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003025 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003026 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003027 actual=newLeaderResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003028 onpass="Leadership election passed",
3029 onfail="Something went wrong with Leadership election" )
3030
Jon Halla440e872016-03-31 15:15:50 -07003031 main.step( "Check that that new leader was the candidate of old leader" )
Jon Hall6e709752016-02-01 13:38:46 -08003032 # candidates[ 2 ] should become the top candidate after withdrawl
acsmars71adceb2015-08-31 15:09:26 -07003033 correctCandidateResult = main.TRUE
3034 if expectNoLeader:
3035 if newLeader == 'none':
3036 main.log.info( "No leader expected. None found. Pass" )
3037 correctCandidateResult = main.TRUE
3038 else:
3039 main.log.info( "Expected no leader, got: " + str( newLeader ) )
3040 correctCandidateResult = main.FALSE
Jon Hallf37d44d2017-05-24 10:37:30 -07003041 elif len( oldLeaders[ 0 ] ) >= 3:
Jon Halla440e872016-03-31 15:15:50 -07003042 if newLeader == oldLeaders[ 0 ][ 2 ]:
3043 # correct leader was elected
3044 correctCandidateResult = main.TRUE
3045 else:
3046 correctCandidateResult = main.FALSE
3047 main.log.error( "Candidate {} was elected. {} should have had priority.".format(
3048 newLeader, oldLeaders[ 0 ][ 2 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08003049 else:
3050 main.log.warn( "Could not determine who should be the correct leader" )
Jon Halla440e872016-03-31 15:15:50 -07003051 main.log.debug( oldLeaders[ 0 ] )
Jon Hall6e709752016-02-01 13:38:46 -08003052 correctCandidateResult = main.FALSE
acsmars71adceb2015-08-31 15:09:26 -07003053 utilities.assert_equals(
3054 expect=main.TRUE,
3055 actual=correctCandidateResult,
3056 onpass="Correct Candidate Elected",
3057 onfail="Incorrect Candidate Elected" )
3058
Jon Hall5cf14d52015-07-16 12:15:19 -07003059 main.step( "Run for election on old leader( just so everyone " +
3060 "is in the hat )" )
acsmars71adceb2015-08-31 15:09:26 -07003061 if oldLeaderCLI is not None:
3062 runResult = oldLeaderCLI.electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07003063 else:
acsmars71adceb2015-08-31 15:09:26 -07003064 main.log.error( "No old leader to re-elect" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003065 runResult = main.FALSE
3066 utilities.assert_equals(
3067 expect=main.TRUE,
3068 actual=runResult,
3069 onpass="App re-ran for election",
3070 onfail="App failed to run for election" )
Jon Halla440e872016-03-31 15:15:50 -07003071
acsmars71adceb2015-08-31 15:09:26 -07003072 main.step(
3073 "Check that oldLeader is a candidate, and leader if only 1 node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07003074 # verify leader didn't just change
Jon Halla440e872016-03-31 15:15:50 -07003075 # Get new leaders and candidates
3076 reRunLeaders = []
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003077 time.sleep( 5 ) # Paremterize
Jon Hall41d39f12016-04-11 22:54:35 -07003078 positionResult, reRunLeaders = main.HA.consistentLeaderboards( activeCLIs )
acsmars71adceb2015-08-31 15:09:26 -07003079
3080 # Check that the re-elected node is last on the candidate List
Jon Hallf37d44d2017-05-24 10:37:30 -07003081 if not reRunLeaders[ 0 ]:
Jon Hall3a7843a2016-04-12 03:01:09 -07003082 positionResult = main.FALSE
3083 elif oldLeader != reRunLeaders[ 0 ][ -1 ]:
Jon Hallf37d44d2017-05-24 10:37:30 -07003084 main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader ),
Jon Halla440e872016-03-31 15:15:50 -07003085 str( reRunLeaders[ 0 ] ) ) )
acsmars71adceb2015-08-31 15:09:26 -07003086 positionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07003087 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07003088 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07003089 actual=positionResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07003090 onpass="Old leader successfully re-ran for election",
3091 onfail="Something went wrong with Leadership election after " +
3092 "the old leader re-ran for election" )
3093
3094 def CASE16( self, main ):
3095 """
3096 Install Distributed Primitives app
3097 """
3098 import time
Jon Halle1a3b752015-07-22 13:02:46 -07003099 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003100 assert main, "main not defined"
3101 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003102 assert main.CLIs, "main.CLIs not defined"
3103 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003104
3105 # Variables for the distributed primitives tests
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003106 main.pCounterName = "TestON-Partitions"
3107 main.pCounterValue = 0
Jon Hallf37d44d2017-05-24 10:37:30 -07003108 main.onosSet = set( [] )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003109 main.onosSetName = "TestON-set"
Jon Hall5cf14d52015-07-16 12:15:19 -07003110
3111 description = "Install Primitives app"
3112 main.case( description )
3113 main.step( "Install Primitives app" )
3114 appName = "org.onosproject.distributedprimitives"
Jon Hallf37d44d2017-05-24 10:37:30 -07003115 node = main.activeNodes[ 0 ]
3116 appResults = main.CLIs[ node ].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07003117 utilities.assert_equals( expect=main.TRUE,
3118 actual=appResults,
3119 onpass="Primitives app activated",
3120 onfail="Primitives app not activated" )
3121 time.sleep( 5 ) # To allow all nodes to activate
3122
3123 def CASE17( self, main ):
3124 """
3125 Check for basic functionality with distributed primitives
3126 """
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003127 main.HA.CASE17( main )