blob: 4f15a604079445012767720a6a76d511834f7c68 [file] [log] [blame]
Jon Hall85794ff2015-07-08 14:12:30 -07001"""
2Description: This test is to determine if a single
3 instance ONOS 'cluster' can handle a restart
4
5List of test cases:
6CASE1: Compile ONOS and push it to the test machines
7CASE2: Assign devices to controllers
8CASE21: Assign mastership to controllers
9CASE3: Assign intents
10CASE4: Ping across added host intents
11CASE5: Reading state of ONOS
12CASE6: The Failure case.
13CASE7: Check state after control plane failure
14CASE8: Compare topo
15CASE9: Link s3-s28 down
16CASE10: Link s3-s28 up
17CASE11: Switch down
18CASE12: Switch up
19CASE13: Clean up
20CASE14: start election app on all onos nodes
21CASE15: Check that Leadership Election is still functional
22CASE16: Install Distributed Primitives app
23CASE17: Check for basic functionality with distributed primitives
24"""
25
26
27class HAsingleInstanceRestart:
28
29 def __init__( self ):
30 self.default = ''
31
32 def CASE1( self, main ):
33 """
34 CASE1 is to compile ONOS and push it to the test machines
35
36 Startup sequence:
37 cell <name>
38 onos-verify-cell
39 NOTE: temporary - onos-remove-raft-logs
40 onos-uninstall
41 start mininet
42 git pull
43 mvn clean install
44 onos-package
45 onos-install -f
46 onos-wait-for-start
47 start cli sessions
48 start tcpdump
49 """
Jon Halle1a3b752015-07-22 13:02:46 -070050 import imp
Jon Hallf3d16e72015-12-16 17:45:08 -080051 import time
Jon Halla440e872016-03-31 15:15:50 -070052 import json
Jon Hall85794ff2015-07-08 14:12:30 -070053 main.log.info( "ONOS Single node cluster restart " +
54 "HA test - initialization" )
55 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070056 main.caseExplanation = "Setup the test environment including " +\
Jon Hall85794ff2015-07-08 14:12:30 -070057 "installing ONOS, starting Mininet and ONOS" +\
58 "cli sessions."
Jon Hall85794ff2015-07-08 14:12:30 -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 )
Jon Hall85794ff2015-07-08 14:12:30 -070071
Jon Halle1a3b752015-07-22 13:02:46 -070072 try:
Jon Hall53c5e662016-04-13 16:06:56 -070073 from tests.HA.dependencies.HA import HA
Jon Hall41d39f12016-04-11 22:54:35 -070074 main.HA = HA()
Jon Halle1a3b752015-07-22 13:02:46 -070075 except Exception as e:
76 main.log.exception( e )
77 main.cleanup()
78 main.exit()
79
80 main.CLIs = []
81 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -070082 ipList = []
83 for i in range( 1, int( main.ONOSbench.maxNodes ) + 1 ):
84 try:
Jon Halle1a3b752015-07-22 13:02:46 -070085 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
86 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
87 ipList.append( main.nodes[ -1 ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -070088 except AttributeError:
89 break
Jon Hall85794ff2015-07-08 14:12:30 -070090
Jon Hall5cf14d52015-07-16 12:15:19 -070091 main.step( "Create cell file" )
92 cellAppString = main.params[ 'ENV' ][ 'appString' ]
93 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
94 main.Mininet1.ip_address,
95 cellAppString, ipList )
Jon Hall85794ff2015-07-08 14:12:30 -070096 main.step( "Applying cell variable to environment" )
97 cellResult = main.ONOSbench.setCell( cellName )
98 verifyResult = main.ONOSbench.verifyCell()
99
100 # FIXME:this is short term fix
101 main.log.info( "Removing raft logs" )
102 main.ONOSbench.onosRemoveRaftLogs()
103
104 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700105 for node in main.nodes:
Jon Hall85794ff2015-07-08 14:12:30 -0700106 main.ONOSbench.onosUninstall( node.ip_address )
107
108 # Make sure ONOS is DEAD
109 main.log.info( "Killing any ONOS processes" )
110 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700111 for node in main.nodes:
Jon Hall85794ff2015-07-08 14:12:30 -0700112 killed = main.ONOSbench.onosKill( node.ip_address )
113 killResults = killResults and killed
114
115 cleanInstallResult = main.TRUE
116 gitPullResult = main.TRUE
117
118 main.step( "Starting Mininet" )
119 # scp topo file to mininet
120 # TODO: move to params?
121 topoName = "obelisk.py"
122 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700123 main.ONOSbench.scp( main.Mininet1,
124 filePath + topoName,
125 main.Mininet1.home,
126 direction="to" )
Jon Hall85794ff2015-07-08 14:12:30 -0700127 mnResult = main.Mininet1.startNet( )
128 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
129 onpass="Mininet Started",
130 onfail="Error starting Mininet" )
131
132 main.step( "Git checkout and pull " + gitBranch )
133 if PULLCODE:
134 main.ONOSbench.gitCheckout( gitBranch )
135 gitPullResult = main.ONOSbench.gitPull()
136 # values of 1 or 3 are good
137 utilities.assert_lesser( expect=0, actual=gitPullResult,
138 onpass="Git pull successful",
139 onfail="Git pull failed" )
140 main.ONOSbench.getVersion( report=True )
141
142 main.step( "Using mvn clean install" )
143 cleanInstallResult = main.TRUE
144 if PULLCODE and gitPullResult == main.TRUE:
145 cleanInstallResult = main.ONOSbench.cleanInstall()
146 else:
147 main.log.warn( "Did not pull new code so skipping mvn " +
148 "clean install" )
149 utilities.assert_equals( expect=main.TRUE,
150 actual=cleanInstallResult,
151 onpass="MCI successful",
152 onfail="MCI failed" )
153 # GRAPHS
154 # NOTE: important params here:
155 # job = name of Jenkins job
156 # Plot Name = Plot-HA, only can be used if multiple plots
157 # index = The number of the graph under plot name
Jon Hall5cf14d52015-07-16 12:15:19 -0700158 job = "HAsingleInstanceRestart"
Jon Hall85794ff2015-07-08 14:12:30 -0700159 plotName = "Plot-HA"
Jon Hall843f8bc2016-03-18 14:28:13 -0700160 index = "2"
Jon Hall85794ff2015-07-08 14:12:30 -0700161 graphs = '<ac:structured-macro ac:name="html">\n'
162 graphs += '<ac:plain-text-body><![CDATA[\n'
163 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Halla9845df2016-01-15 14:55:58 -0800164 '/plot/' + plotName + '/getPlot?index=' + index +\
Jon Hall85794ff2015-07-08 14:12:30 -0700165 '&width=500&height=300"' +\
166 'noborder="0" width="500" height="300" scrolling="yes" ' +\
167 'seamless="seamless"></iframe>\n'
168 graphs += ']]></ac:plain-text-body>\n'
169 graphs += '</ac:structured-macro>\n'
170 main.log.wiki(graphs)
171
Jon Halle1a3b752015-07-22 13:02:46 -0700172 main.CLIs = []
173 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700174 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700175 for i in range( 1, main.numCtrls + 1 ):
176 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
177 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
178 ipList.append( main.nodes[ -1 ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700179
180 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, "SingleHA",
181 main.Mininet1.ip_address,
182 cellAppString, ipList[ 0 ] )
Jon Hall85794ff2015-07-08 14:12:30 -0700183 cellResult = main.ONOSbench.setCell( "SingleHA" )
184 verifyResult = main.ONOSbench.verifyCell()
185 main.step( "Creating ONOS package" )
Jon Hallbd60ea02016-08-23 10:03:59 -0700186 packageResult = main.ONOSbench.buckBuild()
Jon Hall85794ff2015-07-08 14:12:30 -0700187 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
188 onpass="ONOS package successful",
189 onfail="ONOS package failed" )
190
191 main.step( "Installing ONOS package" )
Jon Halla440e872016-03-31 15:15:50 -0700192 onosInstallResult = main.TRUE
193 for node in main.nodes:
194 tmpResult = main.ONOSbench.onosInstall( options="-f",
195 node=node.ip_address )
196 onosInstallResult = onosInstallResult and tmpResult
Jon Hall85794ff2015-07-08 14:12:30 -0700197 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
198 onpass="ONOS install successful",
199 onfail="ONOS install failed" )
200
You Wangf5de25b2017-01-06 15:13:01 -0800201 main.step( "Set up ONOS secure SSH" )
202 secureSshResult = main.TRUE
203 for node in main.nodes:
204 secureSshResult = secureSshResult and main.ONOSbench.onosSecureSSH( node=node.ip_address )
205 utilities.assert_equals( expect=main.TRUE, actual=secureSshResult,
206 onpass="Test step PASS",
207 onfail="Test step FAIL" )
208
Jon Hall85794ff2015-07-08 14:12:30 -0700209 main.step( "Checking if ONOS is up yet" )
210 for i in range( 2 ):
Jon Halla440e872016-03-31 15:15:50 -0700211 onosIsupResult = main.TRUE
212 for node in main.nodes:
213 started = main.ONOSbench.isup( node.ip_address )
214 if not started:
215 main.log.error( node.name + " hasn't started" )
216 onosIsupResult = onosIsupResult and started
217 if onosIsupResult == main.TRUE:
Jon Hall85794ff2015-07-08 14:12:30 -0700218 break
Jon Halla440e872016-03-31 15:15:50 -0700219 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
Jon Hall85794ff2015-07-08 14:12:30 -0700220 onpass="ONOS startup successful",
221 onfail="ONOS startup failed" )
222
Jon Hall6509dbf2016-06-21 17:01:17 -0700223 main.step( "Starting ONOS CLI sessions" )
Jon Halla440e872016-03-31 15:15:50 -0700224 cliResults = main.TRUE
225 threads = []
226 for i in range( main.numCtrls ):
227 t = main.Thread( target=main.CLIs[i].startOnosCli,
228 name="startOnosCli-" + str( i ),
229 args=[main.nodes[i].ip_address] )
230 threads.append( t )
231 t.start()
232
233 for t in threads:
234 t.join()
235 cliResults = cliResults and t.result
Jon Hall85794ff2015-07-08 14:12:30 -0700236 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
237 onpass="ONOS cli startup successful",
238 onfail="ONOS cli startup failed" )
239
Jon Halla440e872016-03-31 15:15:50 -0700240 # Create a list of active nodes for use when some nodes are stopped
241 main.activeNodes = [ i for i in range( 0, len( main.CLIs ) ) ]
242
Jon Hall85794ff2015-07-08 14:12:30 -0700243 if main.params[ 'tcpdump' ].lower() == "true":
244 main.step( "Start Packet Capture MN" )
245 main.Mininet2.startTcpdump(
246 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
247 + "-MN.pcap",
248 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
249 port=main.params[ 'MNtcpdump' ][ 'port' ] )
250
Jon Halla440e872016-03-31 15:15:50 -0700251 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -0700252 nodeResults = utilities.retry( main.HA.nodesCheck,
253 False,
254 args=[main.activeNodes],
255 attempts=5 )
Jon Halla440e872016-03-31 15:15:50 -0700256
Jon Hall41d39f12016-04-11 22:54:35 -0700257 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Halla440e872016-03-31 15:15:50 -0700258 onpass="Nodes check successful",
259 onfail="Nodes check NOT successful" )
260
261 if not nodeResults:
Jon Hall7ac7bc32016-05-05 10:57:02 -0700262 for i in main.activeNodes:
263 cli = main.CLIs[i]
Jon Halla440e872016-03-31 15:15:50 -0700264 main.log.debug( "{} components not ACTIVE: \n{}".format(
265 cli.name,
266 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall85794ff2015-07-08 14:12:30 -0700267 main.log.error( "Failed to start ONOS, stopping test" )
268 main.cleanup()
269 main.exit()
270
Jon Hall172b7ba2016-04-07 18:12:20 -0700271 main.step( "Activate apps defined in the params file" )
272 # get data from the params
273 apps = main.params.get( 'apps' )
274 if apps:
275 apps = apps.split(',')
276 main.log.warn( apps )
277 activateResult = True
278 for app in apps:
279 main.CLIs[ 0 ].app( app, "Activate" )
280 # TODO: check this worked
281 time.sleep( 10 ) # wait for apps to activate
282 for app in apps:
283 state = main.CLIs[ 0 ].appStatus( app )
284 if state == "ACTIVE":
Jon Hall937bc812017-01-31 16:44:10 -0800285 activateResult = activateResult and True
Jon Hall172b7ba2016-04-07 18:12:20 -0700286 else:
287 main.log.error( "{} is in {} state".format( app, state ) )
Jon Hall937bc812017-01-31 16:44:10 -0800288 activateResult = False
Jon Hall172b7ba2016-04-07 18:12:20 -0700289 utilities.assert_equals( expect=True,
290 actual=activateResult,
291 onpass="Successfully activated apps",
292 onfail="Failed to activate apps" )
293 else:
294 main.log.warn( "No apps were specified to be loaded after startup" )
295
296 main.step( "Set ONOS configurations" )
297 config = main.params.get( 'ONOS_Configuration' )
298 if config:
299 main.log.debug( config )
300 checkResult = main.TRUE
301 for component in config:
302 for setting in config[component]:
303 value = config[component][setting]
304 check = main.CLIs[ 0 ].setCfg( component, setting, value )
305 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
306 checkResult = check and checkResult
307 utilities.assert_equals( expect=main.TRUE,
308 actual=checkResult,
309 onpass="Successfully set config",
310 onfail="Failed to set config" )
311 else:
312 main.log.warn( "No configurations were specified to be changed after startup" )
313
Jon Hall9d2dcad2016-04-08 10:15:20 -0700314 main.step( "App Ids check" )
315 appCheck = main.TRUE
316 threads = []
317 for i in main.activeNodes:
318 t = main.Thread( target=main.CLIs[i].appToIDCheck,
319 name="appToIDCheck-" + str( i ),
320 args=[] )
321 threads.append( t )
322 t.start()
323
324 for t in threads:
325 t.join()
326 appCheck = appCheck and t.result
327 if appCheck != main.TRUE:
328 node = main.activeNodes[0]
329 main.log.warn( main.CLIs[node].apps() )
330 main.log.warn( main.CLIs[node].appIDs() )
331 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
332 onpass="App Ids seem to be correct",
333 onfail="Something is wrong with app Ids" )
334
Jon Hall85794ff2015-07-08 14:12:30 -0700335 def CASE2( self, main ):
336 """
337 Assign devices to controllers
338 """
339 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700340 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -0700341 assert main, "main not defined"
342 assert utilities.assert_equals, "utilities.assert_equals not defined"
343
344 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700345 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall85794ff2015-07-08 14:12:30 -0700346 "and check that an ONOS node becomes the " +\
347 "master of the device."
348 main.step( "Assign switches to controllers" )
349
350 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700351 for i in range( main.numCtrls ):
352 ipList.append( main.nodes[ i ].ip_address )
Jon Hall85794ff2015-07-08 14:12:30 -0700353 swList = []
354 for i in range( 1, 29 ):
355 swList.append( "s" + str( i ) )
356 main.Mininet1.assignSwController( sw=swList, ip=ipList )
357
358 mastershipCheck = main.TRUE
359 for i in range( 1, 29 ):
360 response = main.Mininet1.getSwController( "s" + str( i ) )
361 try:
362 main.log.info( str( response ) )
363 except Exception:
364 main.log.info( repr( response ) )
Jon Halla440e872016-03-31 15:15:50 -0700365 for node in main.nodes:
366 if re.search( "tcp:" + node.ip_address, response ):
367 mastershipCheck = mastershipCheck and main.TRUE
368 else:
369 main.log.error( "Error, node " + node.ip_address + " is " +
370 "not in the list of controllers s" +
371 str( i ) + " is connecting to." )
372 mastershipCheck = main.FALSE
Jon Hall85794ff2015-07-08 14:12:30 -0700373 utilities.assert_equals(
374 expect=main.TRUE,
375 actual=mastershipCheck,
376 onpass="Switch mastership assigned correctly",
377 onfail="Switches not assigned correctly to controllers" )
378
379 def CASE21( self, main ):
380 """
381 Assign mastership to controllers
382 """
Jon Halle1a3b752015-07-22 13:02:46 -0700383 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -0700384 assert main, "main not defined"
385 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700386 assert main.CLIs, "main.CLIs not defined"
387 assert main.nodes, "main.nodes not defined"
Jon Hall85794ff2015-07-08 14:12:30 -0700388
389 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700390 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall85794ff2015-07-08 14:12:30 -0700391 "device. Then manually assign" +\
392 " mastership to specific ONOS nodes using" +\
393 " 'device-role'"
394 main.step( "Assign mastership of switches to specific controllers" )
Jon Halla440e872016-03-31 15:15:50 -0700395 # Manually assign mastership to the controller we want
Jon Hall85794ff2015-07-08 14:12:30 -0700396 roleCall = main.TRUE
Jon Halla440e872016-03-31 15:15:50 -0700397
398 ipList = [ ]
399 deviceList = []
400 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall85794ff2015-07-08 14:12:30 -0700401 try:
Jon Halla440e872016-03-31 15:15:50 -0700402 # Assign mastership to specific controllers. This assignment was
403 # determined for a 7 node cluser, but will work with any sized
404 # cluster
Jon Hall85794ff2015-07-08 14:12:30 -0700405 for i in range( 1, 29 ): # switches 1 through 28
Jon Hall85794ff2015-07-08 14:12:30 -0700406 # set up correct variables:
407 if i == 1:
Jon Halla440e872016-03-31 15:15:50 -0700408 c = 0
409 ip = main.nodes[ c ].ip_address # ONOS1
410 deviceId = onosCli.getDevice( "1000" ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700411 elif i == 2:
Jon Halla440e872016-03-31 15:15:50 -0700412 c = 1 % main.numCtrls
413 ip = main.nodes[ c ].ip_address # ONOS2
414 deviceId = onosCli.getDevice( "2000" ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700415 elif i == 3:
Jon Halla440e872016-03-31 15:15:50 -0700416 c = 1 % main.numCtrls
417 ip = main.nodes[ c ].ip_address # ONOS2
418 deviceId = onosCli.getDevice( "3000" ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700419 elif i == 4:
Jon Halla440e872016-03-31 15:15:50 -0700420 c = 3 % main.numCtrls
421 ip = main.nodes[ c ].ip_address # ONOS4
422 deviceId = onosCli.getDevice( "3004" ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700423 elif i == 5:
Jon Halla440e872016-03-31 15:15:50 -0700424 c = 2 % main.numCtrls
425 ip = main.nodes[ c ].ip_address # ONOS3
426 deviceId = onosCli.getDevice( "5000" ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700427 elif i == 6:
Jon Halla440e872016-03-31 15:15:50 -0700428 c = 2 % main.numCtrls
429 ip = main.nodes[ c ].ip_address # ONOS3
430 deviceId = onosCli.getDevice( "6000" ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700431 elif i == 7:
Jon Halla440e872016-03-31 15:15:50 -0700432 c = 5 % main.numCtrls
433 ip = main.nodes[ c ].ip_address # ONOS6
434 deviceId = onosCli.getDevice( "6007" ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700435 elif i >= 8 and i <= 17:
Jon Halla440e872016-03-31 15:15:50 -0700436 c = 4 % main.numCtrls
437 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall85794ff2015-07-08 14:12:30 -0700438 dpid = '3' + str( i ).zfill( 3 )
Jon Halla440e872016-03-31 15:15:50 -0700439 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700440 elif i >= 18 and i <= 27:
Jon Halla440e872016-03-31 15:15:50 -0700441 c = 6 % main.numCtrls
442 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall85794ff2015-07-08 14:12:30 -0700443 dpid = '6' + str( i ).zfill( 3 )
Jon Halla440e872016-03-31 15:15:50 -0700444 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700445 elif i == 28:
Jon Halla440e872016-03-31 15:15:50 -0700446 c = 0
447 ip = main.nodes[ c ].ip_address # ONOS1
448 deviceId = onosCli.getDevice( "2800" ).get( 'id' )
Jon Hall85794ff2015-07-08 14:12:30 -0700449 else:
450 main.log.error( "You didn't write an else statement for " +
451 "switch s" + str( i ) )
Jon Halla440e872016-03-31 15:15:50 -0700452 roleCall = main.FALSE
Jon Hall85794ff2015-07-08 14:12:30 -0700453 # Assign switch
454 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
455 # TODO: make this controller dynamic
Jon Halla440e872016-03-31 15:15:50 -0700456 roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
457 ipList.append( ip )
458 deviceList.append( deviceId )
Jon Hall85794ff2015-07-08 14:12:30 -0700459 except ( AttributeError, AssertionError ):
460 main.log.exception( "Something is wrong with ONOS device view" )
Jon Halla440e872016-03-31 15:15:50 -0700461 main.log.info( onosCli.devices() )
Jon Hall85794ff2015-07-08 14:12:30 -0700462 utilities.assert_equals(
463 expect=main.TRUE,
464 actual=roleCall,
465 onpass="Re-assigned switch mastership to designated controller",
466 onfail="Something wrong with deviceRole calls" )
467
468 main.step( "Check mastership was correctly assigned" )
Jon Halla440e872016-03-31 15:15:50 -0700469 roleCheck = main.TRUE
470 # NOTE: This is due to the fact that device mastership change is not
471 # atomic and is actually a multi step process
472 time.sleep( 5 )
473 for i in range( len( ipList ) ):
474 ip = ipList[i]
475 deviceId = deviceList[i]
476 # Check assignment
477 master = onosCli.getRole( deviceId ).get( 'master' )
478 if ip in master:
479 roleCheck = roleCheck and main.TRUE
480 else:
481 roleCheck = roleCheck and main.FALSE
482 main.log.error( "Error, controller " + ip + " is not" +
483 " master " + "of device " +
484 str( deviceId ) + ". Master is " +
485 repr( master ) + "." )
Jon Hall85794ff2015-07-08 14:12:30 -0700486 utilities.assert_equals(
487 expect=main.TRUE,
488 actual=roleCheck,
489 onpass="Switches were successfully reassigned to designated " +
490 "controller",
491 onfail="Switches were not successfully reassigned" )
492
493 def CASE3( self, main ):
494 """
495 Assign intents
496 """
497 import time
498 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700499 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -0700500 assert main, "main not defined"
501 assert utilities.assert_equals, "utilities.assert_equals not defined"
502 # NOTE: we must reinstall intents until we have a persistant intent
503 # datastore!
504 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700505 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall85794ff2015-07-08 14:12:30 -0700506 "assign predetermined host-to-host intents." +\
507 " After installation, check that the intent" +\
508 " is distributed to all nodes and the state" +\
509 " is INSTALLED"
510
511 # install onos-app-fwd
512 main.step( "Install reactive forwarding app" )
Jon Halla440e872016-03-31 15:15:50 -0700513 onosCli = main.CLIs[ main.activeNodes[0] ]
514 installResults = onosCli.activateApp( "org.onosproject.fwd" )
Jon Hall85794ff2015-07-08 14:12:30 -0700515 utilities.assert_equals( expect=main.TRUE, actual=installResults,
516 onpass="Install fwd successful",
517 onfail="Install fwd failed" )
518
519 main.step( "Check app ids" )
Jon Halla440e872016-03-31 15:15:50 -0700520 appCheck = main.TRUE
521 threads = []
522 for i in main.activeNodes:
523 t = main.Thread( target=main.CLIs[i].appToIDCheck,
524 name="appToIDCheck-" + str( i ),
525 args=[] )
526 threads.append( t )
527 t.start()
528
529 for t in threads:
530 t.join()
531 appCheck = appCheck and t.result
Jon Hall85794ff2015-07-08 14:12:30 -0700532 if appCheck != main.TRUE:
Jon Halla440e872016-03-31 15:15:50 -0700533 main.log.warn( onosCli.apps() )
534 main.log.warn( onosCli.appIDs() )
Jon Hall85794ff2015-07-08 14:12:30 -0700535 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
536 onpass="App Ids seem to be correct",
537 onfail="Something is wrong with app Ids" )
538
539 main.step( "Discovering Hosts( Via pingall for now )" )
540 # FIXME: Once we have a host discovery mechanism, use that instead
541 # REACTIVE FWD test
542 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700543 passMsg = "Reactive Pingall test passed"
544 time1 = time.time()
545 pingResult = main.Mininet1.pingall()
546 time2 = time.time()
547 if not pingResult:
548 main.log.warn("First pingall failed. Trying again...")
Jon Hall85794ff2015-07-08 14:12:30 -0700549 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700550 passMsg += " on the second try"
551 utilities.assert_equals(
552 expect=main.TRUE,
553 actual=pingResult,
554 onpass= passMsg,
555 onfail="Reactive Pingall failed, " +
556 "one or more ping pairs failed" )
557 main.log.info( "Time for pingall: %2f seconds" %
558 ( time2 - time1 ) )
Jon Hall85794ff2015-07-08 14:12:30 -0700559 # timeout for fwd flows
560 time.sleep( 11 )
561 # uninstall onos-app-fwd
562 main.step( "Uninstall reactive forwarding app" )
Jon Halla440e872016-03-31 15:15:50 -0700563 node = main.activeNodes[0]
564 uninstallResult = main.CLIs[node].deactivateApp( "org.onosproject.fwd" )
Jon Hall85794ff2015-07-08 14:12:30 -0700565 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
566 onpass="Uninstall fwd successful",
567 onfail="Uninstall fwd failed" )
568
569 main.step( "Check app ids" )
Jon Halla440e872016-03-31 15:15:50 -0700570 threads = []
571 appCheck2 = main.TRUE
572 for i in main.activeNodes:
573 t = main.Thread( target=main.CLIs[i].appToIDCheck,
574 name="appToIDCheck-" + str( i ),
575 args=[] )
576 threads.append( t )
577 t.start()
578
579 for t in threads:
580 t.join()
581 appCheck2 = appCheck2 and t.result
Jon Hall85794ff2015-07-08 14:12:30 -0700582 if appCheck2 != main.TRUE:
Jon Halla440e872016-03-31 15:15:50 -0700583 node = main.activeNodes[0]
584 main.log.warn( main.CLIs[node].apps() )
585 main.log.warn( main.CLIs[node].appIDs() )
Jon Hall85794ff2015-07-08 14:12:30 -0700586 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
587 onpass="App Ids seem to be correct",
588 onfail="Something is wrong with app Ids" )
589
590 main.step( "Add host intents via cli" )
591 intentIds = []
Jon Halla440e872016-03-31 15:15:50 -0700592 # TODO: move the host numbers to params
593 # Maybe look at all the paths we ping?
Jon Hall85794ff2015-07-08 14:12:30 -0700594 intentAddResult = True
595 hostResult = main.TRUE
596 for i in range( 8, 18 ):
597 main.log.info( "Adding host intent between h" + str( i ) +
598 " and h" + str( i + 10 ) )
599 host1 = "00:00:00:00:00:" + \
600 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
601 host2 = "00:00:00:00:00:" + \
602 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
603 # NOTE: getHost can return None
Jon Halla440e872016-03-31 15:15:50 -0700604 host1Dict = onosCli.getHost( host1 )
605 host2Dict = onosCli.getHost( host2 )
Jon Hall85794ff2015-07-08 14:12:30 -0700606 host1Id = None
607 host2Id = None
608 if host1Dict and host2Dict:
609 host1Id = host1Dict.get( 'id', None )
610 host2Id = host2Dict.get( 'id', None )
611 if host1Id and host2Id:
Jon Halla440e872016-03-31 15:15:50 -0700612 nodeNum = ( i % len( main.activeNodes ) )
613 node = main.activeNodes[nodeNum]
614 tmpId = main.CLIs[node].addHostIntent( host1Id, host2Id )
Jon Hall85794ff2015-07-08 14:12:30 -0700615 if tmpId:
616 main.log.info( "Added intent with id: " + tmpId )
617 intentIds.append( tmpId )
618 else:
619 main.log.error( "addHostIntent returned: " +
620 repr( tmpId ) )
621 else:
622 main.log.error( "Error, getHost() failed for h" + str( i ) +
623 " and/or h" + str( i + 10 ) )
Jon Halla440e872016-03-31 15:15:50 -0700624 node = main.activeNodes[0]
625 hosts = main.CLIs[node].hosts()
Jon Hall85794ff2015-07-08 14:12:30 -0700626 main.log.warn( "Hosts output: " )
627 try:
628 main.log.warn( json.dumps( json.loads( hosts ),
629 sort_keys=True,
630 indent=4,
631 separators=( ',', ': ' ) ) )
632 except ( ValueError, TypeError ):
633 main.log.warn( repr( hosts ) )
634 hostResult = main.FALSE
635 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
636 onpass="Found a host id for each host",
637 onfail="Error looking up host ids" )
638
639 intentStart = time.time()
Jon Halla440e872016-03-31 15:15:50 -0700640 onosIds = onosCli.getAllIntentsId()
Jon Hall85794ff2015-07-08 14:12:30 -0700641 main.log.info( "Submitted intents: " + str( intentIds ) )
642 main.log.info( "Intents in ONOS: " + str( onosIds ) )
643 for intent in intentIds:
644 if intent in onosIds:
645 pass # intent submitted is in onos
646 else:
647 intentAddResult = False
648 if intentAddResult:
649 intentStop = time.time()
650 else:
651 intentStop = None
652 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -0700653 intents = onosCli.intents()
Jon Hall85794ff2015-07-08 14:12:30 -0700654 intentStates = []
655 installedCheck = True
656 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
657 count = 0
658 try:
659 for intent in json.loads( intents ):
660 state = intent.get( 'state', None )
661 if "INSTALLED" not in state:
662 installedCheck = False
663 intentId = intent.get( 'id', None )
664 intentStates.append( ( intentId, state ) )
665 except ( ValueError, TypeError ):
666 main.log.exception( "Error parsing intents" )
667 # add submitted intents not in the store
668 tmplist = [ i for i, s in intentStates ]
669 missingIntents = False
670 for i in intentIds:
671 if i not in tmplist:
672 intentStates.append( ( i, " - " ) )
673 missingIntents = True
674 intentStates.sort()
675 for i, s in intentStates:
676 count += 1
677 main.log.info( "%-6s%-15s%-15s" %
678 ( str( count ), str( i ), str( s ) ) )
Jon Halla440e872016-03-31 15:15:50 -0700679 leaders = onosCli.leaders()
Jon Hall85794ff2015-07-08 14:12:30 -0700680 try:
681 missing = False
682 if leaders:
683 parsedLeaders = json.loads( leaders )
684 main.log.warn( json.dumps( parsedLeaders,
685 sort_keys=True,
686 indent=4,
687 separators=( ',', ': ' ) ) )
688 # check for all intent partitions
689 topics = []
690 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700691 topics.append( "work-partition-" + str( i ) )
Jon Hall85794ff2015-07-08 14:12:30 -0700692 main.log.debug( topics )
693 ONOStopics = [ j['topic'] for j in parsedLeaders ]
694 for topic in topics:
695 if topic not in ONOStopics:
696 main.log.error( "Error: " + topic +
697 " not in leaders" )
698 missing = True
699 else:
700 main.log.error( "leaders() returned None" )
701 except ( ValueError, TypeError ):
702 main.log.exception( "Error parsing leaders" )
703 main.log.error( repr( leaders ) )
704 # Check all nodes
705 if missing:
Jon Halla440e872016-03-31 15:15:50 -0700706 for i in main.activeNodes:
707 response = main.CLIs[i].leaders( jsonFormat=False)
708 main.log.warn( str( main.CLIs[i].name ) + " leaders output: \n" +
709 str( response ) )
Jon Hall85794ff2015-07-08 14:12:30 -0700710
Jon Halla440e872016-03-31 15:15:50 -0700711 partitions = onosCli.partitions()
Jon Hall85794ff2015-07-08 14:12:30 -0700712 try:
713 if partitions :
714 parsedPartitions = json.loads( partitions )
715 main.log.warn( json.dumps( parsedPartitions,
716 sort_keys=True,
717 indent=4,
718 separators=( ',', ': ' ) ) )
719 # TODO check for a leader in all paritions
720 # TODO check for consistency among nodes
721 else:
722 main.log.error( "partitions() returned None" )
723 except ( ValueError, TypeError ):
724 main.log.exception( "Error parsing partitions" )
725 main.log.error( repr( partitions ) )
Jon Halla440e872016-03-31 15:15:50 -0700726 pendingMap = onosCli.pendingMap()
Jon Hall85794ff2015-07-08 14:12:30 -0700727 try:
728 if pendingMap :
729 parsedPending = json.loads( pendingMap )
730 main.log.warn( json.dumps( parsedPending,
731 sort_keys=True,
732 indent=4,
733 separators=( ',', ': ' ) ) )
734 # TODO check something here?
735 else:
736 main.log.error( "pendingMap() returned None" )
737 except ( ValueError, TypeError ):
738 main.log.exception( "Error parsing pending map" )
739 main.log.error( repr( pendingMap ) )
740
741 intentAddResult = bool( intentAddResult and not missingIntents and
742 installedCheck )
743 if not intentAddResult:
744 main.log.error( "Error in pushing host intents to ONOS" )
745
746 main.step( "Intent Anti-Entropy dispersion" )
Jon Halla440e872016-03-31 15:15:50 -0700747 for j in range(100):
Jon Hall85794ff2015-07-08 14:12:30 -0700748 correct = True
749 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Halla440e872016-03-31 15:15:50 -0700750 for i in main.activeNodes:
Jon Hall85794ff2015-07-08 14:12:30 -0700751 onosIds = []
Jon Halla440e872016-03-31 15:15:50 -0700752 ids = main.CLIs[i].getAllIntentsId()
Jon Hall85794ff2015-07-08 14:12:30 -0700753 onosIds.append( ids )
Jon Halla440e872016-03-31 15:15:50 -0700754 main.log.debug( "Intents in " + main.CLIs[i].name + ": " +
Jon Hall85794ff2015-07-08 14:12:30 -0700755 str( sorted( onosIds ) ) )
756 if sorted( ids ) != sorted( intentIds ):
757 main.log.warn( "Set of intent IDs doesn't match" )
758 correct = False
759 break
760 else:
Jon Halla440e872016-03-31 15:15:50 -0700761 intents = json.loads( main.CLIs[i].intents() )
Jon Hall85794ff2015-07-08 14:12:30 -0700762 for intent in intents:
763 if intent[ 'state' ] != "INSTALLED":
764 main.log.warn( "Intent " + intent[ 'id' ] +
765 " is " + intent[ 'state' ] )
766 correct = False
767 break
768 if correct:
769 break
770 else:
771 time.sleep(1)
772 if not intentStop:
773 intentStop = time.time()
774 global gossipTime
775 gossipTime = intentStop - intentStart
776 main.log.info( "It took about " + str( gossipTime ) +
777 " seconds for all intents to appear in each node" )
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700778 gossipPeriod = int( main.params['timers']['gossip'] )
Jon Halla440e872016-03-31 15:15:50 -0700779 maxGossipTime = gossipPeriod * len( main.activeNodes )
Jon Hall85794ff2015-07-08 14:12:30 -0700780 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700781 expect=maxGossipTime, actual=gossipTime,
Jon Hall85794ff2015-07-08 14:12:30 -0700782 onpass="ECM anti-entropy for intents worked within " +
783 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700784 onfail="Intent ECM anti-entropy took too long. " +
785 "Expected time:{}, Actual time:{}".format( maxGossipTime,
786 gossipTime ) )
787 if gossipTime <= maxGossipTime:
Jon Hall85794ff2015-07-08 14:12:30 -0700788 intentAddResult = True
789
790 if not intentAddResult or "key" in pendingMap:
791 import time
792 installedCheck = True
793 main.log.info( "Sleeping 60 seconds to see if intents are found" )
794 time.sleep( 60 )
Jon Halla440e872016-03-31 15:15:50 -0700795 onosIds = onosCli.getAllIntentsId()
Jon Hall85794ff2015-07-08 14:12:30 -0700796 main.log.info( "Submitted intents: " + str( intentIds ) )
797 main.log.info( "Intents in ONOS: " + str( onosIds ) )
798 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -0700799 intents = onosCli.intents()
Jon Hall85794ff2015-07-08 14:12:30 -0700800 intentStates = []
801 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
802 count = 0
803 try:
804 for intent in json.loads( intents ):
805 # Iter through intents of a node
806 state = intent.get( 'state', None )
807 if "INSTALLED" not in state:
808 installedCheck = False
809 intentId = intent.get( 'id', None )
810 intentStates.append( ( intentId, state ) )
811 except ( ValueError, TypeError ):
812 main.log.exception( "Error parsing intents" )
813 # add submitted intents not in the store
814 tmplist = [ i for i, s in intentStates ]
815 for i in intentIds:
816 if i not in tmplist:
817 intentStates.append( ( i, " - " ) )
818 intentStates.sort()
819 for i, s in intentStates:
820 count += 1
821 main.log.info( "%-6s%-15s%-15s" %
822 ( str( count ), str( i ), str( s ) ) )
Jon Halla440e872016-03-31 15:15:50 -0700823 leaders = onosCli.leaders()
Jon Hall85794ff2015-07-08 14:12:30 -0700824 try:
825 missing = False
826 if leaders:
827 parsedLeaders = json.loads( leaders )
828 main.log.warn( json.dumps( parsedLeaders,
829 sort_keys=True,
830 indent=4,
831 separators=( ',', ': ' ) ) )
832 # check for all intent partitions
833 # check for election
834 topics = []
835 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700836 topics.append( "work-partition-" + str( i ) )
Jon Hall85794ff2015-07-08 14:12:30 -0700837 # FIXME: this should only be after we start the app
838 topics.append( "org.onosproject.election" )
839 main.log.debug( topics )
840 ONOStopics = [ j['topic'] for j in parsedLeaders ]
841 for topic in topics:
842 if topic not in ONOStopics:
843 main.log.error( "Error: " + topic +
844 " not in leaders" )
845 missing = True
846 else:
847 main.log.error( "leaders() returned None" )
848 except ( ValueError, TypeError ):
849 main.log.exception( "Error parsing leaders" )
850 main.log.error( repr( leaders ) )
851 # Check all nodes
852 if missing:
Jon Halla440e872016-03-31 15:15:50 -0700853 for i in main.activeNodes:
854 node = main.CLIs[i]
855 response = node.leaders( jsonFormat=False)
856 main.log.warn( str( node.name ) + " leaders output: \n" +
857 str( response ) )
858
859 partitions = onosCli.partitions()
Jon Hall85794ff2015-07-08 14:12:30 -0700860 try:
861 if partitions :
862 parsedPartitions = json.loads( partitions )
863 main.log.warn( json.dumps( parsedPartitions,
864 sort_keys=True,
865 indent=4,
866 separators=( ',', ': ' ) ) )
867 # TODO check for a leader in all paritions
868 # TODO check for consistency among nodes
869 else:
870 main.log.error( "partitions() returned None" )
871 except ( ValueError, TypeError ):
872 main.log.exception( "Error parsing partitions" )
873 main.log.error( repr( partitions ) )
Jon Halla440e872016-03-31 15:15:50 -0700874 pendingMap = onosCli.pendingMap()
Jon Hall85794ff2015-07-08 14:12:30 -0700875 try:
876 if pendingMap :
877 parsedPending = json.loads( pendingMap )
878 main.log.warn( json.dumps( parsedPending,
879 sort_keys=True,
880 indent=4,
881 separators=( ',', ': ' ) ) )
882 # TODO check something here?
883 else:
884 main.log.error( "pendingMap() returned None" )
885 except ( ValueError, TypeError ):
886 main.log.exception( "Error parsing pending map" )
887 main.log.error( repr( pendingMap ) )
888
889 def CASE4( self, main ):
890 """
891 Ping across added host intents
892 """
893 import json
894 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700895 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -0700896 assert main, "main not defined"
897 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halla440e872016-03-31 15:15:50 -0700898 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700899 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall85794ff2015-07-08 14:12:30 -0700900 "functionality and check the state of " +\
901 "the intent"
Jon Hall9d2dcad2016-04-08 10:15:20 -0700902
Jon Hall41d39f12016-04-11 22:54:35 -0700903 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall9d2dcad2016-04-08 10:15:20 -0700904 main.step( "Check Intent state" )
905 installedCheck = True
906 # Print the intent states
907 intents = main.ONOScli1.intents()
908 intentStates = []
909 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
910 count = 0
911 # Iter through intents of a node
912 try:
913 for intent in json.loads( intents ):
914 state = intent.get( 'state', None )
915 if "INSTALLED" not in state:
916 installedCheck = False
917 intentId = intent.get( 'id', None )
918 intentStates.append( ( intentId, state ) )
919 except ( ValueError, TypeError ):
920 main.log.exception( "Error parsing intents." )
921 # Print states
922 intentStates.sort()
923 for i, s in intentStates:
924 count += 1
925 main.log.info( "%-6s%-15s%-15s" %
926 ( str( count ), str( i ), str( s ) ) )
927 utilities.assert_equals( expect=True, actual=installedCheck,
928 onpass="Intents are all INSTALLED",
929 onfail="Intents are not all in " +
930 "INSTALLED state" )
931
Jon Hall85794ff2015-07-08 14:12:30 -0700932 main.step( "Ping across added host intents" )
933 PingResult = main.TRUE
934 for i in range( 8, 18 ):
935 ping = main.Mininet1.pingHost( src="h" + str( i ),
936 target="h" + str( i + 10 ) )
937 PingResult = PingResult and ping
938 if ping == main.FALSE:
939 main.log.warn( "Ping failed between h" + str( i ) +
940 " and h" + str( i + 10 ) )
941 elif ping == main.TRUE:
942 main.log.info( "Ping test passed!" )
943 # Don't set PingResult or you'd override failures
944 if PingResult == main.FALSE:
945 main.log.error(
946 "Intents have not been installed correctly, pings failed." )
947 # TODO: pretty print
948 main.log.warn( "ONOS1 intents: " )
949 try:
Jon Halla440e872016-03-31 15:15:50 -0700950 tmpIntents = onosCli.intents()
Jon Hall85794ff2015-07-08 14:12:30 -0700951 main.log.warn( json.dumps( json.loads( tmpIntents ),
952 sort_keys=True,
953 indent=4,
954 separators=( ',', ': ' ) ) )
955 except ( ValueError, TypeError ):
956 main.log.warn( repr( tmpIntents ) )
957 utilities.assert_equals(
958 expect=main.TRUE,
959 actual=PingResult,
960 onpass="Intents have been installed correctly and pings work",
961 onfail="Intents have not been installed correctly, pings failed." )
962
Jon Hall85794ff2015-07-08 14:12:30 -0700963 main.step( "Check leadership of topics" )
Jon Halla440e872016-03-31 15:15:50 -0700964 leaders = onosCli.leaders()
Jon Hall85794ff2015-07-08 14:12:30 -0700965 topicCheck = main.TRUE
966 try:
967 if leaders:
968 parsedLeaders = json.loads( leaders )
969 main.log.warn( json.dumps( parsedLeaders,
970 sort_keys=True,
971 indent=4,
972 separators=( ',', ': ' ) ) )
973 # check for all intent partitions
974 # check for election
975 # TODO: Look at Devices as topics now that it uses this system
976 topics = []
977 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700978 topics.append( "work-partition-" + str( i ) )
Jon Hall85794ff2015-07-08 14:12:30 -0700979 # FIXME: this should only be after we start the app
980 # FIXME: topics.append( "org.onosproject.election" )
981 # Print leaders output
982 main.log.debug( topics )
983 ONOStopics = [ j['topic'] for j in parsedLeaders ]
984 for topic in topics:
985 if topic not in ONOStopics:
986 main.log.error( "Error: " + topic +
987 " not in leaders" )
988 topicCheck = main.FALSE
989 else:
990 main.log.error( "leaders() returned None" )
991 topicCheck = main.FALSE
992 except ( ValueError, TypeError ):
993 topicCheck = main.FALSE
994 main.log.exception( "Error parsing leaders" )
995 main.log.error( repr( leaders ) )
996 # TODO: Check for a leader of these topics
Jon Halla440e872016-03-31 15:15:50 -0700997 # Check all nodes
998 if topicCheck:
999 for i in main.activeNodes:
1000 node = main.CLIs[i]
1001 response = node.leaders( jsonFormat=False)
1002 main.log.warn( str( node.name ) + " leaders output: \n" +
1003 str( response ) )
1004
Jon Hall85794ff2015-07-08 14:12:30 -07001005 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
1006 onpass="intent Partitions is in leaders",
1007 onfail="Some topics were lost " )
1008 # Print partitions
Jon Halla440e872016-03-31 15:15:50 -07001009 partitions = onosCli.partitions()
Jon Hall85794ff2015-07-08 14:12:30 -07001010 try:
1011 if partitions :
1012 parsedPartitions = json.loads( partitions )
1013 main.log.warn( json.dumps( parsedPartitions,
1014 sort_keys=True,
1015 indent=4,
1016 separators=( ',', ': ' ) ) )
1017 # TODO check for a leader in all paritions
1018 # TODO check for consistency among nodes
1019 else:
1020 main.log.error( "partitions() returned None" )
1021 except ( ValueError, TypeError ):
1022 main.log.exception( "Error parsing partitions" )
1023 main.log.error( repr( partitions ) )
1024 # Print Pending Map
Jon Halla440e872016-03-31 15:15:50 -07001025 pendingMap = onosCli.pendingMap()
Jon Hall85794ff2015-07-08 14:12:30 -07001026 try:
1027 if pendingMap :
1028 parsedPending = json.loads( pendingMap )
1029 main.log.warn( json.dumps( parsedPending,
1030 sort_keys=True,
1031 indent=4,
1032 separators=( ',', ': ' ) ) )
1033 # TODO check something here?
1034 else:
1035 main.log.error( "pendingMap() returned None" )
1036 except ( ValueError, TypeError ):
1037 main.log.exception( "Error parsing pending map" )
1038 main.log.error( repr( pendingMap ) )
1039
1040 if not installedCheck:
1041 main.log.info( "Waiting 60 seconds to see if the state of " +
1042 "intents change" )
1043 time.sleep( 60 )
1044 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -07001045 intents = onosCli.intents()
Jon Hall85794ff2015-07-08 14:12:30 -07001046 intentStates = []
1047 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1048 count = 0
1049 # Iter through intents of a node
1050 try:
1051 for intent in json.loads( intents ):
1052 state = intent.get( 'state', None )
1053 if "INSTALLED" not in state:
1054 installedCheck = False
1055 intentId = intent.get( 'id', None )
1056 intentStates.append( ( intentId, state ) )
1057 except ( ValueError, TypeError ):
1058 main.log.exception( "Error parsing intents." )
1059 intentStates.sort()
1060 for i, s in intentStates:
1061 count += 1
1062 main.log.info( "%-6s%-15s%-15s" %
1063 ( str( count ), str( i ), str( s ) ) )
Jon Halla440e872016-03-31 15:15:50 -07001064 leaders = onosCli.leaders()
Jon Hall85794ff2015-07-08 14:12:30 -07001065 try:
1066 missing = False
1067 if leaders:
1068 parsedLeaders = json.loads( leaders )
1069 main.log.warn( json.dumps( parsedLeaders,
1070 sort_keys=True,
1071 indent=4,
1072 separators=( ',', ': ' ) ) )
1073 # check for all intent partitions
1074 # check for election
1075 topics = []
1076 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -07001077 topics.append( "work-partition-" + str( i ) )
Jon Hall85794ff2015-07-08 14:12:30 -07001078 # FIXME: this should only be after we start the app
1079 topics.append( "org.onosproject.election" )
1080 main.log.debug( topics )
1081 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1082 for topic in topics:
1083 if topic not in ONOStopics:
1084 main.log.error( "Error: " + topic +
1085 " not in leaders" )
1086 missing = True
1087 else:
1088 main.log.error( "leaders() returned None" )
1089 except ( ValueError, TypeError ):
1090 main.log.exception( "Error parsing leaders" )
1091 main.log.error( repr( leaders ) )
1092 if missing:
Jon Halla440e872016-03-31 15:15:50 -07001093 for i in main.activeNodes:
1094 node = main.CLIs[i]
1095 response = node.leaders( jsonFormat=False)
1096 main.log.warn( str( node.name ) + " leaders output: \n" +
1097 str( response ) )
1098
1099 partitions = onosCli.partitions()
Jon Hall85794ff2015-07-08 14:12:30 -07001100 try:
1101 if partitions :
1102 parsedPartitions = json.loads( partitions )
1103 main.log.warn( json.dumps( parsedPartitions,
1104 sort_keys=True,
1105 indent=4,
1106 separators=( ',', ': ' ) ) )
1107 # TODO check for a leader in all paritions
1108 # TODO check for consistency among nodes
1109 else:
1110 main.log.error( "partitions() returned None" )
1111 except ( ValueError, TypeError ):
1112 main.log.exception( "Error parsing partitions" )
1113 main.log.error( repr( partitions ) )
Jon Halla440e872016-03-31 15:15:50 -07001114 pendingMap = onosCli.pendingMap()
Jon Hall85794ff2015-07-08 14:12:30 -07001115 try:
1116 if pendingMap :
1117 parsedPending = json.loads( pendingMap )
1118 main.log.warn( json.dumps( parsedPending,
1119 sort_keys=True,
1120 indent=4,
1121 separators=( ',', ': ' ) ) )
1122 # TODO check something here?
1123 else:
1124 main.log.error( "pendingMap() returned None" )
1125 except ( ValueError, TypeError ):
1126 main.log.exception( "Error parsing pending map" )
1127 main.log.error( repr( pendingMap ) )
1128 # Print flowrules
Jon Halla440e872016-03-31 15:15:50 -07001129 node = main.activeNodes[0]
1130 main.log.debug( main.CLIs[node].flows( jsonFormat=False ) )
Jon Hall85794ff2015-07-08 14:12:30 -07001131 main.step( "Wait a minute then ping again" )
1132 # the wait is above
1133 PingResult = main.TRUE
1134 for i in range( 8, 18 ):
1135 ping = main.Mininet1.pingHost( src="h" + str( i ),
1136 target="h" + str( i + 10 ) )
1137 PingResult = PingResult and ping
1138 if ping == main.FALSE:
1139 main.log.warn( "Ping failed between h" + str( i ) +
1140 " and h" + str( i + 10 ) )
1141 elif ping == main.TRUE:
1142 main.log.info( "Ping test passed!" )
1143 # Don't set PingResult or you'd override failures
1144 if PingResult == main.FALSE:
1145 main.log.error(
1146 "Intents have not been installed correctly, pings failed." )
1147 # TODO: pretty print
1148 main.log.warn( "ONOS1 intents: " )
1149 try:
Jon Halla440e872016-03-31 15:15:50 -07001150 tmpIntents = onosCli.intents()
Jon Hall85794ff2015-07-08 14:12:30 -07001151 main.log.warn( json.dumps( json.loads( tmpIntents ),
1152 sort_keys=True,
1153 indent=4,
1154 separators=( ',', ': ' ) ) )
1155 except ( ValueError, TypeError ):
1156 main.log.warn( repr( tmpIntents ) )
1157 utilities.assert_equals(
1158 expect=main.TRUE,
1159 actual=PingResult,
1160 onpass="Intents have been installed correctly and pings work",
1161 onfail="Intents have not been installed correctly, pings failed." )
1162
1163 def CASE5( self, main ):
1164 """
1165 Reading state of ONOS
1166 """
1167 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001168 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07001169 assert main, "main not defined"
1170 assert utilities.assert_equals, "utilities.assert_equals not defined"
1171
1172 main.case( "Setting up and gathering data for current state" )
1173 # The general idea for this test case is to pull the state of
1174 # ( intents,flows, topology,... ) from each ONOS node
1175 # We can then compare them with each other and also with past states
1176
1177 main.step( "Check that each switch has a master" )
1178 global mastershipState
1179 mastershipState = '[]'
1180
1181 # Assert that each device has a master
Jon Halla440e872016-03-31 15:15:50 -07001182 rolesNotNull = main.TRUE
1183 threads = []
1184 for i in main.activeNodes:
1185 t = main.Thread( target=main.CLIs[i].rolesNotNull,
1186 name="rolesNotNull-" + str( i ),
1187 args=[] )
1188 threads.append( t )
1189 t.start()
1190
1191 for t in threads:
1192 t.join()
1193 rolesNotNull = rolesNotNull and t.result
Jon Hall85794ff2015-07-08 14:12:30 -07001194 utilities.assert_equals(
1195 expect=main.TRUE,
1196 actual=rolesNotNull,
1197 onpass="Each device has a master",
1198 onfail="Some devices don't have a master assigned" )
1199
1200 main.step( "Get the Mastership of each switch" )
1201 ONOS1Mastership = main.ONOScli1.roles()
1202 # TODO: Make this a meaningful check
1203 if "Error" in ONOS1Mastership or not ONOS1Mastership:
1204 main.log.error( "Error in getting ONOS roles" )
1205 main.log.warn(
1206 "ONOS1 mastership response: " +
1207 repr( ONOS1Mastership ) )
1208 consistentMastership = main.FALSE
1209 else:
1210 mastershipState = ONOS1Mastership
1211 consistentMastership = main.TRUE
1212
1213 main.step( "Get the intents from each controller" )
1214 global intentState
1215 intentState = []
1216 ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
1217 intentCheck = main.FALSE
1218 if "Error" in ONOS1Intents or not ONOS1Intents:
1219 main.log.error( "Error in getting ONOS intents" )
1220 main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
1221 else:
1222 intentCheck = main.TRUE
1223
1224 main.step( "Get the flows from each controller" )
1225 global flowState
1226 flowState = []
1227 flowCheck = main.FALSE
1228 ONOS1Flows = main.ONOScli1.flows( jsonFormat=True )
1229 if "Error" in ONOS1Flows or not ONOS1Flows:
1230 main.log.error( "Error in getting ONOS flows" )
1231 main.log.warn( "ONOS1 flows repsponse: " + ONOS1Flows )
1232 else:
1233 # TODO: Do a better check, maybe compare flows on switches?
1234 flowState = ONOS1Flows
1235 flowCheck = main.TRUE
1236
1237 main.step( "Get the OF Table entries" )
1238 global flows
1239 flows = []
1240 for i in range( 1, 29 ):
GlennRC68467eb2015-11-16 18:01:01 -08001241 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
Jon Hall85794ff2015-07-08 14:12:30 -07001242 if flowCheck == main.FALSE:
1243 for table in flows:
1244 main.log.warn( table )
1245 # TODO: Compare switch flow tables with ONOS flow tables
1246
1247 main.step( "Collecting topology information from ONOS" )
1248 devices = []
1249 devices.append( main.ONOScli1.devices() )
1250 hosts = []
1251 hosts.append( json.loads( main.ONOScli1.hosts() ) )
1252 ports = []
1253 ports.append( main.ONOScli1.ports() )
1254 links = []
1255 links.append( main.ONOScli1.links() )
1256 clusters = []
1257 clusters.append( main.ONOScli1.clusters() )
1258
1259 main.step( "Each host has an IP address" )
1260 ipResult = main.TRUE
1261 for controller in range( 0, len( hosts ) ):
Jon Halla440e872016-03-31 15:15:50 -07001262 controllerStr = str( main.activeNodes[controller] + 1 )
1263 if hosts[ controller ]:
1264 for host in hosts[ controller ]:
1265 if not host.get( 'ipAddresses', [ ] ):
1266 main.log.error( "Error with host ips on controller" +
1267 controllerStr + ": " + str( host ) )
1268 ipResult = main.FALSE
Jon Hall85794ff2015-07-08 14:12:30 -07001269 utilities.assert_equals(
1270 expect=main.TRUE,
1271 actual=ipResult,
1272 onpass="The ips of the hosts aren't empty",
1273 onfail="The ip of at least one host is missing" )
1274
1275 # there should always only be one cluster
1276 main.step( "There is only one dataplane cluster" )
1277 try:
1278 numClusters = len( json.loads( clusters[ 0 ] ) )
1279 except ( ValueError, TypeError ):
1280 main.log.exception( "Error parsing clusters[0]: " +
1281 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001282 numClusters = "ERROR"
Jon Hall85794ff2015-07-08 14:12:30 -07001283 clusterResults = main.FALSE
1284 if numClusters == 1:
1285 clusterResults = main.TRUE
1286 utilities.assert_equals(
1287 expect=1,
1288 actual=numClusters,
1289 onpass="ONOS shows 1 SCC",
1290 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1291
1292 main.step( "Comparing ONOS topology to MN" )
1293 devicesResults = main.TRUE
1294 linksResults = main.TRUE
1295 hostsResults = main.TRUE
1296 mnSwitches = main.Mininet1.getSwitches()
1297 mnLinks = main.Mininet1.getLinks()
1298 mnHosts = main.Mininet1.getHosts()
Jon Halla440e872016-03-31 15:15:50 -07001299 for controller in main.activeNodes:
1300 controllerStr = str( main.activeNodes[controller] + 1 )
Jon Hall85794ff2015-07-08 14:12:30 -07001301 if devices[ controller ] and ports[ controller ] and\
1302 "Error" not in devices[ controller ] and\
1303 "Error" not in ports[ controller ]:
Jon Hall6e709752016-02-01 13:38:46 -08001304 currentDevicesResult = main.Mininet1.compareSwitches(
1305 mnSwitches,
1306 json.loads( devices[ controller ] ),
1307 json.loads( ports[ controller ] ) )
Jon Hall85794ff2015-07-08 14:12:30 -07001308 else:
1309 currentDevicesResult = main.FALSE
1310 utilities.assert_equals( expect=main.TRUE,
1311 actual=currentDevicesResult,
1312 onpass="ONOS" + controllerStr +
1313 " Switches view is correct",
1314 onfail="ONOS" + controllerStr +
1315 " Switches view is incorrect" )
1316 if links[ controller ] and "Error" not in links[ controller ]:
1317 currentLinksResult = main.Mininet1.compareLinks(
1318 mnSwitches, mnLinks,
1319 json.loads( links[ controller ] ) )
1320 else:
1321 currentLinksResult = main.FALSE
1322 utilities.assert_equals( expect=main.TRUE,
1323 actual=currentLinksResult,
1324 onpass="ONOS" + controllerStr +
1325 " links view is correct",
1326 onfail="ONOS" + controllerStr +
1327 " links view is incorrect" )
1328
Jon Halla440e872016-03-31 15:15:50 -07001329 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall85794ff2015-07-08 14:12:30 -07001330 currentHostsResult = main.Mininet1.compareHosts(
1331 mnHosts,
1332 hosts[ controller ] )
1333 else:
1334 currentHostsResult = main.FALSE
1335 utilities.assert_equals( expect=main.TRUE,
1336 actual=currentHostsResult,
1337 onpass="ONOS" + controllerStr +
1338 " hosts exist in Mininet",
1339 onfail="ONOS" + controllerStr +
1340 " hosts don't match Mininet" )
1341
1342 devicesResults = devicesResults and currentDevicesResult
1343 linksResults = linksResults and currentLinksResult
1344 hostsResults = hostsResults and currentHostsResult
1345
1346 main.step( "Device information is correct" )
1347 utilities.assert_equals(
1348 expect=main.TRUE,
1349 actual=devicesResults,
1350 onpass="Device information is correct",
1351 onfail="Device information is incorrect" )
1352
1353 main.step( "Links are correct" )
1354 utilities.assert_equals(
1355 expect=main.TRUE,
1356 actual=linksResults,
1357 onpass="Link are correct",
1358 onfail="Links are incorrect" )
1359
1360 main.step( "Hosts are correct" )
1361 utilities.assert_equals(
1362 expect=main.TRUE,
1363 actual=hostsResults,
1364 onpass="Hosts are correct",
1365 onfail="Hosts are incorrect" )
1366
1367 def CASE6( self, main ):
1368 """
1369 The Failure case.
1370 """
1371 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001372 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07001373 assert main, "main not defined"
1374 assert utilities.assert_equals, "utilities.assert_equals not defined"
1375
1376 # Reset non-persistent variables
1377 try:
1378 iCounterValue = 0
1379 except NameError:
1380 main.log.error( "iCounterValue not defined, setting to 0" )
1381 iCounterValue = 0
1382
1383 main.case( "Restart ONOS node" )
Jon Hall783bbf92015-07-23 14:33:19 -07001384 main.caseExplanation = "Killing ONOS process and restart cli " +\
Jon Hall85794ff2015-07-08 14:12:30 -07001385 "sessions once onos is up."
Jon Hall96091e62015-09-21 17:34:17 -07001386
1387 main.step( "Checking ONOS Logs for errors" )
1388 for node in main.nodes:
1389 main.log.debug( "Checking logs for errors on " + node.name + ":" )
1390 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
1391
Jon Hall85794ff2015-07-08 14:12:30 -07001392 main.step( "Killing ONOS processes" )
Jon Halle1a3b752015-07-22 13:02:46 -07001393 killResult = main.ONOSbench.onosKill( main.nodes[0].ip_address )
Jon Hall85794ff2015-07-08 14:12:30 -07001394 start = time.time()
1395 utilities.assert_equals( expect=main.TRUE, actual=killResult,
1396 onpass="ONOS Killed",
1397 onfail="Error killing ONOS" )
1398
1399 main.step( "Checking if ONOS is up yet" )
1400 count = 0
1401 while count < 10:
Jon Halle1a3b752015-07-22 13:02:46 -07001402 onos1Isup = main.ONOSbench.isup( main.nodes[0].ip_address )
Jon Hall85794ff2015-07-08 14:12:30 -07001403 if onos1Isup == main.TRUE:
1404 elapsed = time.time() - start
1405 break
1406 else:
1407 count = count + 1
1408 utilities.assert_equals( expect=main.TRUE, actual=onos1Isup,
1409 onpass="ONOS is back up",
1410 onfail="ONOS failed to start" )
1411
Jon Hall6509dbf2016-06-21 17:01:17 -07001412 main.step( "Starting ONOS CLI sessions" )
Jon Halle1a3b752015-07-22 13:02:46 -07001413 cliResults = main.ONOScli1.startOnosCli( main.nodes[0].ip_address )
Jon Hall85794ff2015-07-08 14:12:30 -07001414 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1415 onpass="ONOS cli startup successful",
1416 onfail="ONOS cli startup failed" )
1417
1418 if elapsed:
1419 main.log.info( "ESTIMATE: ONOS took %s seconds to restart" %
1420 str( elapsed ) )
1421 main.restartTime = elapsed
1422 else:
1423 main.restartTime = -1
1424 time.sleep( 5 )
1425 # rerun on election apps
1426 main.ONOScli1.electionTestRun()
1427
1428 def CASE7( self, main ):
1429 """
1430 Check state after ONOS failure
1431 """
1432 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001433 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07001434 assert main, "main not defined"
1435 assert utilities.assert_equals, "utilities.assert_equals not defined"
1436 main.case( "Running ONOS Constant State Tests" )
Jon Hall6e709752016-02-01 13:38:46 -08001437
Jon Hall85794ff2015-07-08 14:12:30 -07001438 main.step( "Check that each switch has a master" )
1439 # Assert that each device has a master
Jon Halla440e872016-03-31 15:15:50 -07001440 rolesNotNull = main.TRUE
1441 threads = []
1442 for i in main.activeNodes:
1443 t = main.Thread( target=main.CLIs[i].rolesNotNull,
1444 name="rolesNotNull-" + str( i ),
1445 args=[ ] )
1446 threads.append( t )
1447 t.start()
1448
1449 for t in threads:
1450 t.join()
1451 rolesNotNull = rolesNotNull and t.result
Jon Hall85794ff2015-07-08 14:12:30 -07001452 utilities.assert_equals(
1453 expect=main.TRUE,
1454 actual=rolesNotNull,
1455 onpass="Each device has a master",
1456 onfail="Some devices don't have a master assigned" )
1457
1458 main.step( "Check if switch roles are consistent across all nodes" )
1459 ONOS1Mastership = main.ONOScli1.roles()
1460 # FIXME: Refactor this whole case for single instance
1461 if "Error" in ONOS1Mastership or not ONOS1Mastership:
1462 main.log.error( "Error in getting ONOS mastership" )
1463 main.log.warn( "ONOS1 mastership response: " +
1464 repr( ONOS1Mastership ) )
1465 consistentMastership = main.FALSE
1466 else:
1467 consistentMastership = main.TRUE
1468 utilities.assert_equals(
1469 expect=main.TRUE,
1470 actual=consistentMastership,
1471 onpass="Switch roles are consistent across all ONOS nodes",
1472 onfail="ONOS nodes have different views of switch roles" )
1473
1474 description2 = "Compare switch roles from before failure"
1475 main.step( description2 )
1476
1477 currentJson = json.loads( ONOS1Mastership )
1478 oldJson = json.loads( mastershipState )
1479 mastershipCheck = main.TRUE
1480 for i in range( 1, 29 ):
1481 switchDPID = str(
1482 main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
1483
1484 current = [ switch[ 'master' ] for switch in currentJson
1485 if switchDPID in switch[ 'id' ] ]
1486 old = [ switch[ 'master' ] for switch in oldJson
1487 if switchDPID in switch[ 'id' ] ]
1488 if current == old:
1489 mastershipCheck = mastershipCheck and main.TRUE
1490 else:
1491 main.log.warn( "Mastership of switch %s changed" % switchDPID )
1492 mastershipCheck = main.FALSE
1493 utilities.assert_equals(
1494 expect=main.TRUE,
1495 actual=mastershipCheck,
1496 onpass="Mastership of Switches was not changed",
1497 onfail="Mastership of some switches changed" )
1498 mastershipCheck = mastershipCheck and consistentMastership
1499
1500 main.step( "Get the intents and compare across all nodes" )
1501 ONOS1Intents = main.ONOScli1.intents( jsonFormat=True )
1502 intentCheck = main.FALSE
1503 if "Error" in ONOS1Intents or not ONOS1Intents:
1504 main.log.error( "Error in getting ONOS intents" )
1505 main.log.warn( "ONOS1 intents response: " + repr( ONOS1Intents ) )
1506 else:
1507 intentCheck = main.TRUE
1508 utilities.assert_equals(
1509 expect=main.TRUE,
1510 actual=intentCheck,
1511 onpass="Intents are consistent across all ONOS nodes",
1512 onfail="ONOS nodes have different views of intents" )
1513 # Print the intent states
1514 intents = []
1515 intents.append( ONOS1Intents )
1516 intentStates = []
1517 for node in intents: # Iter through ONOS nodes
1518 nodeStates = []
1519 # Iter through intents of a node
1520 for intent in json.loads( node ):
1521 nodeStates.append( intent[ 'state' ] )
1522 intentStates.append( nodeStates )
1523 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
1524 main.log.info( dict( out ) )
1525
1526 # NOTE: Store has no durability, so intents are lost across system
1527 # restarts
1528 """
1529 main.step( "Compare current intents with intents before the failure" )
1530 # NOTE: this requires case 5 to pass for intentState to be set.
1531 # maybe we should stop the test if that fails?
1532 sameIntents = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07001533 try:
1534 intentState
1535 except NameError:
1536 main.log.warn( "No previous intent state was saved" )
1537 else:
1538 if intentState and intentState == ONOSIntents[ 0 ]:
1539 sameIntents = main.TRUE
1540 main.log.info( "Intents are consistent with before failure" )
1541 # TODO: possibly the states have changed? we may need to figure out
1542 # what the acceptable states are
1543 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
1544 sameIntents = main.TRUE
1545 try:
1546 before = json.loads( intentState )
1547 after = json.loads( ONOSIntents[ 0 ] )
1548 for intent in before:
1549 if intent not in after:
1550 sameIntents = main.FALSE
1551 main.log.debug( "Intent is not currently in ONOS " +
1552 "(at least in the same form):" )
1553 main.log.debug( json.dumps( intent ) )
1554 except ( ValueError, TypeError ):
1555 main.log.exception( "Exception printing intents" )
1556 main.log.debug( repr( ONOSIntents[0] ) )
1557 main.log.debug( repr( intentState ) )
1558 if sameIntents == main.FALSE:
1559 try:
1560 main.log.debug( "ONOS intents before: " )
1561 main.log.debug( json.dumps( json.loads( intentState ),
1562 sort_keys=True, indent=4,
1563 separators=( ',', ': ' ) ) )
1564 main.log.debug( "Current ONOS intents: " )
1565 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
1566 sort_keys=True, indent=4,
1567 separators=( ',', ': ' ) ) )
1568 except ( ValueError, TypeError ):
1569 main.log.exception( "Exception printing intents" )
1570 main.log.debug( repr( ONOSIntents[0] ) )
1571 main.log.debug( repr( intentState ) )
1572 utilities.assert_equals(
1573 expect=main.TRUE,
1574 actual=sameIntents,
1575 onpass="Intents are consistent with before failure",
1576 onfail="The Intents changed during failure" )
Jon Hall85794ff2015-07-08 14:12:30 -07001577 intentCheck = intentCheck and sameIntents
1578 """
1579 main.step( "Get the OF Table entries and compare to before " +
1580 "component failure" )
1581 FlowTables = main.TRUE
Jon Hall85794ff2015-07-08 14:12:30 -07001582 for i in range( 28 ):
1583 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08001584 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
Jon Hall41d39f12016-04-11 22:54:35 -07001585 curSwitch = main.Mininet1.flowTableComp( flows[i], tmpFlows )
1586 FlowTables = FlowTables and curSwitch
1587 if curSwitch == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08001588 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall85794ff2015-07-08 14:12:30 -07001589 utilities.assert_equals(
1590 expect=main.TRUE,
1591 actual=FlowTables,
1592 onpass="No changes were found in the flow tables",
1593 onfail="Changes were found in the flow tables" )
1594
1595 main.step( "Leadership Election is still functional" )
1596 # Test of LeadershipElection
1597
Jon Halla440e872016-03-31 15:15:50 -07001598 leader = main.nodes[ main.activeNodes[ 0 ] ].ip_address
Jon Hall85794ff2015-07-08 14:12:30 -07001599 leaderResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -07001600 for controller in range( 1, main.numCtrls + 1 ):
Jon Hall85794ff2015-07-08 14:12:30 -07001601 # loop through ONOScli handlers
1602 node = getattr( main, ( 'ONOScli' + str( controller ) ) )
1603 leaderN = node.electionTestLeader()
1604 # verify leader is ONOS1
1605 # NOTE even though we restarted ONOS, it is the only one so onos 1
1606 # must be leader
1607 if leaderN == leader:
1608 # all is well
1609 pass
1610 elif leaderN == main.FALSE:
1611 # error in response
1612 main.log.error( "Something is wrong with " +
1613 "electionTestLeader function, check the" +
1614 " error logs" )
1615 leaderResult = main.FALSE
1616 elif leader != leaderN:
1617 leaderResult = main.FALSE
1618 main.log.error( "ONOS" + str( controller ) + " sees " +
1619 str( leaderN ) +
1620 " as the leader of the election app. " +
1621 "Leader should be " + str( leader ) )
1622 utilities.assert_equals(
1623 expect=main.TRUE,
1624 actual=leaderResult,
1625 onpass="Leadership election passed",
1626 onfail="Something went wrong with Leadership election" )
1627
1628 def CASE8( self, main ):
1629 """
1630 Compare topo
1631 """
1632 import json
1633 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001634 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07001635 assert main, "main not defined"
1636 assert utilities.assert_equals, "utilities.assert_equals not defined"
1637
1638 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07001639 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall85794ff2015-07-08 14:12:30 -07001640 " and ONOS"
Jon Hall85794ff2015-07-08 14:12:30 -07001641 topoResult = main.FALSE
1642 elapsed = 0
1643 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08001644 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall85794ff2015-07-08 14:12:30 -07001645 startTime = time.time()
1646 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08001647 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hall96091e62015-09-21 17:34:17 -07001648 devicesResults = main.TRUE
1649 linksResults = main.TRUE
1650 hostsResults = main.TRUE
1651 hostAttachmentResults = True
Jon Hall85794ff2015-07-08 14:12:30 -07001652 count += 1
1653 cliStart = time.time()
1654 devices = []
1655 devices.append( main.ONOScli1.devices() )
1656 hosts = []
1657 hosts.append( json.loads( main.ONOScli1.hosts() ) )
1658 ipResult = main.TRUE
1659 for controller in range( 0, len( hosts ) ):
1660 controllerStr = str( controller + 1 )
1661 for host in hosts[ controller ]:
1662 if host is None or host.get( 'ipAddresses', [] ) == []:
1663 main.log.error(
1664 "DEBUG:Error with host ips on controller" +
1665 controllerStr + ": " + str( host ) )
1666 ipResult = main.FALSE
1667 ports = []
1668 ports.append( main.ONOScli1.ports() )
1669 links = []
1670 links.append( main.ONOScli1.links() )
1671 clusters = []
1672 clusters.append( main.ONOScli1.clusters() )
1673
1674 elapsed = time.time() - startTime
1675 cliTime = time.time() - cliStart
1676 print "CLI time: " + str( cliTime )
1677
1678 mnSwitches = main.Mininet1.getSwitches()
1679 mnLinks = main.Mininet1.getLinks()
1680 mnHosts = main.Mininet1.getHosts()
Jon Halle1a3b752015-07-22 13:02:46 -07001681 for controller in range( main.numCtrls ):
Jon Hall85794ff2015-07-08 14:12:30 -07001682 controllerStr = str( controller + 1 )
1683 if devices[ controller ] and ports[ controller ] and\
1684 "Error" not in devices[ controller ] and\
1685 "Error" not in ports[ controller ]:
1686
Jon Hallc6793552016-01-19 14:18:37 -08001687 try:
1688 currentDevicesResult = main.Mininet1.compareSwitches(
1689 mnSwitches,
1690 json.loads( devices[ controller ] ),
1691 json.loads( ports[ controller ] ) )
1692 except ( TypeError, ValueError ) as e:
1693 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
1694 devices[ controller ], ports[ controller ] ) )
Jon Hall85794ff2015-07-08 14:12:30 -07001695 else:
1696 currentDevicesResult = main.FALSE
1697 utilities.assert_equals( expect=main.TRUE,
1698 actual=currentDevicesResult,
1699 onpass="ONOS" + controllerStr +
1700 " Switches view is correct",
1701 onfail="ONOS" + controllerStr +
1702 " Switches view is incorrect" )
1703
1704 if links[ controller ] and "Error" not in links[ controller ]:
1705 currentLinksResult = main.Mininet1.compareLinks(
1706 mnSwitches, mnLinks,
1707 json.loads( links[ controller ] ) )
1708 else:
1709 currentLinksResult = main.FALSE
1710 utilities.assert_equals( expect=main.TRUE,
1711 actual=currentLinksResult,
1712 onpass="ONOS" + controllerStr +
1713 " links view is correct",
1714 onfail="ONOS" + controllerStr +
1715 " links view is incorrect" )
1716
1717 if hosts[ controller ] or "Error" not in hosts[ controller ]:
1718 currentHostsResult = main.Mininet1.compareHosts(
1719 mnHosts,
1720 hosts[ controller ] )
1721 else:
1722 currentHostsResult = main.FALSE
1723 utilities.assert_equals( expect=main.TRUE,
1724 actual=currentHostsResult,
1725 onpass="ONOS" + controllerStr +
1726 " hosts exist in Mininet",
1727 onfail="ONOS" + controllerStr +
1728 " hosts don't match Mininet" )
1729 # CHECKING HOST ATTACHMENT POINTS
1730 hostAttachment = True
1731 zeroHosts = False
1732 # FIXME: topo-HA/obelisk specific mappings:
1733 # key is mac and value is dpid
1734 mappings = {}
1735 for i in range( 1, 29 ): # hosts 1 through 28
1736 # set up correct variables:
1737 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
1738 if i == 1:
1739 deviceId = "1000".zfill(16)
1740 elif i == 2:
1741 deviceId = "2000".zfill(16)
1742 elif i == 3:
1743 deviceId = "3000".zfill(16)
1744 elif i == 4:
1745 deviceId = "3004".zfill(16)
1746 elif i == 5:
1747 deviceId = "5000".zfill(16)
1748 elif i == 6:
1749 deviceId = "6000".zfill(16)
1750 elif i == 7:
1751 deviceId = "6007".zfill(16)
1752 elif i >= 8 and i <= 17:
1753 dpid = '3' + str( i ).zfill( 3 )
1754 deviceId = dpid.zfill(16)
1755 elif i >= 18 and i <= 27:
1756 dpid = '6' + str( i ).zfill( 3 )
1757 deviceId = dpid.zfill(16)
1758 elif i == 28:
1759 deviceId = "2800".zfill(16)
1760 mappings[ macId ] = deviceId
1761 if hosts[ controller ] or "Error" not in hosts[ controller ]:
1762 if hosts[ controller ] == []:
1763 main.log.warn( "There are no hosts discovered" )
1764 zeroHosts = True
1765 else:
1766 for host in hosts[ controller ]:
1767 mac = None
1768 location = None
1769 device = None
1770 port = None
1771 try:
1772 mac = host.get( 'mac' )
1773 assert mac, "mac field could not be found for this host object"
1774
1775 location = host.get( 'location' )
1776 assert location, "location field could not be found for this host object"
1777
1778 # Trim the protocol identifier off deviceId
1779 device = str( location.get( 'elementId' ) ).split(':')[1]
1780 assert device, "elementId field could not be found for this host location object"
1781
1782 port = location.get( 'port' )
1783 assert port, "port field could not be found for this host location object"
1784
1785 # Now check if this matches where they should be
1786 if mac and device and port:
1787 if str( port ) != "1":
1788 main.log.error( "The attachment port is incorrect for " +
1789 "host " + str( mac ) +
1790 ". Expected: 1 Actual: " + str( port) )
1791 hostAttachment = False
1792 if device != mappings[ str( mac ) ]:
1793 main.log.error( "The attachment device is incorrect for " +
1794 "host " + str( mac ) +
1795 ". Expected: " + mappings[ str( mac ) ] +
1796 " Actual: " + device )
1797 hostAttachment = False
1798 else:
1799 hostAttachment = False
1800 except AssertionError:
1801 main.log.exception( "Json object not as expected" )
1802 main.log.error( repr( host ) )
1803 hostAttachment = False
1804 else:
1805 main.log.error( "No hosts json output or \"Error\"" +
1806 " in output. hosts = " +
1807 repr( hosts[ controller ] ) )
1808 if zeroHosts is False:
1809 hostAttachment = True
1810
Jon Hall85794ff2015-07-08 14:12:30 -07001811 devicesResults = devicesResults and currentDevicesResult
1812 linksResults = linksResults and currentLinksResult
1813 hostsResults = hostsResults and currentHostsResult
1814 hostAttachmentResults = hostAttachmentResults and\
1815 hostAttachment
1816
Jon Halla440e872016-03-31 15:15:50 -07001817 # "consistent" results don't make sense for single instance
Jon Hall85794ff2015-07-08 14:12:30 -07001818 # there should always only be one cluster
Jon Hall85794ff2015-07-08 14:12:30 -07001819 clusterResults = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07001820 try:
1821 numClusters = len( json.loads( clusters[ 0 ] ) )
1822 except ( ValueError, TypeError ):
1823 main.log.exception( "Error parsing clusters[0]: " +
1824 repr( clusters[0] ) )
1825 numClusters = "ERROR"
1826 clusterResults = main.FALSE
Jon Hall85794ff2015-07-08 14:12:30 -07001827 if numClusters == 1:
1828 clusterResults = main.TRUE
1829 utilities.assert_equals(
1830 expect=1,
1831 actual=numClusters,
1832 onpass="ONOS shows 1 SCC",
1833 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1834
1835 topoResult = ( devicesResults and linksResults
1836 and hostsResults and ipResult and clusterResults and
1837 hostAttachmentResults )
1838
1839 topoResult = topoResult and int( count <= 2 )
1840 note = "note it takes about " + str( int( cliTime ) ) + \
1841 " seconds for the test to make all the cli calls to fetch " +\
1842 "the topology from each ONOS instance"
1843 main.log.info(
1844 "Very crass estimate for topology discovery/convergence( " +
1845 str( note ) + " ): " + str( elapsed ) + " seconds, " +
1846 str( count ) + " tries" )
1847 utilities.assert_equals( expect=main.TRUE, actual=topoResult,
1848 onpass="Topology Check Test successful",
1849 onfail="Topology Check Test NOT successful" )
Jon Hall41d39f12016-04-11 22:54:35 -07001850 main.step( "Checking ONOS nodes" )
1851 nodeResults = utilities.retry( main.HA.nodesCheck,
1852 False,
1853 args=[main.activeNodes],
1854 attempts=5 )
1855
1856 utilities.assert_equals( expect=True, actual=nodeResults,
1857 onpass="Nodes check successful",
1858 onfail="Nodes check NOT successful" )
1859 if not nodeResults:
1860 for i in main.activeNodes:
1861 main.log.debug( "{} components not ACTIVE: \n{}".format(
1862 main.CLIs[i].name,
1863 main.CLIs[i].sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall85794ff2015-07-08 14:12:30 -07001864
Jon Halld2871c22016-07-26 11:01:14 -07001865 if not topoResult:
1866 main.cleanup()
1867 main.exit()
1868
Jon Hall85794ff2015-07-08 14:12:30 -07001869 def CASE9( self, main ):
1870 """
1871 Link s3-s28 down
1872 """
1873 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001874 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07001875 assert main, "main not defined"
1876 assert utilities.assert_equals, "utilities.assert_equals not defined"
1877 # NOTE: You should probably run a topology check after this
1878
1879 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
1880
1881 description = "Turn off a link to ensure that Link Discovery " +\
1882 "is working properly"
1883 main.case( description )
1884
1885 main.step( "Kill Link between s3 and s28" )
1886 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
1887 main.log.info( "Waiting " + str( linkSleep ) +
1888 " seconds for link down to be discovered" )
1889 time.sleep( linkSleep )
1890 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
1891 onpass="Link down successful",
1892 onfail="Failed to bring link down" )
1893 # TODO do some sort of check here
1894
1895 def CASE10( self, main ):
1896 """
1897 Link s3-s28 up
1898 """
1899 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001900 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07001901 assert main, "main not defined"
1902 assert utilities.assert_equals, "utilities.assert_equals not defined"
1903 # NOTE: You should probably run a topology check after this
1904
1905 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
1906
1907 description = "Restore a link to ensure that Link Discovery is " + \
1908 "working properly"
1909 main.case( description )
1910
1911 main.step( "Bring link between s3 and s28 back up" )
1912 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
1913 main.log.info( "Waiting " + str( linkSleep ) +
1914 " seconds for link up to be discovered" )
1915 time.sleep( linkSleep )
1916 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
1917 onpass="Link up successful",
1918 onfail="Failed to bring link up" )
1919 # TODO do some sort of check here
1920
1921 def CASE11( self, main ):
1922 """
1923 Switch Down
1924 """
1925 # NOTE: You should probably run a topology check after this
1926 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001927 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07001928 assert main, "main not defined"
1929 assert utilities.assert_equals, "utilities.assert_equals not defined"
1930
1931 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
1932
1933 description = "Killing a switch to ensure it is discovered correctly"
Jon Halla440e872016-03-31 15:15:50 -07001934 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall85794ff2015-07-08 14:12:30 -07001935 main.case( description )
1936 switch = main.params[ 'kill' ][ 'switch' ]
1937 switchDPID = main.params[ 'kill' ][ 'dpid' ]
1938
1939 # TODO: Make this switch parameterizable
1940 main.step( "Kill " + switch )
1941 main.log.info( "Deleting " + switch )
1942 main.Mininet1.delSwitch( switch )
1943 main.log.info( "Waiting " + str( switchSleep ) +
1944 " seconds for switch down to be discovered" )
1945 time.sleep( switchSleep )
Jon Halla440e872016-03-31 15:15:50 -07001946 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall85794ff2015-07-08 14:12:30 -07001947 # Peek at the deleted switch
1948 main.log.warn( str( device ) )
1949 result = main.FALSE
1950 if device and device[ 'available' ] is False:
1951 result = main.TRUE
1952 utilities.assert_equals( expect=main.TRUE, actual=result,
1953 onpass="Kill switch successful",
1954 onfail="Failed to kill switch?" )
1955
1956 def CASE12( self, main ):
1957 """
1958 Switch Up
1959 """
1960 # NOTE: You should probably run a topology check after this
1961 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001962 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07001963 assert main, "main not defined"
1964 assert utilities.assert_equals, "utilities.assert_equals not defined"
1965
1966 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
1967 switch = main.params[ 'kill' ][ 'switch' ]
1968 switchDPID = main.params[ 'kill' ][ 'dpid' ]
1969 links = main.params[ 'kill' ][ 'links' ].split()
Jon Halla440e872016-03-31 15:15:50 -07001970 onosCli = main.CLIs[ main.activeNodes[0] ]
Jon Hall85794ff2015-07-08 14:12:30 -07001971 description = "Adding a switch to ensure it is discovered correctly"
1972 main.case( description )
1973
1974 main.step( "Add back " + switch )
1975 main.Mininet1.addSwitch( switch, dpid=switchDPID )
1976 for peer in links:
1977 main.Mininet1.addLink( switch, peer )
Jon Halla440e872016-03-31 15:15:50 -07001978 ipList = [ node.ip_address for node in main.nodes ]
Jon Hall85794ff2015-07-08 14:12:30 -07001979 main.Mininet1.assignSwController( sw=switch, ip=ipList )
1980 main.log.info( "Waiting " + str( switchSleep ) +
1981 " seconds for switch up to be discovered" )
1982 time.sleep( switchSleep )
Jon Halla440e872016-03-31 15:15:50 -07001983 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall85794ff2015-07-08 14:12:30 -07001984 # Peek at the deleted switch
1985 main.log.warn( str( device ) )
1986 result = main.FALSE
1987 if device and device[ 'available' ]:
1988 result = main.TRUE
1989 utilities.assert_equals( expect=main.TRUE, actual=result,
1990 onpass="add switch successful",
1991 onfail="Failed to add switch?" )
1992
1993 def CASE13( self, main ):
1994 """
1995 Clean up
1996 """
1997 import os
1998 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001999 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07002000 assert main, "main not defined"
2001 assert utilities.assert_equals, "utilities.assert_equals not defined"
2002 # printing colors to terminal
2003 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2004 'blue': '\033[94m', 'green': '\033[92m',
2005 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2006 main.case( "Test Cleanup" )
2007 main.step( "Killing tcpdumps" )
2008 main.Mininet2.stopTcpdump()
2009
2010 testname = main.TEST
Jon Hall96091e62015-09-21 17:34:17 -07002011 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall85794ff2015-07-08 14:12:30 -07002012 main.step( "Copying MN pcap and ONOS log files to test station" )
2013 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2014 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002015 # NOTE: MN Pcap file is being saved to logdir.
2016 # We scp this file as MN and TestON aren't necessarily the same vm
2017
2018 # FIXME: To be replaced with a Jenkin's post script
Jon Hall85794ff2015-07-08 14:12:30 -07002019 # TODO: Load these from params
2020 # NOTE: must end in /
2021 logFolder = "/opt/onos/log/"
2022 logFiles = [ "karaf.log", "karaf.log.1" ]
2023 # NOTE: must end in /
Jon Hall85794ff2015-07-08 14:12:30 -07002024 for f in logFiles:
Jon Hall96091e62015-09-21 17:34:17 -07002025 for node in main.nodes:
Jon Halla440e872016-03-31 15:15:50 -07002026 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002027 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2028 logFolder + f, dstName )
Jon Hall85794ff2015-07-08 14:12:30 -07002029 # std*.log's
2030 # NOTE: must end in /
2031 logFolder = "/opt/onos/var/"
2032 logFiles = [ "stderr.log", "stdout.log" ]
2033 # NOTE: must end in /
Jon Hall85794ff2015-07-08 14:12:30 -07002034 for f in logFiles:
Jon Hall96091e62015-09-21 17:34:17 -07002035 for node in main.nodes:
Jon Halla440e872016-03-31 15:15:50 -07002036 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002037 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2038 logFolder + f, dstName )
2039 else:
2040 main.log.debug( "skipping saving log files" )
Jon Hall85794ff2015-07-08 14:12:30 -07002041
Jon Hall85794ff2015-07-08 14:12:30 -07002042 main.step( "Stopping Mininet" )
2043 mnResult = main.Mininet1.stopNet()
2044 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2045 onpass="Mininet stopped",
2046 onfail="MN cleanup NOT successful" )
2047
2048 main.step( "Checking ONOS Logs for errors" )
Jon Hall96091e62015-09-21 17:34:17 -07002049 for node in main.nodes:
2050 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2051 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall85794ff2015-07-08 14:12:30 -07002052
2053 try:
2054 timerLog = open( main.logdir + "/Timers.csv", 'w')
2055 # Overwrite with empty line and close
2056 labels = "Gossip Intents, Restart"
2057 data = str( gossipTime ) + ", " + str( main.restartTime )
2058 timerLog.write( labels + "\n" + data )
2059 timerLog.close()
2060 except NameError, e:
2061 main.log.exception(e)
2062
2063 def CASE14( self, main ):
2064 """
2065 start election app on all onos nodes
2066 """
Jon Halle1a3b752015-07-22 13:02:46 -07002067 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07002068 assert main, "main not defined"
2069 assert utilities.assert_equals, "utilities.assert_equals not defined"
2070
2071 main.case("Start Leadership Election app")
2072 main.step( "Install leadership election app" )
Jon Halla440e872016-03-31 15:15:50 -07002073 onosCli = main.CLIs[ main.activeNodes[0] ]
2074 appResult = onosCli.activateApp( "org.onosproject.election" )
Jon Hall85794ff2015-07-08 14:12:30 -07002075 utilities.assert_equals(
2076 expect=main.TRUE,
2077 actual=appResult,
2078 onpass="Election app installed",
2079 onfail="Something went wrong with installing Leadership election" )
2080
2081 main.step( "Run for election on each node" )
Jon Halla440e872016-03-31 15:15:50 -07002082 for i in main.activeNodes:
2083 main.CLIs[i].electionTestRun()
Jon Hall25463a82016-04-13 14:03:52 -07002084 time.sleep(5)
2085 activeCLIs = [ main.CLIs[i] for i in main.activeNodes ]
2086 sameResult, leaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall85794ff2015-07-08 14:12:30 -07002087 utilities.assert_equals(
Jon Hall25463a82016-04-13 14:03:52 -07002088 expect=True,
2089 actual=sameResult,
2090 onpass="All nodes see the same leaderboards",
2091 onfail="Inconsistent leaderboards" )
2092
2093 if sameResult:
2094 leader = leaders[ 0 ][ 0 ]
2095 if main.nodes[main.activeNodes[0]].ip_address in leader:
2096 correctLeader = True
2097 else:
2098 correctLeader = False
2099 main.step( "First node was elected leader" )
2100 utilities.assert_equals(
2101 expect=True,
2102 actual=correctLeader,
2103 onpass="Correct leader was elected",
2104 onfail="Incorrect leader" )
Jon Hall85794ff2015-07-08 14:12:30 -07002105
2106 def CASE15( self, main ):
2107 """
2108 Check that Leadership Election is still functional
acsmars71adceb2015-08-31 15:09:26 -07002109 15.1 Run election on each node
2110 15.2 Check that each node has the same leaders and candidates
2111 15.3 Find current leader and withdraw
2112 15.4 Check that a new node was elected leader
2113 15.5 Check that that new leader was the candidate of old leader
2114 15.6 Run for election on old leader
2115 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2116 15.8 Make sure that the old leader was added to the candidate list
2117
2118 old and new variable prefixes refer to data from before vs after
2119 withdrawl and later before withdrawl vs after re-election
Jon Hall85794ff2015-07-08 14:12:30 -07002120 """
acsmars71adceb2015-08-31 15:09:26 -07002121 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002122 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07002123 assert main, "main not defined"
2124 assert utilities.assert_equals, "utilities.assert_equals not defined"
acsmars71adceb2015-08-31 15:09:26 -07002125 assert main.CLIs, "main.CLIs not defined"
2126 assert main.nodes, "main.nodes not defined"
2127
Jon Hall85794ff2015-07-08 14:12:30 -07002128 description = "Check that Leadership Election is still functional"
2129 main.case( description )
Jon Halla440e872016-03-31 15:15:50 -07002130 # NOTE: Need to re-run after restarts since being a canidate is not persistant
acsmars2c2fcdd2015-08-25 17:14:13 -07002131
Jon Halla440e872016-03-31 15:15:50 -07002132 oldLeaders = [] # list of lists of each nodes' candidates before
2133 newLeaders = [] # list of lists of each nodes' candidates after
acsmars71adceb2015-08-31 15:09:26 -07002134 oldLeader = '' # the old leader from oldLeaders, None if not same
2135 newLeader = '' # the new leaders fron newLoeaders, None if not same
2136 oldLeaderCLI = None # the CLI of the old leader used for re-electing
2137 expectNoLeader = False # True when there is only one leader
2138 if main.numCtrls == 1:
2139 expectNoLeader = True
acsmars2c2fcdd2015-08-25 17:14:13 -07002140
acsmars71adceb2015-08-31 15:09:26 -07002141 main.step( "Run for election on each node" )
2142 electionResult = main.TRUE
2143
Jon Halla440e872016-03-31 15:15:50 -07002144 for i in main.activeNodes: # run test election on each node
2145 if main.CLIs[i].electionTestRun() == main.FALSE:
acsmars71adceb2015-08-31 15:09:26 -07002146 electionResult = main.FALSE
acsmars71adceb2015-08-31 15:09:26 -07002147 utilities.assert_equals(
2148 expect=main.TRUE,
2149 actual=electionResult,
2150 onpass="All nodes successfully ran for leadership",
2151 onfail="At least one node failed to run for leadership" )
2152
acsmars3a72bde2015-09-02 14:16:22 -07002153 if electionResult == main.FALSE:
2154 main.log.error(
2155 "Skipping Test Case because Election Test App isn't loaded" )
2156 main.skipCase()
2157
acsmars71adceb2015-08-31 15:09:26 -07002158 main.step( "Check that each node shows the same leader and candidates" )
Jon Halla440e872016-03-31 15:15:50 -07002159 failMessage = "Nodes have different leaderboards"
Jon Halla440e872016-03-31 15:15:50 -07002160 activeCLIs = [ main.CLIs[i] for i in main.activeNodes ]
Jon Hall41d39f12016-04-11 22:54:35 -07002161 sameResult, oldLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Halla440e872016-03-31 15:15:50 -07002162 if sameResult:
2163 oldLeader = oldLeaders[ 0 ][ 0 ]
2164 main.log.warn( oldLeader )
Jon Hall85794ff2015-07-08 14:12:30 -07002165 else:
Jon Halla440e872016-03-31 15:15:50 -07002166 oldLeader = None
acsmars71adceb2015-08-31 15:09:26 -07002167 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002168 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002169 actual=sameResult,
Jon Halla440e872016-03-31 15:15:50 -07002170 onpass="Leaderboards are consistent for the election topic",
acsmars71adceb2015-08-31 15:09:26 -07002171 onfail=failMessage )
2172
2173 main.step( "Find current leader and withdraw" )
2174 withdrawResult = main.TRUE
2175 # do some sanity checking on leader before using it
2176 if oldLeader is None:
2177 main.log.error( "Leadership isn't consistent." )
2178 withdrawResult = main.FALSE
2179 # Get the CLI of the oldLeader
Jon Halla440e872016-03-31 15:15:50 -07002180 for i in main.activeNodes:
acsmars71adceb2015-08-31 15:09:26 -07002181 if oldLeader == main.nodes[ i ].ip_address:
2182 oldLeaderCLI = main.CLIs[ i ]
2183 break
2184 else: # FOR/ELSE statement
2185 main.log.error( "Leader election, could not find current leader" )
Jon Hall85794ff2015-07-08 14:12:30 -07002186 if oldLeader:
acsmars71adceb2015-08-31 15:09:26 -07002187 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall85794ff2015-07-08 14:12:30 -07002188 utilities.assert_equals(
2189 expect=main.TRUE,
2190 actual=withdrawResult,
2191 onpass="Node was withdrawn from election",
2192 onfail="Node was not withdrawn from election" )
2193
acsmars71adceb2015-08-31 15:09:26 -07002194 main.step( "Check that a new node was elected leader" )
acsmars71adceb2015-08-31 15:09:26 -07002195 failMessage = "Nodes have different leaders"
acsmars71adceb2015-08-31 15:09:26 -07002196 # Get new leaders and candidates
Jon Hall41d39f12016-04-11 22:54:35 -07002197 newLeaderResult, newLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall3a7843a2016-04-12 03:01:09 -07002198 newLeader = None
Jon Halla440e872016-03-31 15:15:50 -07002199 if newLeaderResult:
Jon Hall3a7843a2016-04-12 03:01:09 -07002200 if newLeaders[ 0 ][ 0 ] == 'none':
2201 main.log.error( "No leader was elected on at least 1 node" )
2202 if not expectNoLeader:
2203 newLeaderResult = False
Jon Hall25463a82016-04-13 14:03:52 -07002204 newLeader = newLeaders[ 0 ][ 0 ]
acsmars71adceb2015-08-31 15:09:26 -07002205
2206 # Check that the new leader is not the older leader, which was withdrawn
2207 if newLeader == oldLeader:
Jon Halla440e872016-03-31 15:15:50 -07002208 newLeaderResult = False
2209 main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
acsmars71adceb2015-08-31 15:09:26 -07002210 " as the current leader" )
Jon Hall85794ff2015-07-08 14:12:30 -07002211 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002212 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002213 actual=newLeaderResult,
2214 onpass="Leadership election passed",
2215 onfail="Something went wrong with Leadership election" )
Jon Hall85794ff2015-07-08 14:12:30 -07002216
Jon Halla440e872016-03-31 15:15:50 -07002217 main.step( "Check that that new leader was the candidate of old leader" )
2218 # candidates[ 2 ] should become the top candidate after withdrawl
acsmars71adceb2015-08-31 15:09:26 -07002219 correctCandidateResult = main.TRUE
2220 if expectNoLeader:
2221 if newLeader == 'none':
2222 main.log.info( "No leader expected. None found. Pass" )
2223 correctCandidateResult = main.TRUE
2224 else:
2225 main.log.info( "Expected no leader, got: " + str( newLeader ) )
2226 correctCandidateResult = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002227 elif len( oldLeaders[0] ) >= 3:
2228 if newLeader == oldLeaders[ 0 ][ 2 ]:
2229 # correct leader was elected
2230 correctCandidateResult = main.TRUE
2231 else:
2232 correctCandidateResult = main.FALSE
2233 main.log.error( "Candidate {} was elected. {} should have had priority.".format(
2234 newLeader, oldLeaders[ 0 ][ 2 ] ) )
2235 else:
2236 main.log.warn( "Could not determine who should be the correct leader" )
2237 main.log.debug( oldLeaders[ 0 ] )
acsmars71adceb2015-08-31 15:09:26 -07002238 correctCandidateResult = main.FALSE
acsmars71adceb2015-08-31 15:09:26 -07002239 utilities.assert_equals(
2240 expect=main.TRUE,
2241 actual=correctCandidateResult,
2242 onpass="Correct Candidate Elected",
2243 onfail="Incorrect Candidate Elected" )
2244
Jon Hall85794ff2015-07-08 14:12:30 -07002245 main.step( "Run for election on old leader( just so everyone " +
2246 "is in the hat )" )
acsmars71adceb2015-08-31 15:09:26 -07002247 if oldLeaderCLI is not None:
2248 runResult = oldLeaderCLI.electionTestRun()
Jon Hall85794ff2015-07-08 14:12:30 -07002249 else:
acsmars71adceb2015-08-31 15:09:26 -07002250 main.log.error( "No old leader to re-elect" )
Jon Hall85794ff2015-07-08 14:12:30 -07002251 runResult = main.FALSE
2252 utilities.assert_equals(
2253 expect=main.TRUE,
2254 actual=runResult,
2255 onpass="App re-ran for election",
2256 onfail="App failed to run for election" )
Jon Halla440e872016-03-31 15:15:50 -07002257
acsmars71adceb2015-08-31 15:09:26 -07002258 main.step(
2259 "Check that oldLeader is a candidate, and leader if only 1 node" )
2260 # verify leader didn't just change
Jon Halla440e872016-03-31 15:15:50 -07002261 # Get new leaders and candidates
2262 reRunLeaders = []
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002263 time.sleep( 5 ) # Paremterize
Jon Hall41d39f12016-04-11 22:54:35 -07002264 positionResult, reRunLeaders = main.HA.consistentLeaderboards( activeCLIs )
acsmars71adceb2015-08-31 15:09:26 -07002265
2266 # Check that the re-elected node is last on the candidate List
Jon Hall3a7843a2016-04-12 03:01:09 -07002267 if not reRunLeaders[0]:
2268 positionResult = main.FALSE
2269 elif oldLeader != reRunLeaders[ 0 ][ -1 ]:
Jon Halla440e872016-03-31 15:15:50 -07002270 main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader),
2271 str( reRunLeaders[ 0 ] ) ) )
acsmars71adceb2015-08-31 15:09:26 -07002272 positionResult = main.FALSE
Jon Hall85794ff2015-07-08 14:12:30 -07002273 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002274 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002275 actual=positionResult,
Jon Hall85794ff2015-07-08 14:12:30 -07002276 onpass="Old leader successfully re-ran for election",
2277 onfail="Something went wrong with Leadership election after " +
2278 "the old leader re-ran for election" )
2279
2280 def CASE16( self, main ):
2281 """
2282 Install Distributed Primitives app
2283 """
Jon Halla440e872016-03-31 15:15:50 -07002284 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002285 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07002286 assert main, "main not defined"
2287 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002288 assert main.CLIs, "main.CLIs not defined"
2289 assert main.nodes, "main.nodes not defined"
Jon Hall85794ff2015-07-08 14:12:30 -07002290
2291 # Variables for the distributed primitives tests
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002292 main.pCounterName = "TestON-Partitions"
2293 main.pCounterValue = 0
2294 main.onosSet = set([])
2295 main.onosSetName = "TestON-set"
Jon Hall85794ff2015-07-08 14:12:30 -07002296
2297 description = "Install Primitives app"
2298 main.case( description )
2299 main.step( "Install Primitives app" )
2300 appName = "org.onosproject.distributedprimitives"
Jon Halla440e872016-03-31 15:15:50 -07002301 node = main.activeNodes[0]
2302 appResults = main.CLIs[node].activateApp( appName )
Jon Hall85794ff2015-07-08 14:12:30 -07002303 utilities.assert_equals( expect=main.TRUE,
2304 actual=appResults,
2305 onpass="Primitives app activated",
2306 onfail="Primitives app not activated" )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002307 # TODO check on all nodes instead of sleeping
Jon Halla440e872016-03-31 15:15:50 -07002308 time.sleep( 5 ) # To allow all nodes to activate
Jon Hall85794ff2015-07-08 14:12:30 -07002309
2310 def CASE17( self, main ):
2311 """
2312 Check for basic functionality with distributed primitives
2313 """
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002314 main.HA.CASE17( main )