blob: 8f640a113a24a7fbf81efbaa378d4e529c506687 [file] [log] [blame]
Jon Hall5cf14d52015-07-16 12:15:19 -07001"""
2Description: This test is to determine if the HA test setup is
3 working correctly. There are no failures so this test should
4 have a 100% pass rate
5
6List of test cases:
7CASE1: Compile ONOS and push it to the test machines
8CASE2: Assign devices to controllers
9CASE21: Assign mastership to controllers
10CASE3: Assign intents
11CASE4: Ping across added host intents
12CASE5: Reading state of ONOS
13CASE6: The Failure case. Since this is the Sanity test, we do nothing.
14CASE7: Check state after control plane failure
15CASE8: Compare topo
16CASE9: Link s3-s28 down
17CASE10: Link s3-s28 up
18CASE11: Switch down
19CASE12: Switch up
20CASE13: Clean up
21CASE14: start election app on all onos nodes
22CASE15: Check that Leadership Election is still functional
23CASE16: Install Distributed Primitives app
24CASE17: Check for basic functionality with distributed primitives
25"""
Jon Hall5cf14d52015-07-16 12:15:19 -070026class HAsanity:
27
28 def __init__( self ):
29 self.default = ''
30
31 def CASE1( self, main ):
32 """
33 CASE1 is to compile ONOS and push it to the test machines
34
35 Startup sequence:
36 cell <name>
37 onos-verify-cell
38 NOTE: temporary - onos-remove-raft-logs
39 onos-uninstall
40 start mininet
41 git pull
42 mvn clean install
43 onos-package
44 onos-install -f
45 onos-wait-for-start
46 start cli sessions
47 start tcpdump
48 """
Jon Halle1a3b752015-07-22 13:02:46 -070049 import imp
Jon Hallf3d16e72015-12-16 17:45:08 -080050 import time
Jon Halla440e872016-03-31 15:15:50 -070051 import json
Jon Hall5cf14d52015-07-16 12:15:19 -070052 main.log.info( "ONOS HA Sanity test - initialization" )
53 main.case( "Setting up test environment" )
Jon Hall783bbf92015-07-23 14:33:19 -070054 main.caseExplanation = "Setup the test environment including " +\
Jon Hall5cf14d52015-07-16 12:15:19 -070055 "installing ONOS, starting Mininet and ONOS" +\
56 "cli sessions."
Jon Hall5cf14d52015-07-16 12:15:19 -070057
58 # load some variables from the params file
59 PULLCODE = False
60 if main.params[ 'Git' ] == 'True':
61 PULLCODE = True
62 gitBranch = main.params[ 'branch' ]
63 cellName = main.params[ 'ENV' ][ 'cellName' ]
64
Jon Halle1a3b752015-07-22 13:02:46 -070065 main.numCtrls = int( main.params[ 'num_controllers' ] )
Jon Hall5cf14d52015-07-16 12:15:19 -070066 if main.ONOSbench.maxNodes:
Jon Halle1a3b752015-07-22 13:02:46 -070067 if main.ONOSbench.maxNodes < main.numCtrls:
68 main.numCtrls = int( main.ONOSbench.maxNodes )
Jon Hall5cf14d52015-07-16 12:15:19 -070069 # TODO: refactor how to get onos port, maybe put into component tag?
Jon Halle1a3b752015-07-22 13:02:46 -070070 # set global variables
Jon Hall5cf14d52015-07-16 12:15:19 -070071 global ONOS1Port
72 global ONOS2Port
73 global ONOS3Port
74 global ONOS4Port
75 global ONOS5Port
76 global ONOS6Port
77 global ONOS7Port
Jon Halla440e872016-03-31 15:15:50 -070078 # These are for csv plotting in jenkins
79 global labels
80 global data
81 labels = []
82 data = []
Jon Hall5cf14d52015-07-16 12:15:19 -070083
84 # FIXME: just get controller port from params?
85 # TODO: do we really need all these?
86 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
87 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
88 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
89 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
90 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
91 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
92 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
93
Jon Halle1a3b752015-07-22 13:02:46 -070094 try:
Jon Hall53c5e662016-04-13 16:06:56 -070095 from tests.HA.dependencies.HA import HA
Jon Hall41d39f12016-04-11 22:54:35 -070096 main.HA = HA()
Jon Halle1a3b752015-07-22 13:02:46 -070097 except Exception as e:
98 main.log.exception( e )
99 main.cleanup()
100 main.exit()
101
102 main.CLIs = []
103 main.nodes = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700104 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700105 for i in range( 1, main.numCtrls + 1 ):
106 try:
107 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
108 main.nodes.append( getattr( main, 'ONOS' + str( i ) ) )
109 ipList.append( main.nodes[ -1 ].ip_address )
110 except AttributeError:
111 break
Jon Hall5cf14d52015-07-16 12:15:19 -0700112
113 main.step( "Create cell file" )
114 cellAppString = main.params[ 'ENV' ][ 'appString' ]
115 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
116 main.Mininet1.ip_address,
117 cellAppString, ipList )
118 main.step( "Applying cell variable to environment" )
119 cellResult = main.ONOSbench.setCell( cellName )
120 verifyResult = main.ONOSbench.verifyCell()
121
122 # FIXME:this is short term fix
123 main.log.info( "Removing raft logs" )
124 main.ONOSbench.onosRemoveRaftLogs()
125
126 main.log.info( "Uninstalling ONOS" )
Jon Halle1a3b752015-07-22 13:02:46 -0700127 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700128 main.ONOSbench.onosUninstall( node.ip_address )
129
130 # Make sure ONOS is DEAD
131 main.log.info( "Killing any ONOS processes" )
132 killResults = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700133 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700134 killed = main.ONOSbench.onosKill( node.ip_address )
135 killResults = killResults and killed
136
137 cleanInstallResult = main.TRUE
138 gitPullResult = main.TRUE
139
140 main.step( "Starting Mininet" )
141 # scp topo file to mininet
142 # TODO: move to params?
143 topoName = "obelisk.py"
144 filePath = main.ONOSbench.home + "/tools/test/topos/"
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700145 main.ONOSbench.scp( main.Mininet1,
146 filePath + topoName,
147 main.Mininet1.home,
148 direction="to" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700149 mnResult = main.Mininet1.startNet()
Jon Hall5cf14d52015-07-16 12:15:19 -0700150 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
151 onpass="Mininet Started",
152 onfail="Error starting Mininet" )
153
154 main.step( "Git checkout and pull " + gitBranch )
155 if PULLCODE:
156 main.ONOSbench.gitCheckout( gitBranch )
157 gitPullResult = main.ONOSbench.gitPull()
158 # values of 1 or 3 are good
159 utilities.assert_lesser( expect=0, actual=gitPullResult,
160 onpass="Git pull successful",
161 onfail="Git pull failed" )
162 main.ONOSbench.getVersion( report=True )
163
164 main.step( "Using mvn clean install" )
165 cleanInstallResult = main.TRUE
166 if PULLCODE and gitPullResult == main.TRUE:
167 cleanInstallResult = main.ONOSbench.cleanInstall()
168 else:
169 main.log.warn( "Did not pull new code so skipping mvn " +
170 "clean install" )
171 utilities.assert_equals( expect=main.TRUE,
172 actual=cleanInstallResult,
173 onpass="MCI successful",
174 onfail="MCI failed" )
175 # GRAPHS
176 # NOTE: important params here:
177 # job = name of Jenkins job
178 # Plot Name = Plot-HA, only can be used if multiple plots
179 # index = The number of the graph under plot name
180 job = "HAsanity"
181 plotName = "Plot-HA"
Jon Hall843f8bc2016-03-18 14:28:13 -0700182 index = "2"
Jon Hall5cf14d52015-07-16 12:15:19 -0700183 graphs = '<ac:structured-macro ac:name="html">\n'
184 graphs += '<ac:plain-text-body><![CDATA[\n'
185 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Halla9845df2016-01-15 14:55:58 -0800186 '/plot/' + plotName + '/getPlot?index=' + index +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700187 '&width=500&height=300"' +\
188 'noborder="0" width="500" height="300" scrolling="yes" ' +\
189 'seamless="seamless"></iframe>\n'
190 graphs += ']]></ac:plain-text-body>\n'
191 graphs += '</ac:structured-macro>\n'
Jon Hallf37d44d2017-05-24 10:37:30 -0700192 main.log.wiki( graphs )
Jon Hall5cf14d52015-07-16 12:15:19 -0700193
194 main.step( "Creating ONOS package" )
Jon Hallbd60ea02016-08-23 10:03:59 -0700195 packageResult = main.ONOSbench.buckBuild()
Jon Hall5cf14d52015-07-16 12:15:19 -0700196 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
197 onpass="ONOS package successful",
198 onfail="ONOS package failed" )
199
200 main.step( "Installing ONOS package" )
201 onosInstallResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700202 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700203 tmpResult = main.ONOSbench.onosInstall( options="-f",
204 node=node.ip_address )
205 onosInstallResult = onosInstallResult and tmpResult
206 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
207 onpass="ONOS install successful",
208 onfail="ONOS install failed" )
209
You Wangf5de25b2017-01-06 15:13:01 -0800210 main.step( "Set up ONOS secure SSH" )
211 secureSshResult = main.TRUE
212 for node in main.nodes:
213 secureSshResult = secureSshResult and main.ONOSbench.onosSecureSSH( node=node.ip_address )
214 utilities.assert_equals( expect=main.TRUE, actual=secureSshResult,
215 onpass="Test step PASS",
216 onfail="Test step FAIL" )
217
Jon Hall5cf14d52015-07-16 12:15:19 -0700218 main.step( "Checking if ONOS is up yet" )
219 for i in range( 2 ):
220 onosIsupResult = main.TRUE
Jon Halle1a3b752015-07-22 13:02:46 -0700221 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700222 started = main.ONOSbench.isup( node.ip_address )
223 if not started:
Jon Hallc6793552016-01-19 14:18:37 -0800224 main.log.error( node.name + " hasn't started" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700225 onosIsupResult = onosIsupResult and started
226 if onosIsupResult == main.TRUE:
227 break
228 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
229 onpass="ONOS startup successful",
230 onfail="ONOS startup failed" )
231
Jon Hall6509dbf2016-06-21 17:01:17 -0700232 main.step( "Starting ONOS CLI sessions" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700233 cliResults = main.TRUE
234 threads = []
Jon Halle1a3b752015-07-22 13:02:46 -0700235 for i in range( main.numCtrls ):
Jon Hallf37d44d2017-05-24 10:37:30 -0700236 t = main.Thread( target=main.CLIs[ i ].startOnosCli,
Jon Hall5cf14d52015-07-16 12:15:19 -0700237 name="startOnosCli-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -0700238 args=[ main.nodes[ i ].ip_address ] )
Jon Hall5cf14d52015-07-16 12:15:19 -0700239 threads.append( t )
240 t.start()
241
242 for t in threads:
243 t.join()
244 cliResults = cliResults and t.result
245 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
246 onpass="ONOS cli startup successful",
247 onfail="ONOS cli startup failed" )
248
Jon Halla440e872016-03-31 15:15:50 -0700249 # Create a list of active nodes for use when some nodes are stopped
250 main.activeNodes = [ i for i in range( 0, len( main.CLIs ) ) ]
251
Jon Hall5cf14d52015-07-16 12:15:19 -0700252 if main.params[ 'tcpdump' ].lower() == "true":
253 main.step( "Start Packet Capture MN" )
254 main.Mininet2.startTcpdump(
255 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
256 + "-MN.pcap",
257 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
258 port=main.params[ 'MNtcpdump' ][ 'port' ] )
259
Jon Halla440e872016-03-31 15:15:50 -0700260 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -0700261 nodeResults = utilities.retry( main.HA.nodesCheck,
262 False,
Jon Hallf37d44d2017-05-24 10:37:30 -0700263 args=[ main.activeNodes ],
Jon Hall41d39f12016-04-11 22:54:35 -0700264 attempts=5 )
Jon Halla440e872016-03-31 15:15:50 -0700265
Jon Hall41d39f12016-04-11 22:54:35 -0700266 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Halla440e872016-03-31 15:15:50 -0700267 onpass="Nodes check successful",
268 onfail="Nodes check NOT successful" )
269
270 if not nodeResults:
Jon Hall7ac7bc32016-05-05 10:57:02 -0700271 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700272 cli = main.CLIs[ i ]
Jon Halla440e872016-03-31 15:15:50 -0700273 main.log.debug( "{} components not ACTIVE: \n{}".format(
274 cli.name,
275 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700276 main.log.error( "Failed to start ONOS, stopping test" )
277 main.cleanup()
278 main.exit()
279
Jon Hall172b7ba2016-04-07 18:12:20 -0700280 main.step( "Activate apps defined in the params file" )
281 # get data from the params
282 apps = main.params.get( 'apps' )
283 if apps:
Jon Hallf37d44d2017-05-24 10:37:30 -0700284 apps = apps.split( ',' )
Jon Hall172b7ba2016-04-07 18:12:20 -0700285 main.log.warn( apps )
286 activateResult = True
287 for app in apps:
288 main.CLIs[ 0 ].app( app, "Activate" )
289 # TODO: check this worked
290 time.sleep( 10 ) # wait for apps to activate
291 for app in apps:
292 state = main.CLIs[ 0 ].appStatus( app )
293 if state == "ACTIVE":
Jon Hall937bc812017-01-31 16:44:10 -0800294 activateResult = activateResult and True
Jon Hall172b7ba2016-04-07 18:12:20 -0700295 else:
296 main.log.error( "{} is in {} state".format( app, state ) )
Jon Hall937bc812017-01-31 16:44:10 -0800297 activateResult = False
Jon Hall172b7ba2016-04-07 18:12:20 -0700298 utilities.assert_equals( expect=True,
299 actual=activateResult,
300 onpass="Successfully activated apps",
301 onfail="Failed to activate apps" )
302 else:
303 main.log.warn( "No apps were specified to be loaded after startup" )
304
305 main.step( "Set ONOS configurations" )
306 config = main.params.get( 'ONOS_Configuration' )
307 if config:
308 main.log.debug( config )
309 checkResult = main.TRUE
310 for component in config:
Jon Hallf37d44d2017-05-24 10:37:30 -0700311 for setting in config[ component ]:
312 value = config[ component ][ setting ]
Jon Hall172b7ba2016-04-07 18:12:20 -0700313 check = main.CLIs[ 0 ].setCfg( component, setting, value )
314 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
315 checkResult = check and checkResult
316 utilities.assert_equals( expect=main.TRUE,
317 actual=checkResult,
318 onpass="Successfully set config",
319 onfail="Failed to set config" )
320 else:
321 main.log.warn( "No configurations were specified to be changed after startup" )
322
Jon Hall9d2dcad2016-04-08 10:15:20 -0700323 main.step( "App Ids check" )
324 appCheck = main.TRUE
325 threads = []
326 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700327 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall9d2dcad2016-04-08 10:15:20 -0700328 name="appToIDCheck-" + str( i ),
329 args=[] )
330 threads.append( t )
331 t.start()
332
333 for t in threads:
334 t.join()
335 appCheck = appCheck and t.result
336 if appCheck != main.TRUE:
Jon Hallf37d44d2017-05-24 10:37:30 -0700337 node = main.activeNodes[ 0 ]
338 main.log.warn( main.CLIs[ node ].apps() )
339 main.log.warn( main.CLIs[ node ].appIDs() )
Jon Hall9d2dcad2016-04-08 10:15:20 -0700340 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
341 onpass="App Ids seem to be correct",
342 onfail="Something is wrong with app Ids" )
343
Jon Hall5cf14d52015-07-16 12:15:19 -0700344 def CASE2( self, main ):
345 """
346 Assign devices to controllers
347 """
348 import re
Jon Halle1a3b752015-07-22 13:02:46 -0700349 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700350 assert main, "main not defined"
351 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700352 assert main.CLIs, "main.CLIs not defined"
353 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700354 assert ONOS1Port, "ONOS1Port not defined"
355 assert ONOS2Port, "ONOS2Port not defined"
356 assert ONOS3Port, "ONOS3Port not defined"
357 assert ONOS4Port, "ONOS4Port not defined"
358 assert ONOS5Port, "ONOS5Port not defined"
359 assert ONOS6Port, "ONOS6Port not defined"
360 assert ONOS7Port, "ONOS7Port not defined"
361
362 main.case( "Assigning devices to controllers" )
Jon Hall783bbf92015-07-23 14:33:19 -0700363 main.caseExplanation = "Assign switches to ONOS using 'ovs-vsctl' " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700364 "and check that an ONOS node becomes the " +\
365 "master of the device."
366 main.step( "Assign switches to controllers" )
367
368 ipList = []
Jon Halle1a3b752015-07-22 13:02:46 -0700369 for i in range( main.numCtrls ):
370 ipList.append( main.nodes[ i ].ip_address )
Jon Hall5cf14d52015-07-16 12:15:19 -0700371 swList = []
372 for i in range( 1, 29 ):
373 swList.append( "s" + str( i ) )
374 main.Mininet1.assignSwController( sw=swList, ip=ipList )
375
376 mastershipCheck = main.TRUE
377 for i in range( 1, 29 ):
378 response = main.Mininet1.getSwController( "s" + str( i ) )
379 try:
380 main.log.info( str( response ) )
381 except Exception:
382 main.log.info( repr( response ) )
Jon Halle1a3b752015-07-22 13:02:46 -0700383 for node in main.nodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700384 if re.search( "tcp:" + node.ip_address, response ):
385 mastershipCheck = mastershipCheck and main.TRUE
386 else:
387 main.log.error( "Error, node " + node.ip_address + " is " +
388 "not in the list of controllers s" +
389 str( i ) + " is connecting to." )
390 mastershipCheck = main.FALSE
391 utilities.assert_equals(
392 expect=main.TRUE,
393 actual=mastershipCheck,
394 onpass="Switch mastership assigned correctly",
395 onfail="Switches not assigned correctly to controllers" )
396
397 def CASE21( self, main ):
398 """
399 Assign mastership to controllers
400 """
Jon Hall5cf14d52015-07-16 12:15:19 -0700401 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700402 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700403 assert main, "main not defined"
404 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700405 assert main.CLIs, "main.CLIs not defined"
406 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700407 assert ONOS1Port, "ONOS1Port not defined"
408 assert ONOS2Port, "ONOS2Port not defined"
409 assert ONOS3Port, "ONOS3Port not defined"
410 assert ONOS4Port, "ONOS4Port not defined"
411 assert ONOS5Port, "ONOS5Port not defined"
412 assert ONOS6Port, "ONOS6Port not defined"
413 assert ONOS7Port, "ONOS7Port not defined"
414
415 main.case( "Assigning Controller roles for switches" )
Jon Hall783bbf92015-07-23 14:33:19 -0700416 main.caseExplanation = "Check that ONOS is connected to each " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700417 "device. Then manually assign" +\
418 " mastership to specific ONOS nodes using" +\
419 " 'device-role'"
420 main.step( "Assign mastership of switches to specific controllers" )
421 # Manually assign mastership to the controller we want
422 roleCall = main.TRUE
423
Jon Hallf37d44d2017-05-24 10:37:30 -0700424 ipList = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700425 deviceList = []
Jon Hallf37d44d2017-05-24 10:37:30 -0700426 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700427 try:
428 # Assign mastership to specific controllers. This assignment was
429 # determined for a 7 node cluser, but will work with any sized
430 # cluster
431 for i in range( 1, 29 ): # switches 1 through 28
432 # set up correct variables:
433 if i == 1:
434 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700435 ip = main.nodes[ c ].ip_address # ONOS1
Jon Halla440e872016-03-31 15:15:50 -0700436 deviceId = onosCli.getDevice( "1000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700437 elif i == 2:
Jon Halle1a3b752015-07-22 13:02:46 -0700438 c = 1 % main.numCtrls
439 ip = main.nodes[ c ].ip_address # ONOS2
Jon Halla440e872016-03-31 15:15:50 -0700440 deviceId = onosCli.getDevice( "2000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700441 elif i == 3:
Jon Halle1a3b752015-07-22 13:02:46 -0700442 c = 1 % main.numCtrls
443 ip = main.nodes[ c ].ip_address # ONOS2
Jon Halla440e872016-03-31 15:15:50 -0700444 deviceId = onosCli.getDevice( "3000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700445 elif i == 4:
Jon Halle1a3b752015-07-22 13:02:46 -0700446 c = 3 % main.numCtrls
447 ip = main.nodes[ c ].ip_address # ONOS4
Jon Halla440e872016-03-31 15:15:50 -0700448 deviceId = onosCli.getDevice( "3004" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700449 elif i == 5:
Jon Halle1a3b752015-07-22 13:02:46 -0700450 c = 2 % main.numCtrls
451 ip = main.nodes[ c ].ip_address # ONOS3
Jon Halla440e872016-03-31 15:15:50 -0700452 deviceId = onosCli.getDevice( "5000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700453 elif i == 6:
Jon Halle1a3b752015-07-22 13:02:46 -0700454 c = 2 % main.numCtrls
455 ip = main.nodes[ c ].ip_address # ONOS3
Jon Halla440e872016-03-31 15:15:50 -0700456 deviceId = onosCli.getDevice( "6000" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700457 elif i == 7:
Jon Halle1a3b752015-07-22 13:02:46 -0700458 c = 5 % main.numCtrls
459 ip = main.nodes[ c ].ip_address # ONOS6
Jon Halla440e872016-03-31 15:15:50 -0700460 deviceId = onosCli.getDevice( "6007" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700461 elif i >= 8 and i <= 17:
Jon Halle1a3b752015-07-22 13:02:46 -0700462 c = 4 % main.numCtrls
463 ip = main.nodes[ c ].ip_address # ONOS5
Jon Hall5cf14d52015-07-16 12:15:19 -0700464 dpid = '3' + str( i ).zfill( 3 )
Jon Halla440e872016-03-31 15:15:50 -0700465 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700466 elif i >= 18 and i <= 27:
Jon Halle1a3b752015-07-22 13:02:46 -0700467 c = 6 % main.numCtrls
468 ip = main.nodes[ c ].ip_address # ONOS7
Jon Hall5cf14d52015-07-16 12:15:19 -0700469 dpid = '6' + str( i ).zfill( 3 )
Jon Halla440e872016-03-31 15:15:50 -0700470 deviceId = onosCli.getDevice( dpid ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700471 elif i == 28:
472 c = 0
Jon Halle1a3b752015-07-22 13:02:46 -0700473 ip = main.nodes[ c ].ip_address # ONOS1
Jon Halla440e872016-03-31 15:15:50 -0700474 deviceId = onosCli.getDevice( "2800" ).get( 'id' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700475 else:
476 main.log.error( "You didn't write an else statement for " +
477 "switch s" + str( i ) )
478 roleCall = main.FALSE
479 # Assign switch
480 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
481 # TODO: make this controller dynamic
Jon Halla440e872016-03-31 15:15:50 -0700482 roleCall = roleCall and onosCli.deviceRole( deviceId, ip )
Jon Hall5cf14d52015-07-16 12:15:19 -0700483 ipList.append( ip )
484 deviceList.append( deviceId )
485 except ( AttributeError, AssertionError ):
486 main.log.exception( "Something is wrong with ONOS device view" )
Jon Halla440e872016-03-31 15:15:50 -0700487 main.log.info( onosCli.devices() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700488 utilities.assert_equals(
489 expect=main.TRUE,
490 actual=roleCall,
491 onpass="Re-assigned switch mastership to designated controller",
492 onfail="Something wrong with deviceRole calls" )
493
494 main.step( "Check mastership was correctly assigned" )
495 roleCheck = main.TRUE
496 # NOTE: This is due to the fact that device mastership change is not
497 # atomic and is actually a multi step process
498 time.sleep( 5 )
499 for i in range( len( ipList ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -0700500 ip = ipList[ i ]
501 deviceId = deviceList[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700502 # Check assignment
Jon Halla440e872016-03-31 15:15:50 -0700503 master = onosCli.getRole( deviceId ).get( 'master' )
Jon Hall5cf14d52015-07-16 12:15:19 -0700504 if ip in master:
505 roleCheck = roleCheck and main.TRUE
506 else:
507 roleCheck = roleCheck and main.FALSE
508 main.log.error( "Error, controller " + ip + " is not" +
509 " master " + "of device " +
510 str( deviceId ) + ". Master is " +
511 repr( master ) + "." )
512 utilities.assert_equals(
513 expect=main.TRUE,
514 actual=roleCheck,
515 onpass="Switches were successfully reassigned to designated " +
516 "controller",
517 onfail="Switches were not successfully reassigned" )
518
519 def CASE3( self, main ):
520 """
521 Assign intents
522 """
523 import time
524 import json
Jon Halle1a3b752015-07-22 13:02:46 -0700525 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700526 assert main, "main not defined"
527 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700528 assert main.CLIs, "main.CLIs not defined"
529 assert main.nodes, "main.nodes not defined"
Jon Halla440e872016-03-31 15:15:50 -0700530 try:
531 labels
532 except NameError:
533 main.log.error( "labels not defined, setting to []" )
534 labels = []
535 try:
536 data
537 except NameError:
538 main.log.error( "data not defined, setting to []" )
539 data = []
Jon Hall5cf14d52015-07-16 12:15:19 -0700540 main.case( "Adding host Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700541 main.caseExplanation = "Discover hosts by using pingall then " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700542 "assign predetermined host-to-host intents." +\
543 " After installation, check that the intent" +\
544 " is distributed to all nodes and the state" +\
545 " is INSTALLED"
546
547 # install onos-app-fwd
548 main.step( "Install reactive forwarding app" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700549 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Halla440e872016-03-31 15:15:50 -0700550 installResults = onosCli.activateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700551 utilities.assert_equals( expect=main.TRUE, actual=installResults,
552 onpass="Install fwd successful",
553 onfail="Install fwd failed" )
554
555 main.step( "Check app ids" )
556 appCheck = main.TRUE
557 threads = []
Jon Halla440e872016-03-31 15:15:50 -0700558 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700559 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700560 name="appToIDCheck-" + str( i ),
561 args=[] )
562 threads.append( t )
563 t.start()
564
565 for t in threads:
566 t.join()
567 appCheck = appCheck and t.result
568 if appCheck != main.TRUE:
Jon Halla440e872016-03-31 15:15:50 -0700569 main.log.warn( onosCli.apps() )
570 main.log.warn( onosCli.appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700571 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
572 onpass="App Ids seem to be correct",
573 onfail="Something is wrong with app Ids" )
574
575 main.step( "Discovering Hosts( Via pingall for now )" )
576 # FIXME: Once we have a host discovery mechanism, use that instead
577 # REACTIVE FWD test
578 pingResult = main.FALSE
Jon Hall96091e62015-09-21 17:34:17 -0700579 passMsg = "Reactive Pingall test passed"
580 time1 = time.time()
581 pingResult = main.Mininet1.pingall()
582 time2 = time.time()
583 if not pingResult:
Jon Hallf37d44d2017-05-24 10:37:30 -0700584 main.log.warn( "First pingall failed. Trying again..." )
Jon Hall5cf14d52015-07-16 12:15:19 -0700585 pingResult = main.Mininet1.pingall()
Jon Hall96091e62015-09-21 17:34:17 -0700586 passMsg += " on the second try"
587 utilities.assert_equals(
588 expect=main.TRUE,
589 actual=pingResult,
Jon Hallf37d44d2017-05-24 10:37:30 -0700590 onpass=passMsg,
Jon Hall96091e62015-09-21 17:34:17 -0700591 onfail="Reactive Pingall failed, " +
592 "one or more ping pairs failed" )
593 main.log.info( "Time for pingall: %2f seconds" %
594 ( time2 - time1 ) )
Jon Halld2871c22016-07-26 11:01:14 -0700595 if not pingResult:
596 main.cleanup()
597 main.exit()
Jon Hall5cf14d52015-07-16 12:15:19 -0700598 # timeout for fwd flows
599 time.sleep( 11 )
600 # uninstall onos-app-fwd
601 main.step( "Uninstall reactive forwarding app" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700602 node = main.activeNodes[ 0 ]
603 uninstallResult = main.CLIs[ node ].deactivateApp( "org.onosproject.fwd" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700604 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
605 onpass="Uninstall fwd successful",
606 onfail="Uninstall fwd failed" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700607
608 main.step( "Check app ids" )
609 threads = []
610 appCheck2 = main.TRUE
Jon Halla440e872016-03-31 15:15:50 -0700611 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700612 t = main.Thread( target=main.CLIs[ i ].appToIDCheck,
Jon Hall5cf14d52015-07-16 12:15:19 -0700613 name="appToIDCheck-" + str( i ),
614 args=[] )
615 threads.append( t )
616 t.start()
617
618 for t in threads:
619 t.join()
620 appCheck2 = appCheck2 and t.result
621 if appCheck2 != main.TRUE:
Jon Hallf37d44d2017-05-24 10:37:30 -0700622 node = main.activeNodes[ 0 ]
623 main.log.warn( main.CLIs[ node ].apps() )
624 main.log.warn( main.CLIs[ node ].appIDs() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700625 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
626 onpass="App Ids seem to be correct",
627 onfail="Something is wrong with app Ids" )
628
629 main.step( "Add host intents via cli" )
630 intentIds = []
Jon Hall6e709752016-02-01 13:38:46 -0800631 # TODO: move the host numbers to params
632 # Maybe look at all the paths we ping?
Jon Hall5cf14d52015-07-16 12:15:19 -0700633 intentAddResult = True
634 hostResult = main.TRUE
635 for i in range( 8, 18 ):
636 main.log.info( "Adding host intent between h" + str( i ) +
637 " and h" + str( i + 10 ) )
638 host1 = "00:00:00:00:00:" + \
639 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
640 host2 = "00:00:00:00:00:" + \
641 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
642 # NOTE: getHost can return None
Jon Halla440e872016-03-31 15:15:50 -0700643 host1Dict = onosCli.getHost( host1 )
644 host2Dict = onosCli.getHost( host2 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700645 host1Id = None
646 host2Id = None
647 if host1Dict and host2Dict:
648 host1Id = host1Dict.get( 'id', None )
649 host2Id = host2Dict.get( 'id', None )
650 if host1Id and host2Id:
Jon Halla440e872016-03-31 15:15:50 -0700651 nodeNum = ( i % len( main.activeNodes ) )
Jon Hallf37d44d2017-05-24 10:37:30 -0700652 node = main.activeNodes[ nodeNum ]
653 tmpId = main.CLIs[ node ].addHostIntent( host1Id, host2Id )
Jon Hall5cf14d52015-07-16 12:15:19 -0700654 if tmpId:
655 main.log.info( "Added intent with id: " + tmpId )
656 intentIds.append( tmpId )
657 else:
658 main.log.error( "addHostIntent returned: " +
659 repr( tmpId ) )
660 else:
661 main.log.error( "Error, getHost() failed for h" + str( i ) +
662 " and/or h" + str( i + 10 ) )
Jon Hallf37d44d2017-05-24 10:37:30 -0700663 node = main.activeNodes[ 0 ]
664 hosts = main.CLIs[ node ].hosts()
Jon Hall5cf14d52015-07-16 12:15:19 -0700665 main.log.warn( "Hosts output: " )
666 try:
667 main.log.warn( json.dumps( json.loads( hosts ),
668 sort_keys=True,
669 indent=4,
670 separators=( ',', ': ' ) ) )
671 except ( ValueError, TypeError ):
672 main.log.warn( repr( hosts ) )
673 hostResult = main.FALSE
674 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
675 onpass="Found a host id for each host",
676 onfail="Error looking up host ids" )
677
678 intentStart = time.time()
Jon Halla440e872016-03-31 15:15:50 -0700679 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700680 main.log.info( "Submitted intents: " + str( intentIds ) )
681 main.log.info( "Intents in ONOS: " + str( onosIds ) )
682 for intent in intentIds:
683 if intent in onosIds:
684 pass # intent submitted is in onos
685 else:
686 intentAddResult = False
687 if intentAddResult:
688 intentStop = time.time()
689 else:
690 intentStop = None
691 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -0700692 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700693 intentStates = []
694 installedCheck = True
695 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
696 count = 0
697 try:
698 for intent in json.loads( intents ):
699 state = intent.get( 'state', None )
700 if "INSTALLED" not in state:
701 installedCheck = False
702 intentId = intent.get( 'id', None )
703 intentStates.append( ( intentId, state ) )
704 except ( ValueError, TypeError ):
705 main.log.exception( "Error parsing intents" )
706 # add submitted intents not in the store
707 tmplist = [ i for i, s in intentStates ]
708 missingIntents = False
709 for i in intentIds:
710 if i not in tmplist:
711 intentStates.append( ( i, " - " ) )
712 missingIntents = True
713 intentStates.sort()
714 for i, s in intentStates:
715 count += 1
716 main.log.info( "%-6s%-15s%-15s" %
717 ( str( count ), str( i ), str( s ) ) )
Jon Halla440e872016-03-31 15:15:50 -0700718 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700719 try:
720 missing = False
721 if leaders:
722 parsedLeaders = json.loads( leaders )
723 main.log.warn( json.dumps( parsedLeaders,
724 sort_keys=True,
725 indent=4,
726 separators=( ',', ': ' ) ) )
727 # check for all intent partitions
728 topics = []
729 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700730 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700731 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -0700732 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700733 for topic in topics:
734 if topic not in ONOStopics:
735 main.log.error( "Error: " + topic +
736 " not in leaders" )
737 missing = True
738 else:
739 main.log.error( "leaders() returned None" )
740 except ( ValueError, TypeError ):
741 main.log.exception( "Error parsing leaders" )
742 main.log.error( repr( leaders ) )
743 # Check all nodes
744 if missing:
Jon Halla440e872016-03-31 15:15:50 -0700745 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700746 response = main.CLIs[ i ].leaders( jsonFormat=False )
747 main.log.warn( str( main.CLIs[ i ].name ) + " leaders output: \n" +
Jon Hall5cf14d52015-07-16 12:15:19 -0700748 str( response ) )
749
Jon Halla440e872016-03-31 15:15:50 -0700750 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700751 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700752 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -0700753 parsedPartitions = json.loads( partitions )
754 main.log.warn( json.dumps( parsedPartitions,
755 sort_keys=True,
756 indent=4,
757 separators=( ',', ': ' ) ) )
758 # TODO check for a leader in all paritions
759 # TODO check for consistency among nodes
760 else:
761 main.log.error( "partitions() returned None" )
762 except ( ValueError, TypeError ):
763 main.log.exception( "Error parsing partitions" )
764 main.log.error( repr( partitions ) )
Jon Halla440e872016-03-31 15:15:50 -0700765 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700766 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700767 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -0700768 parsedPending = json.loads( pendingMap )
769 main.log.warn( json.dumps( parsedPending,
770 sort_keys=True,
771 indent=4,
772 separators=( ',', ': ' ) ) )
773 # TODO check something here?
774 else:
775 main.log.error( "pendingMap() returned None" )
776 except ( ValueError, TypeError ):
777 main.log.exception( "Error parsing pending map" )
778 main.log.error( repr( pendingMap ) )
779
780 intentAddResult = bool( intentAddResult and not missingIntents and
781 installedCheck )
782 if not intentAddResult:
783 main.log.error( "Error in pushing host intents to ONOS" )
784
785 main.step( "Intent Anti-Entropy dispersion" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700786 for j in range( 100 ):
Jon Hall5cf14d52015-07-16 12:15:19 -0700787 correct = True
788 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Halla440e872016-03-31 15:15:50 -0700789 for i in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -0700790 onosIds = []
Jon Hallf37d44d2017-05-24 10:37:30 -0700791 ids = main.CLIs[ i ].getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700792 onosIds.append( ids )
Jon Hallf37d44d2017-05-24 10:37:30 -0700793 main.log.debug( "Intents in " + main.CLIs[ i ].name + ": " +
Jon Hall5cf14d52015-07-16 12:15:19 -0700794 str( sorted( onosIds ) ) )
795 if sorted( ids ) != sorted( intentIds ):
796 main.log.warn( "Set of intent IDs doesn't match" )
797 correct = False
798 break
799 else:
Jon Hallf37d44d2017-05-24 10:37:30 -0700800 intents = json.loads( main.CLIs[ i ].intents() )
Jon Hall5cf14d52015-07-16 12:15:19 -0700801 for intent in intents:
802 if intent[ 'state' ] != "INSTALLED":
803 main.log.warn( "Intent " + intent[ 'id' ] +
804 " is " + intent[ 'state' ] )
805 correct = False
806 break
807 if correct:
808 break
809 else:
Jon Hallf37d44d2017-05-24 10:37:30 -0700810 time.sleep( 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -0700811 if not intentStop:
812 intentStop = time.time()
813 global gossipTime
814 gossipTime = intentStop - intentStart
815 main.log.info( "It took about " + str( gossipTime ) +
816 " seconds for all intents to appear in each node" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700817 gossipPeriod = int( main.params[ 'timers' ][ 'gossip' ] )
Jon Halla440e872016-03-31 15:15:50 -0700818 maxGossipTime = gossipPeriod * len( main.activeNodes )
Jon Hall5cf14d52015-07-16 12:15:19 -0700819 utilities.assert_greater_equals(
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700820 expect=maxGossipTime, actual=gossipTime,
Jon Hall5cf14d52015-07-16 12:15:19 -0700821 onpass="ECM anti-entropy for intents worked within " +
822 "expected time",
Jon Hallb3ed8ed2015-10-28 16:43:55 -0700823 onfail="Intent ECM anti-entropy took too long. " +
824 "Expected time:{}, Actual time:{}".format( maxGossipTime,
825 gossipTime ) )
826 if gossipTime <= maxGossipTime:
Jon Hall5cf14d52015-07-16 12:15:19 -0700827 intentAddResult = True
828
829 if not intentAddResult or "key" in pendingMap:
830 import time
831 installedCheck = True
832 main.log.info( "Sleeping 60 seconds to see if intents are found" )
833 time.sleep( 60 )
Jon Halla440e872016-03-31 15:15:50 -0700834 onosIds = onosCli.getAllIntentsId()
Jon Hall5cf14d52015-07-16 12:15:19 -0700835 main.log.info( "Submitted intents: " + str( intentIds ) )
836 main.log.info( "Intents in ONOS: " + str( onosIds ) )
837 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -0700838 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700839 intentStates = []
840 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
841 count = 0
842 try:
843 for intent in json.loads( intents ):
844 # Iter through intents of a node
845 state = intent.get( 'state', None )
846 if "INSTALLED" not in state:
847 installedCheck = False
848 intentId = intent.get( 'id', None )
849 intentStates.append( ( intentId, state ) )
850 except ( ValueError, TypeError ):
851 main.log.exception( "Error parsing intents" )
852 # add submitted intents not in the store
853 tmplist = [ i for i, s in intentStates ]
854 for i in intentIds:
855 if i not in tmplist:
856 intentStates.append( ( i, " - " ) )
857 intentStates.sort()
858 for i, s in intentStates:
859 count += 1
860 main.log.info( "%-6s%-15s%-15s" %
861 ( str( count ), str( i ), str( s ) ) )
Jon Halla440e872016-03-31 15:15:50 -0700862 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -0700863 try:
864 missing = False
865 if leaders:
866 parsedLeaders = json.loads( leaders )
867 main.log.warn( json.dumps( parsedLeaders,
868 sort_keys=True,
869 indent=4,
870 separators=( ',', ': ' ) ) )
871 # check for all intent partitions
872 # check for election
873 topics = []
874 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700875 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -0700876 # FIXME: this should only be after we start the app
877 topics.append( "org.onosproject.election" )
878 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -0700879 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700880 for topic in topics:
881 if topic not in ONOStopics:
882 main.log.error( "Error: " + topic +
883 " not in leaders" )
884 missing = True
885 else:
886 main.log.error( "leaders() returned None" )
887 except ( ValueError, TypeError ):
888 main.log.exception( "Error parsing leaders" )
889 main.log.error( repr( leaders ) )
890 # Check all nodes
891 if missing:
Jon Halla440e872016-03-31 15:15:50 -0700892 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700893 node = main.CLIs[ i ]
894 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -0700895 main.log.warn( str( node.name ) + " leaders output: \n" +
896 str( response ) )
897
Jon Halla440e872016-03-31 15:15:50 -0700898 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -0700899 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700900 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -0700901 parsedPartitions = json.loads( partitions )
902 main.log.warn( json.dumps( parsedPartitions,
903 sort_keys=True,
904 indent=4,
905 separators=( ',', ': ' ) ) )
906 # TODO check for a leader in all paritions
907 # TODO check for consistency among nodes
908 else:
909 main.log.error( "partitions() returned None" )
910 except ( ValueError, TypeError ):
911 main.log.exception( "Error parsing partitions" )
912 main.log.error( repr( partitions ) )
Jon Halla440e872016-03-31 15:15:50 -0700913 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -0700914 try:
Jon Hallf37d44d2017-05-24 10:37:30 -0700915 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -0700916 parsedPending = json.loads( pendingMap )
917 main.log.warn( json.dumps( parsedPending,
918 sort_keys=True,
919 indent=4,
920 separators=( ',', ': ' ) ) )
921 # TODO check something here?
922 else:
923 main.log.error( "pendingMap() returned None" )
924 except ( ValueError, TypeError ):
925 main.log.exception( "Error parsing pending map" )
926 main.log.error( repr( pendingMap ) )
927
928 def CASE4( self, main ):
929 """
930 Ping across added host intents
931 """
932 import json
933 import time
Jon Halle1a3b752015-07-22 13:02:46 -0700934 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -0700935 assert main, "main not defined"
936 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -0700937 assert main.CLIs, "main.CLIs not defined"
938 assert main.nodes, "main.nodes not defined"
Jon Halla440e872016-03-31 15:15:50 -0700939 main.case( "Verify connectivity by sending traffic across Intents" )
Jon Hall783bbf92015-07-23 14:33:19 -0700940 main.caseExplanation = "Ping across added host intents to check " +\
Jon Hall5cf14d52015-07-16 12:15:19 -0700941 "functionality and check the state of " +\
942 "the intent"
Jon Hall5cf14d52015-07-16 12:15:19 -0700943
Jon Hallf37d44d2017-05-24 10:37:30 -0700944 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -0700945 main.step( "Check Intent state" )
946 installedCheck = False
947 loopCount = 0
948 while not installedCheck and loopCount < 40:
949 installedCheck = True
950 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -0700951 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -0700952 intentStates = []
953 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
954 count = 0
955 # Iter through intents of a node
956 try:
957 for intent in json.loads( intents ):
958 state = intent.get( 'state', None )
959 if "INSTALLED" not in state:
960 installedCheck = False
961 intentId = intent.get( 'id', None )
962 intentStates.append( ( intentId, state ) )
963 except ( ValueError, TypeError ):
964 main.log.exception( "Error parsing intents." )
965 # Print states
966 intentStates.sort()
967 for i, s in intentStates:
968 count += 1
969 main.log.info( "%-6s%-15s%-15s" %
970 ( str( count ), str( i ), str( s ) ) )
971 if not installedCheck:
972 time.sleep( 1 )
973 loopCount += 1
974 utilities.assert_equals( expect=True, actual=installedCheck,
975 onpass="Intents are all INSTALLED",
976 onfail="Intents are not all in " +
977 "INSTALLED state" )
978
Jon Hall9d2dcad2016-04-08 10:15:20 -0700979 main.step( "Ping across added host intents" )
Jon Hall9d2dcad2016-04-08 10:15:20 -0700980 PingResult = main.TRUE
981 for i in range( 8, 18 ):
982 ping = main.Mininet1.pingHost( src="h" + str( i ),
983 target="h" + str( i + 10 ) )
984 PingResult = PingResult and ping
985 if ping == main.FALSE:
986 main.log.warn( "Ping failed between h" + str( i ) +
987 " and h" + str( i + 10 ) )
988 elif ping == main.TRUE:
989 main.log.info( "Ping test passed!" )
990 # Don't set PingResult or you'd override failures
991 if PingResult == main.FALSE:
992 main.log.error(
993 "Intents have not been installed correctly, pings failed." )
994 # TODO: pretty print
995 main.log.warn( "ONOS1 intents: " )
996 try:
997 tmpIntents = onosCli.intents()
998 main.log.warn( json.dumps( json.loads( tmpIntents ),
999 sort_keys=True,
1000 indent=4,
1001 separators=( ',', ': ' ) ) )
1002 except ( ValueError, TypeError ):
1003 main.log.warn( repr( tmpIntents ) )
1004 utilities.assert_equals(
1005 expect=main.TRUE,
1006 actual=PingResult,
1007 onpass="Intents have been installed correctly and pings work",
1008 onfail="Intents have not been installed correctly, pings failed." )
1009
Jon Hall5cf14d52015-07-16 12:15:19 -07001010 main.step( "Check leadership of topics" )
Jon Halla440e872016-03-31 15:15:50 -07001011 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001012 topicCheck = main.TRUE
1013 try:
1014 if leaders:
1015 parsedLeaders = json.loads( leaders )
1016 main.log.warn( json.dumps( parsedLeaders,
1017 sort_keys=True,
1018 indent=4,
1019 separators=( ',', ': ' ) ) )
1020 # check for all intent partitions
1021 # check for election
1022 # TODO: Look at Devices as topics now that it uses this system
1023 topics = []
1024 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -07001025 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001026 # FIXME: this should only be after we start the app
1027 # FIXME: topics.append( "org.onosproject.election" )
1028 # Print leaders output
1029 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -07001030 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -07001031 for topic in topics:
1032 if topic not in ONOStopics:
1033 main.log.error( "Error: " + topic +
1034 " not in leaders" )
1035 topicCheck = main.FALSE
1036 else:
1037 main.log.error( "leaders() returned None" )
1038 topicCheck = main.FALSE
1039 except ( ValueError, TypeError ):
1040 topicCheck = main.FALSE
1041 main.log.exception( "Error parsing leaders" )
1042 main.log.error( repr( leaders ) )
1043 # TODO: Check for a leader of these topics
1044 # Check all nodes
1045 if topicCheck:
Jon Halla440e872016-03-31 15:15:50 -07001046 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001047 node = main.CLIs[ i ]
1048 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -07001049 main.log.warn( str( node.name ) + " leaders output: \n" +
1050 str( response ) )
1051
1052 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
1053 onpass="intent Partitions is in leaders",
1054 onfail="Some topics were lost " )
1055 # Print partitions
Jon Halla440e872016-03-31 15:15:50 -07001056 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001057 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001058 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -07001059 parsedPartitions = json.loads( partitions )
1060 main.log.warn( json.dumps( parsedPartitions,
1061 sort_keys=True,
1062 indent=4,
1063 separators=( ',', ': ' ) ) )
1064 # TODO check for a leader in all paritions
1065 # TODO check for consistency among nodes
1066 else:
1067 main.log.error( "partitions() returned None" )
1068 except ( ValueError, TypeError ):
1069 main.log.exception( "Error parsing partitions" )
1070 main.log.error( repr( partitions ) )
1071 # Print Pending Map
Jon Halla440e872016-03-31 15:15:50 -07001072 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001073 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001074 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -07001075 parsedPending = json.loads( pendingMap )
1076 main.log.warn( json.dumps( parsedPending,
1077 sort_keys=True,
1078 indent=4,
1079 separators=( ',', ': ' ) ) )
1080 # TODO check something here?
1081 else:
1082 main.log.error( "pendingMap() returned None" )
1083 except ( ValueError, TypeError ):
1084 main.log.exception( "Error parsing pending map" )
1085 main.log.error( repr( pendingMap ) )
1086
1087 if not installedCheck:
1088 main.log.info( "Waiting 60 seconds to see if the state of " +
1089 "intents change" )
1090 time.sleep( 60 )
1091 # Print the intent states
Jon Halla440e872016-03-31 15:15:50 -07001092 intents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001093 intentStates = []
1094 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
1095 count = 0
1096 # Iter through intents of a node
1097 try:
1098 for intent in json.loads( intents ):
1099 state = intent.get( 'state', None )
1100 if "INSTALLED" not in state:
1101 installedCheck = False
1102 intentId = intent.get( 'id', None )
1103 intentStates.append( ( intentId, state ) )
1104 except ( ValueError, TypeError ):
1105 main.log.exception( "Error parsing intents." )
1106 intentStates.sort()
1107 for i, s in intentStates:
1108 count += 1
1109 main.log.info( "%-6s%-15s%-15s" %
1110 ( str( count ), str( i ), str( s ) ) )
Jon Halla440e872016-03-31 15:15:50 -07001111 leaders = onosCli.leaders()
Jon Hall5cf14d52015-07-16 12:15:19 -07001112 try:
1113 missing = False
1114 if leaders:
1115 parsedLeaders = json.loads( leaders )
1116 main.log.warn( json.dumps( parsedLeaders,
1117 sort_keys=True,
1118 indent=4,
1119 separators=( ',', ': ' ) ) )
1120 # check for all intent partitions
1121 # check for election
1122 topics = []
1123 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -07001124 topics.append( "work-partition-" + str( i ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001125 # FIXME: this should only be after we start the app
1126 topics.append( "org.onosproject.election" )
1127 main.log.debug( topics )
Jon Hallf37d44d2017-05-24 10:37:30 -07001128 ONOStopics = [ j[ 'topic' ] for j in parsedLeaders ]
Jon Hall5cf14d52015-07-16 12:15:19 -07001129 for topic in topics:
1130 if topic not in ONOStopics:
1131 main.log.error( "Error: " + topic +
1132 " not in leaders" )
1133 missing = True
1134 else:
1135 main.log.error( "leaders() returned None" )
1136 except ( ValueError, TypeError ):
1137 main.log.exception( "Error parsing leaders" )
1138 main.log.error( repr( leaders ) )
1139 if missing:
Jon Halla440e872016-03-31 15:15:50 -07001140 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001141 node = main.CLIs[ i ]
1142 response = node.leaders( jsonFormat=False )
Jon Hall5cf14d52015-07-16 12:15:19 -07001143 main.log.warn( str( node.name ) + " leaders output: \n" +
1144 str( response ) )
1145
Jon Halla440e872016-03-31 15:15:50 -07001146 partitions = onosCli.partitions()
Jon Hall5cf14d52015-07-16 12:15:19 -07001147 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001148 if partitions:
Jon Hall5cf14d52015-07-16 12:15:19 -07001149 parsedPartitions = json.loads( partitions )
1150 main.log.warn( json.dumps( parsedPartitions,
1151 sort_keys=True,
1152 indent=4,
1153 separators=( ',', ': ' ) ) )
1154 # TODO check for a leader in all paritions
1155 # TODO check for consistency among nodes
1156 else:
1157 main.log.error( "partitions() returned None" )
1158 except ( ValueError, TypeError ):
1159 main.log.exception( "Error parsing partitions" )
1160 main.log.error( repr( partitions ) )
Jon Halla440e872016-03-31 15:15:50 -07001161 pendingMap = onosCli.pendingMap()
Jon Hall5cf14d52015-07-16 12:15:19 -07001162 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001163 if pendingMap:
Jon Hall5cf14d52015-07-16 12:15:19 -07001164 parsedPending = json.loads( pendingMap )
1165 main.log.warn( json.dumps( parsedPending,
1166 sort_keys=True,
1167 indent=4,
1168 separators=( ',', ': ' ) ) )
1169 # TODO check something here?
1170 else:
1171 main.log.error( "pendingMap() returned None" )
1172 except ( ValueError, TypeError ):
1173 main.log.exception( "Error parsing pending map" )
1174 main.log.error( repr( pendingMap ) )
1175 # Print flowrules
Jon Hallf37d44d2017-05-24 10:37:30 -07001176 node = main.activeNodes[ 0 ]
1177 main.log.debug( main.CLIs[ node ].flows( jsonFormat=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001178 main.step( "Wait a minute then ping again" )
1179 # the wait is above
1180 PingResult = main.TRUE
1181 for i in range( 8, 18 ):
1182 ping = main.Mininet1.pingHost( src="h" + str( i ),
1183 target="h" + str( i + 10 ) )
1184 PingResult = PingResult and ping
1185 if ping == main.FALSE:
1186 main.log.warn( "Ping failed between h" + str( i ) +
1187 " and h" + str( i + 10 ) )
1188 elif ping == main.TRUE:
1189 main.log.info( "Ping test passed!" )
1190 # Don't set PingResult or you'd override failures
1191 if PingResult == main.FALSE:
1192 main.log.error(
1193 "Intents have not been installed correctly, pings failed." )
1194 # TODO: pretty print
1195 main.log.warn( "ONOS1 intents: " )
1196 try:
Jon Halla440e872016-03-31 15:15:50 -07001197 tmpIntents = onosCli.intents()
Jon Hall5cf14d52015-07-16 12:15:19 -07001198 main.log.warn( json.dumps( json.loads( tmpIntents ),
1199 sort_keys=True,
1200 indent=4,
1201 separators=( ',', ': ' ) ) )
1202 except ( ValueError, TypeError ):
1203 main.log.warn( repr( tmpIntents ) )
1204 utilities.assert_equals(
1205 expect=main.TRUE,
1206 actual=PingResult,
1207 onpass="Intents have been installed correctly and pings work",
1208 onfail="Intents have not been installed correctly, pings failed." )
1209
1210 def CASE5( self, main ):
1211 """
1212 Reading state of ONOS
1213 """
1214 import json
1215 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001216 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001217 assert main, "main not defined"
1218 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001219 assert main.CLIs, "main.CLIs not defined"
1220 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001221
1222 main.case( "Setting up and gathering data for current state" )
1223 # The general idea for this test case is to pull the state of
1224 # ( intents,flows, topology,... ) from each ONOS node
1225 # We can then compare them with each other and also with past states
1226
1227 main.step( "Check that each switch has a master" )
1228 global mastershipState
1229 mastershipState = '[]'
1230
1231 # Assert that each device has a master
1232 rolesNotNull = main.TRUE
1233 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001234 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001235 t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001236 name="rolesNotNull-" + str( i ),
1237 args=[] )
1238 threads.append( t )
1239 t.start()
1240
1241 for t in threads:
1242 t.join()
1243 rolesNotNull = rolesNotNull and t.result
1244 utilities.assert_equals(
1245 expect=main.TRUE,
1246 actual=rolesNotNull,
1247 onpass="Each device has a master",
1248 onfail="Some devices don't have a master assigned" )
1249
1250 main.step( "Get the Mastership of each switch from each controller" )
1251 ONOSMastership = []
1252 mastershipCheck = main.FALSE
1253 consistentMastership = True
1254 rolesResults = True
1255 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001256 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001257 t = main.Thread( target=main.CLIs[ i ].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001258 name="roles-" + str( i ),
1259 args=[] )
1260 threads.append( t )
1261 t.start()
1262
1263 for t in threads:
1264 t.join()
1265 ONOSMastership.append( t.result )
1266
Jon Halla440e872016-03-31 15:15:50 -07001267 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001268 node = str( main.activeNodes[ i ] + 1 )
1269 if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
Jon Halla440e872016-03-31 15:15:50 -07001270 main.log.error( "Error in getting ONOS" + node + " roles" )
1271 main.log.warn( "ONOS" + node + " mastership response: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001272 repr( ONOSMastership[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001273 rolesResults = False
1274 utilities.assert_equals(
1275 expect=True,
1276 actual=rolesResults,
1277 onpass="No error in reading roles output",
1278 onfail="Error in reading roles from ONOS" )
1279
1280 main.step( "Check for consistency in roles from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001281 if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001282 main.log.info(
1283 "Switch roles are consistent across all ONOS nodes" )
1284 else:
1285 consistentMastership = False
1286 utilities.assert_equals(
1287 expect=True,
1288 actual=consistentMastership,
1289 onpass="Switch roles are consistent across all ONOS nodes",
1290 onfail="ONOS nodes have different views of switch roles" )
1291
1292 if rolesResults and not consistentMastership:
Jon Halla440e872016-03-31 15:15:50 -07001293 for i in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001294 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001295 try:
1296 main.log.warn(
Jon Halla440e872016-03-31 15:15:50 -07001297 "ONOS" + node + " roles: ",
Jon Hall5cf14d52015-07-16 12:15:19 -07001298 json.dumps(
1299 json.loads( ONOSMastership[ i ] ),
1300 sort_keys=True,
1301 indent=4,
1302 separators=( ',', ': ' ) ) )
1303 except ( ValueError, TypeError ):
1304 main.log.warn( repr( ONOSMastership[ i ] ) )
1305 elif rolesResults and consistentMastership:
1306 mastershipCheck = main.TRUE
1307 mastershipState = ONOSMastership[ 0 ]
1308
1309 main.step( "Get the intents from each controller" )
1310 global intentState
1311 intentState = []
1312 ONOSIntents = []
1313 intentCheck = main.FALSE
1314 consistentIntents = True
1315 intentsResults = True
1316 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001317 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001318 t = main.Thread( target=main.CLIs[ i ].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001319 name="intents-" + str( i ),
1320 args=[],
1321 kwargs={ 'jsonFormat': True } )
1322 threads.append( t )
1323 t.start()
1324
1325 for t in threads:
1326 t.join()
1327 ONOSIntents.append( t.result )
1328
Jon Halla440e872016-03-31 15:15:50 -07001329 for i in range( len( ONOSIntents ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001330 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001331 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Halla440e872016-03-31 15:15:50 -07001332 main.log.error( "Error in getting ONOS" + node + " intents" )
1333 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001334 repr( ONOSIntents[ i ] ) )
1335 intentsResults = False
1336 utilities.assert_equals(
1337 expect=True,
1338 actual=intentsResults,
1339 onpass="No error in reading intents output",
1340 onfail="Error in reading intents from ONOS" )
1341
1342 main.step( "Check for consistency in Intents from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001343 if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001344 main.log.info( "Intents are consistent across all ONOS " +
1345 "nodes" )
1346 else:
1347 consistentIntents = False
1348 main.log.error( "Intents not consistent" )
1349 utilities.assert_equals(
1350 expect=True,
1351 actual=consistentIntents,
1352 onpass="Intents are consistent across all ONOS nodes",
1353 onfail="ONOS nodes have different views of intents" )
1354
1355 if intentsResults:
1356 # Try to make it easy to figure out what is happening
1357 #
1358 # Intent ONOS1 ONOS2 ...
1359 # 0x01 INSTALLED INSTALLING
1360 # ... ... ...
1361 # ... ... ...
1362 title = " Id"
Jon Halla440e872016-03-31 15:15:50 -07001363 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001364 title += " " * 10 + "ONOS" + str( n + 1 )
1365 main.log.warn( title )
Jon Halle1a3b752015-07-22 13:02:46 -07001366 # get all intent keys in the cluster
Jon Hall5cf14d52015-07-16 12:15:19 -07001367 keys = []
1368 try:
1369 # Get the set of all intent keys
1370 for nodeStr in ONOSIntents:
1371 node = json.loads( nodeStr )
1372 for intent in node:
1373 keys.append( intent.get( 'id' ) )
1374 keys = set( keys )
1375 # For each intent key, print the state on each node
1376 for key in keys:
1377 row = "%-13s" % key
1378 for nodeStr in ONOSIntents:
1379 node = json.loads( nodeStr )
1380 for intent in node:
1381 if intent.get( 'id', "Error" ) == key:
1382 row += "%-15s" % intent.get( 'state' )
1383 main.log.warn( row )
1384 # End of intent state table
1385 except ValueError as e:
1386 main.log.exception( e )
1387 main.log.debug( "nodeStr was: " + repr( nodeStr ) )
1388
1389 if intentsResults and not consistentIntents:
1390 # print the json objects
Jon Hallf37d44d2017-05-24 10:37:30 -07001391 n = str( main.activeNodes[ -1 ] + 1 )
Jon Halla440e872016-03-31 15:15:50 -07001392 main.log.debug( "ONOS" + n + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001393 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1394 sort_keys=True,
1395 indent=4,
1396 separators=( ',', ': ' ) ) )
Jon Halla440e872016-03-31 15:15:50 -07001397 for i in range( len( ONOSIntents ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001398 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001399 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Halla440e872016-03-31 15:15:50 -07001400 main.log.debug( "ONOS" + node + " intents: " )
Jon Hallf37d44d2017-05-24 10:37:30 -07001401 main.log.debug( json.dumps( json.loads( ONOSIntents[ i ] ),
Jon Hall5cf14d52015-07-16 12:15:19 -07001402 sort_keys=True,
1403 indent=4,
1404 separators=( ',', ': ' ) ) )
1405 else:
Jon Halla440e872016-03-31 15:15:50 -07001406 main.log.debug( "ONOS" + node + " intents match ONOS" +
1407 n + " intents" )
Jon Hall5cf14d52015-07-16 12:15:19 -07001408 elif intentsResults and consistentIntents:
1409 intentCheck = main.TRUE
1410 intentState = ONOSIntents[ 0 ]
1411
1412 main.step( "Get the flows from each controller" )
1413 global flowState
1414 flowState = []
1415 ONOSFlows = []
1416 ONOSFlowsJson = []
1417 flowCheck = main.FALSE
1418 consistentFlows = True
1419 flowsResults = True
1420 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001421 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001422 t = main.Thread( target=main.CLIs[ i ].flows,
Jon Hall5cf14d52015-07-16 12:15:19 -07001423 name="flows-" + str( i ),
1424 args=[],
1425 kwargs={ 'jsonFormat': True } )
1426 threads.append( t )
1427 t.start()
1428
1429 # NOTE: Flows command can take some time to run
Jon Hallf37d44d2017-05-24 10:37:30 -07001430 time.sleep( 30 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001431 for t in threads:
1432 t.join()
1433 result = t.result
1434 ONOSFlows.append( result )
1435
Jon Halla440e872016-03-31 15:15:50 -07001436 for i in range( len( ONOSFlows ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001437 num = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001438 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
1439 main.log.error( "Error in getting ONOS" + num + " flows" )
1440 main.log.warn( "ONOS" + num + " flows response: " +
1441 repr( ONOSFlows[ i ] ) )
1442 flowsResults = False
1443 ONOSFlowsJson.append( None )
1444 else:
1445 try:
1446 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1447 except ( ValueError, TypeError ):
1448 # FIXME: change this to log.error?
1449 main.log.exception( "Error in parsing ONOS" + num +
1450 " response as json." )
1451 main.log.error( repr( ONOSFlows[ i ] ) )
1452 ONOSFlowsJson.append( None )
1453 flowsResults = False
1454 utilities.assert_equals(
1455 expect=True,
1456 actual=flowsResults,
1457 onpass="No error in reading flows output",
1458 onfail="Error in reading flows from ONOS" )
1459
1460 main.step( "Check for consistency in Flows from each controller" )
1461 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1462 if all( tmp ):
1463 main.log.info( "Flow count is consistent across all ONOS nodes" )
1464 else:
1465 consistentFlows = False
1466 utilities.assert_equals(
1467 expect=True,
1468 actual=consistentFlows,
1469 onpass="The flow count is consistent across all ONOS nodes",
1470 onfail="ONOS nodes have different flow counts" )
1471
1472 if flowsResults and not consistentFlows:
Jon Halla440e872016-03-31 15:15:50 -07001473 for i in range( len( ONOSFlows ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001474 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001475 try:
1476 main.log.warn(
Jon Halla440e872016-03-31 15:15:50 -07001477 "ONOS" + node + " flows: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001478 json.dumps( json.loads( ONOSFlows[ i ] ), sort_keys=True,
Jon Hall5cf14d52015-07-16 12:15:19 -07001479 indent=4, separators=( ',', ': ' ) ) )
1480 except ( ValueError, TypeError ):
Jon Halla440e872016-03-31 15:15:50 -07001481 main.log.warn( "ONOS" + node + " flows: " +
1482 repr( ONOSFlows[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001483 elif flowsResults and consistentFlows:
1484 flowCheck = main.TRUE
1485 flowState = ONOSFlows[ 0 ]
1486
1487 main.step( "Get the OF Table entries" )
1488 global flows
1489 flows = []
1490 for i in range( 1, 29 ):
GlennRC68467eb2015-11-16 18:01:01 -08001491 flows.append( main.Mininet1.getFlowTable( "s" + str( i ), version="1.3", debug=False ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001492 if flowCheck == main.FALSE:
1493 for table in flows:
1494 main.log.warn( table )
1495 # TODO: Compare switch flow tables with ONOS flow tables
1496
1497 main.step( "Start continuous pings" )
1498 main.Mininet2.pingLong(
1499 src=main.params[ 'PING' ][ 'source1' ],
1500 target=main.params[ 'PING' ][ 'target1' ],
1501 pingTime=500 )
1502 main.Mininet2.pingLong(
1503 src=main.params[ 'PING' ][ 'source2' ],
1504 target=main.params[ 'PING' ][ 'target2' ],
1505 pingTime=500 )
1506 main.Mininet2.pingLong(
1507 src=main.params[ 'PING' ][ 'source3' ],
1508 target=main.params[ 'PING' ][ 'target3' ],
1509 pingTime=500 )
1510 main.Mininet2.pingLong(
1511 src=main.params[ 'PING' ][ 'source4' ],
1512 target=main.params[ 'PING' ][ 'target4' ],
1513 pingTime=500 )
1514 main.Mininet2.pingLong(
1515 src=main.params[ 'PING' ][ 'source5' ],
1516 target=main.params[ 'PING' ][ 'target5' ],
1517 pingTime=500 )
1518 main.Mininet2.pingLong(
1519 src=main.params[ 'PING' ][ 'source6' ],
1520 target=main.params[ 'PING' ][ 'target6' ],
1521 pingTime=500 )
1522 main.Mininet2.pingLong(
1523 src=main.params[ 'PING' ][ 'source7' ],
1524 target=main.params[ 'PING' ][ 'target7' ],
1525 pingTime=500 )
1526 main.Mininet2.pingLong(
1527 src=main.params[ 'PING' ][ 'source8' ],
1528 target=main.params[ 'PING' ][ 'target8' ],
1529 pingTime=500 )
1530 main.Mininet2.pingLong(
1531 src=main.params[ 'PING' ][ 'source9' ],
1532 target=main.params[ 'PING' ][ 'target9' ],
1533 pingTime=500 )
1534 main.Mininet2.pingLong(
1535 src=main.params[ 'PING' ][ 'source10' ],
1536 target=main.params[ 'PING' ][ 'target10' ],
1537 pingTime=500 )
1538
1539 main.step( "Collecting topology information from ONOS" )
1540 devices = []
1541 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001542 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001543 t = main.Thread( target=main.CLIs[ i ].devices,
Jon Hall5cf14d52015-07-16 12:15:19 -07001544 name="devices-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001545 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001546 threads.append( t )
1547 t.start()
1548
1549 for t in threads:
1550 t.join()
1551 devices.append( t.result )
1552 hosts = []
1553 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001554 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001555 t = main.Thread( target=main.CLIs[ i ].hosts,
Jon Hall5cf14d52015-07-16 12:15:19 -07001556 name="hosts-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001557 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001558 threads.append( t )
1559 t.start()
1560
1561 for t in threads:
1562 t.join()
1563 try:
1564 hosts.append( json.loads( t.result ) )
1565 except ( ValueError, TypeError ):
1566 # FIXME: better handling of this, print which node
1567 # Maybe use thread name?
1568 main.log.exception( "Error parsing json output of hosts" )
Jon Hallf3d16e72015-12-16 17:45:08 -08001569 main.log.warn( repr( t.result ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001570 hosts.append( None )
1571
1572 ports = []
1573 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001574 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001575 t = main.Thread( target=main.CLIs[ i ].ports,
Jon Hall5cf14d52015-07-16 12:15:19 -07001576 name="ports-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001577 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001578 threads.append( t )
1579 t.start()
1580
1581 for t in threads:
1582 t.join()
1583 ports.append( t.result )
1584 links = []
1585 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001586 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001587 t = main.Thread( target=main.CLIs[ i ].links,
Jon Hall5cf14d52015-07-16 12:15:19 -07001588 name="links-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001589 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001590 threads.append( t )
1591 t.start()
1592
1593 for t in threads:
1594 t.join()
1595 links.append( t.result )
1596 clusters = []
1597 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001598 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001599 t = main.Thread( target=main.CLIs[ i ].clusters,
Jon Hall5cf14d52015-07-16 12:15:19 -07001600 name="clusters-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001601 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001602 threads.append( t )
1603 t.start()
1604
1605 for t in threads:
1606 t.join()
1607 clusters.append( t.result )
1608 # Compare json objects for hosts and dataplane clusters
1609
1610 # hosts
1611 main.step( "Host view is consistent across ONOS nodes" )
1612 consistentHostsResult = main.TRUE
1613 for controller in range( len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001614 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001615 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001616 if hosts[ controller ] == hosts[ 0 ]:
1617 continue
1618 else: # hosts not consistent
1619 main.log.error( "hosts from ONOS" +
1620 controllerStr +
1621 " is inconsistent with ONOS1" )
1622 main.log.warn( repr( hosts[ controller ] ) )
1623 consistentHostsResult = main.FALSE
1624
1625 else:
1626 main.log.error( "Error in getting ONOS hosts from ONOS" +
1627 controllerStr )
1628 consistentHostsResult = main.FALSE
1629 main.log.warn( "ONOS" + controllerStr +
1630 " hosts response: " +
1631 repr( hosts[ controller ] ) )
1632 utilities.assert_equals(
1633 expect=main.TRUE,
1634 actual=consistentHostsResult,
1635 onpass="Hosts view is consistent across all ONOS nodes",
1636 onfail="ONOS nodes have different views of hosts" )
1637
1638 main.step( "Each host has an IP address" )
1639 ipResult = main.TRUE
1640 for controller in range( 0, len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001641 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallf3d16e72015-12-16 17:45:08 -08001642 if hosts[ controller ]:
1643 for host in hosts[ controller ]:
Jon Hallf37d44d2017-05-24 10:37:30 -07001644 if not host.get( 'ipAddresses', [] ):
Jon Hallf3d16e72015-12-16 17:45:08 -08001645 main.log.error( "Error with host ips on controller" +
1646 controllerStr + ": " + str( host ) )
1647 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07001648 utilities.assert_equals(
1649 expect=main.TRUE,
1650 actual=ipResult,
1651 onpass="The ips of the hosts aren't empty",
1652 onfail="The ip of at least one host is missing" )
1653
1654 # Strongly connected clusters of devices
1655 main.step( "Cluster view is consistent across ONOS nodes" )
1656 consistentClustersResult = main.TRUE
1657 for controller in range( len( clusters ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001658 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001659 if "Error" not in clusters[ controller ]:
1660 if clusters[ controller ] == clusters[ 0 ]:
1661 continue
1662 else: # clusters not consistent
1663 main.log.error( "clusters from ONOS" + controllerStr +
1664 " is inconsistent with ONOS1" )
1665 consistentClustersResult = main.FALSE
1666
1667 else:
1668 main.log.error( "Error in getting dataplane clusters " +
1669 "from ONOS" + controllerStr )
1670 consistentClustersResult = main.FALSE
1671 main.log.warn( "ONOS" + controllerStr +
1672 " clusters response: " +
1673 repr( clusters[ controller ] ) )
1674 utilities.assert_equals(
1675 expect=main.TRUE,
1676 actual=consistentClustersResult,
1677 onpass="Clusters view is consistent across all ONOS nodes",
1678 onfail="ONOS nodes have different views of clusters" )
Jon Hall64948022016-05-12 13:38:50 -07001679 if not consistentClustersResult:
Jon Hall172b7ba2016-04-07 18:12:20 -07001680 main.log.debug( clusters )
Jon Hall64948022016-05-12 13:38:50 -07001681
Jon Hall5cf14d52015-07-16 12:15:19 -07001682 # there should always only be one cluster
1683 main.step( "Cluster view correct across ONOS nodes" )
1684 try:
1685 numClusters = len( json.loads( clusters[ 0 ] ) )
1686 except ( ValueError, TypeError ):
1687 main.log.exception( "Error parsing clusters[0]: " +
1688 repr( clusters[ 0 ] ) )
Jon Hall6e709752016-02-01 13:38:46 -08001689 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07001690 clusterResults = main.FALSE
1691 if numClusters == 1:
1692 clusterResults = main.TRUE
1693 utilities.assert_equals(
1694 expect=1,
1695 actual=numClusters,
1696 onpass="ONOS shows 1 SCC",
1697 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
1698
1699 main.step( "Comparing ONOS topology to MN" )
1700 devicesResults = main.TRUE
1701 linksResults = main.TRUE
1702 hostsResults = main.TRUE
1703 mnSwitches = main.Mininet1.getSwitches()
1704 mnLinks = main.Mininet1.getLinks()
1705 mnHosts = main.Mininet1.getHosts()
Jon Halla440e872016-03-31 15:15:50 -07001706 for controller in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001707 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001708 if devices[ controller ] and ports[ controller ] and\
Jon Hallf37d44d2017-05-24 10:37:30 -07001709 "Error" not in devices[ controller ] and\
1710 "Error" not in ports[ controller ]:
1711 currentDevicesResult = main.Mininet1.compareSwitches(
1712 mnSwitches,
1713 json.loads( devices[ controller ] ),
1714 json.loads( ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001715 else:
1716 currentDevicesResult = main.FALSE
1717 utilities.assert_equals( expect=main.TRUE,
1718 actual=currentDevicesResult,
1719 onpass="ONOS" + controllerStr +
1720 " Switches view is correct",
1721 onfail="ONOS" + controllerStr +
1722 " Switches view is incorrect" )
1723 if links[ controller ] and "Error" not in links[ controller ]:
1724 currentLinksResult = main.Mininet1.compareLinks(
1725 mnSwitches, mnLinks,
1726 json.loads( links[ controller ] ) )
1727 else:
1728 currentLinksResult = main.FALSE
1729 utilities.assert_equals( expect=main.TRUE,
1730 actual=currentLinksResult,
1731 onpass="ONOS" + controllerStr +
1732 " links view is correct",
1733 onfail="ONOS" + controllerStr +
1734 " links view is incorrect" )
1735
Jon Hall657cdf62015-12-17 14:40:51 -08001736 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07001737 currentHostsResult = main.Mininet1.compareHosts(
1738 mnHosts,
1739 hosts[ controller ] )
1740 else:
1741 currentHostsResult = main.FALSE
1742 utilities.assert_equals( expect=main.TRUE,
1743 actual=currentHostsResult,
1744 onpass="ONOS" + controllerStr +
1745 " hosts exist in Mininet",
1746 onfail="ONOS" + controllerStr +
1747 " hosts don't match Mininet" )
1748
1749 devicesResults = devicesResults and currentDevicesResult
1750 linksResults = linksResults and currentLinksResult
1751 hostsResults = hostsResults and currentHostsResult
1752
1753 main.step( "Device information is correct" )
1754 utilities.assert_equals(
1755 expect=main.TRUE,
1756 actual=devicesResults,
1757 onpass="Device information is correct",
1758 onfail="Device information is incorrect" )
1759
1760 main.step( "Links are correct" )
1761 utilities.assert_equals(
1762 expect=main.TRUE,
1763 actual=linksResults,
1764 onpass="Link are correct",
1765 onfail="Links are incorrect" )
1766
1767 main.step( "Hosts are correct" )
1768 utilities.assert_equals(
1769 expect=main.TRUE,
1770 actual=hostsResults,
1771 onpass="Hosts are correct",
1772 onfail="Hosts are incorrect" )
1773
1774 def CASE6( self, main ):
1775 """
1776 The Failure case. Since this is the Sanity test, we do nothing.
1777 """
1778 import time
Jon Halle1a3b752015-07-22 13:02:46 -07001779 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001780 assert main, "main not defined"
1781 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001782 assert main.CLIs, "main.CLIs not defined"
1783 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001784 main.case( "Wait 60 seconds instead of inducing a failure" )
1785 time.sleep( 60 )
1786 utilities.assert_equals(
1787 expect=main.TRUE,
1788 actual=main.TRUE,
1789 onpass="Sleeping 60 seconds",
1790 onfail="Something is terribly wrong with my math" )
1791
1792 def CASE7( self, main ):
1793 """
1794 Check state after ONOS failure
1795 """
1796 import json
Jon Halle1a3b752015-07-22 13:02:46 -07001797 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001798 assert main, "main not defined"
1799 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07001800 assert main.CLIs, "main.CLIs not defined"
1801 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07001802 main.case( "Running ONOS Constant State Tests" )
1803
1804 main.step( "Check that each switch has a master" )
1805 # Assert that each device has a master
1806 rolesNotNull = main.TRUE
1807 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001808 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001809 t = main.Thread( target=main.CLIs[ i ].rolesNotNull,
Jon Hall5cf14d52015-07-16 12:15:19 -07001810 name="rolesNotNull-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07001811 args=[] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001812 threads.append( t )
1813 t.start()
1814
1815 for t in threads:
1816 t.join()
1817 rolesNotNull = rolesNotNull and t.result
1818 utilities.assert_equals(
1819 expect=main.TRUE,
1820 actual=rolesNotNull,
1821 onpass="Each device has a master",
1822 onfail="Some devices don't have a master assigned" )
1823
1824 main.step( "Read device roles from ONOS" )
1825 ONOSMastership = []
1826 mastershipCheck = main.FALSE
1827 consistentMastership = True
1828 rolesResults = True
1829 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001830 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001831 t = main.Thread( target=main.CLIs[ i ].roles,
Jon Hall5cf14d52015-07-16 12:15:19 -07001832 name="roles-" + str( i ),
1833 args=[] )
1834 threads.append( t )
1835 t.start()
1836
1837 for t in threads:
1838 t.join()
1839 ONOSMastership.append( t.result )
1840
Jon Halla440e872016-03-31 15:15:50 -07001841 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001842 node = str( main.activeNodes[ i ] + 1 )
1843 if not ONOSMastership[ i ] or "Error" in ONOSMastership[ i ]:
Jon Halla440e872016-03-31 15:15:50 -07001844 main.log.error( "Error in getting ONOS" + node + " roles" )
1845 main.log.warn( "ONOS" + node + " mastership response: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07001846 repr( ONOSMastership[ i ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001847 rolesResults = False
1848 utilities.assert_equals(
1849 expect=True,
1850 actual=rolesResults,
1851 onpass="No error in reading roles output",
1852 onfail="Error in reading roles from ONOS" )
1853
1854 main.step( "Check for consistency in roles from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001855 if all( [ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001856 main.log.info(
1857 "Switch roles are consistent across all ONOS nodes" )
1858 else:
1859 consistentMastership = False
1860 utilities.assert_equals(
1861 expect=True,
1862 actual=consistentMastership,
1863 onpass="Switch roles are consistent across all ONOS nodes",
1864 onfail="ONOS nodes have different views of switch roles" )
1865
1866 if rolesResults and not consistentMastership:
Jon Halla440e872016-03-31 15:15:50 -07001867 for i in range( len( ONOSMastership ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001868 node = str( main.activeNodes[ i ] + 1 )
Jon Halla440e872016-03-31 15:15:50 -07001869 main.log.warn( "ONOS" + node + " roles: ",
1870 json.dumps( json.loads( ONOSMastership[ i ] ),
1871 sort_keys=True,
1872 indent=4,
1873 separators=( ',', ': ' ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001874
1875 description2 = "Compare switch roles from before failure"
1876 main.step( description2 )
1877 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07001878 currentJson = json.loads( ONOSMastership[ 0 ] )
Jon Hall5cf14d52015-07-16 12:15:19 -07001879 oldJson = json.loads( mastershipState )
1880 except ( ValueError, TypeError ):
1881 main.log.exception( "Something is wrong with parsing " +
1882 "ONOSMastership[0] or mastershipState" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001883 main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[ 0 ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07001884 main.log.error( "mastershipState" + repr( mastershipState ) )
1885 main.cleanup()
1886 main.exit()
1887 mastershipCheck = main.TRUE
1888 for i in range( 1, 29 ):
1889 switchDPID = str(
1890 main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
1891 current = [ switch[ 'master' ] for switch in currentJson
1892 if switchDPID in switch[ 'id' ] ]
1893 old = [ switch[ 'master' ] for switch in oldJson
1894 if switchDPID in switch[ 'id' ] ]
1895 if current == old:
1896 mastershipCheck = mastershipCheck and main.TRUE
1897 else:
1898 main.log.warn( "Mastership of switch %s changed" % switchDPID )
1899 mastershipCheck = main.FALSE
1900 utilities.assert_equals(
1901 expect=main.TRUE,
1902 actual=mastershipCheck,
1903 onpass="Mastership of Switches was not changed",
1904 onfail="Mastership of some switches changed" )
1905 mastershipCheck = mastershipCheck and consistentMastership
1906
1907 main.step( "Get the intents and compare across all nodes" )
1908 ONOSIntents = []
1909 intentCheck = main.FALSE
1910 consistentIntents = True
1911 intentsResults = True
1912 threads = []
Jon Halla440e872016-03-31 15:15:50 -07001913 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07001914 t = main.Thread( target=main.CLIs[ i ].intents,
Jon Hall5cf14d52015-07-16 12:15:19 -07001915 name="intents-" + str( i ),
1916 args=[],
1917 kwargs={ 'jsonFormat': True } )
1918 threads.append( t )
1919 t.start()
1920
1921 for t in threads:
1922 t.join()
1923 ONOSIntents.append( t.result )
1924
Jon Hallf37d44d2017-05-24 10:37:30 -07001925 for i in range( len( ONOSIntents ) ):
1926 node = str( main.activeNodes[ i ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07001927 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Halla440e872016-03-31 15:15:50 -07001928 main.log.error( "Error in getting ONOS" + node + " intents" )
1929 main.log.warn( "ONOS" + node + " intents response: " +
Jon Hall5cf14d52015-07-16 12:15:19 -07001930 repr( ONOSIntents[ i ] ) )
1931 intentsResults = False
1932 utilities.assert_equals(
1933 expect=True,
1934 actual=intentsResults,
1935 onpass="No error in reading intents output",
1936 onfail="Error in reading intents from ONOS" )
1937
1938 main.step( "Check for consistency in Intents from each controller" )
Jon Hallf37d44d2017-05-24 10:37:30 -07001939 if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall5cf14d52015-07-16 12:15:19 -07001940 main.log.info( "Intents are consistent across all ONOS " +
1941 "nodes" )
1942 else:
1943 consistentIntents = False
1944
1945 # Try to make it easy to figure out what is happening
1946 #
1947 # Intent ONOS1 ONOS2 ...
1948 # 0x01 INSTALLED INSTALLING
1949 # ... ... ...
1950 # ... ... ...
1951 title = " ID"
Jon Halla440e872016-03-31 15:15:50 -07001952 for n in main.activeNodes:
Jon Hall5cf14d52015-07-16 12:15:19 -07001953 title += " " * 10 + "ONOS" + str( n + 1 )
1954 main.log.warn( title )
1955 # get all intent keys in the cluster
1956 keys = []
1957 for nodeStr in ONOSIntents:
1958 node = json.loads( nodeStr )
1959 for intent in node:
1960 keys.append( intent.get( 'id' ) )
1961 keys = set( keys )
1962 for key in keys:
1963 row = "%-13s" % key
1964 for nodeStr in ONOSIntents:
1965 node = json.loads( nodeStr )
1966 for intent in node:
1967 if intent.get( 'id' ) == key:
1968 row += "%-15s" % intent.get( 'state' )
1969 main.log.warn( row )
1970 # End table view
1971
1972 utilities.assert_equals(
1973 expect=True,
1974 actual=consistentIntents,
1975 onpass="Intents are consistent across all ONOS nodes",
1976 onfail="ONOS nodes have different views of intents" )
1977 intentStates = []
1978 for node in ONOSIntents: # Iter through ONOS nodes
1979 nodeStates = []
1980 # Iter through intents of a node
1981 try:
1982 for intent in json.loads( node ):
1983 nodeStates.append( intent[ 'state' ] )
1984 except ( ValueError, TypeError ):
1985 main.log.exception( "Error in parsing intents" )
1986 main.log.error( repr( node ) )
1987 intentStates.append( nodeStates )
Jon Hallf37d44d2017-05-24 10:37:30 -07001988 out = [ ( i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
Jon Hall5cf14d52015-07-16 12:15:19 -07001989 main.log.info( dict( out ) )
1990
1991 if intentsResults and not consistentIntents:
Jon Halla440e872016-03-31 15:15:50 -07001992 for i in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07001993 node = str( main.activeNodes[ i ] + 1 )
Jon Halla440e872016-03-31 15:15:50 -07001994 main.log.warn( "ONOS" + node + " intents: " )
Jon Hall5cf14d52015-07-16 12:15:19 -07001995 main.log.warn( json.dumps(
1996 json.loads( ONOSIntents[ i ] ),
1997 sort_keys=True,
1998 indent=4,
1999 separators=( ',', ': ' ) ) )
2000 elif intentsResults and consistentIntents:
2001 intentCheck = main.TRUE
2002
2003 # NOTE: Store has no durability, so intents are lost across system
2004 # restarts
2005 main.step( "Compare current intents with intents before the failure" )
2006 # NOTE: this requires case 5 to pass for intentState to be set.
2007 # maybe we should stop the test if that fails?
2008 sameIntents = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002009 try:
2010 intentState
2011 except NameError:
2012 main.log.warn( "No previous intent state was saved" )
2013 else:
2014 if intentState and intentState == ONOSIntents[ 0 ]:
2015 sameIntents = main.TRUE
2016 main.log.info( "Intents are consistent with before failure" )
2017 # TODO: possibly the states have changed? we may need to figure out
2018 # what the acceptable states are
2019 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
2020 sameIntents = main.TRUE
2021 try:
2022 before = json.loads( intentState )
2023 after = json.loads( ONOSIntents[ 0 ] )
2024 for intent in before:
2025 if intent not in after:
2026 sameIntents = main.FALSE
2027 main.log.debug( "Intent is not currently in ONOS " +
2028 "(at least in the same form):" )
2029 main.log.debug( json.dumps( intent ) )
2030 except ( ValueError, TypeError ):
2031 main.log.exception( "Exception printing intents" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002032 main.log.debug( repr( ONOSIntents[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002033 main.log.debug( repr( intentState ) )
2034 if sameIntents == main.FALSE:
2035 try:
2036 main.log.debug( "ONOS intents before: " )
2037 main.log.debug( json.dumps( json.loads( intentState ),
2038 sort_keys=True, indent=4,
2039 separators=( ',', ': ' ) ) )
2040 main.log.debug( "Current ONOS intents: " )
2041 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2042 sort_keys=True, indent=4,
2043 separators=( ',', ': ' ) ) )
2044 except ( ValueError, TypeError ):
2045 main.log.exception( "Exception printing intents" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002046 main.log.debug( repr( ONOSIntents[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002047 main.log.debug( repr( intentState ) )
2048 utilities.assert_equals(
2049 expect=main.TRUE,
2050 actual=sameIntents,
2051 onpass="Intents are consistent with before failure",
2052 onfail="The Intents changed during failure" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002053 intentCheck = intentCheck and sameIntents
2054
2055 main.step( "Get the OF Table entries and compare to before " +
2056 "component failure" )
2057 FlowTables = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002058 for i in range( 28 ):
2059 main.log.info( "Checking flow table on s" + str( i + 1 ) )
GlennRC68467eb2015-11-16 18:01:01 -08002060 tmpFlows = main.Mininet1.getFlowTable( "s" + str( i + 1 ), version="1.3", debug=False )
Jon Hallf37d44d2017-05-24 10:37:30 -07002061 curSwitch = main.Mininet1.flowTableComp( flows[ i ], tmpFlows )
Jon Hall41d39f12016-04-11 22:54:35 -07002062 FlowTables = FlowTables and curSwitch
2063 if curSwitch == main.FALSE:
GlennRC68467eb2015-11-16 18:01:01 -08002064 main.log.warn( "Differences in flow table for switch: s{}".format( i + 1 ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002065 utilities.assert_equals(
2066 expect=main.TRUE,
2067 actual=FlowTables,
2068 onpass="No changes were found in the flow tables",
2069 onfail="Changes were found in the flow tables" )
2070
2071 main.Mininet2.pingLongKill()
Jon Hallf37d44d2017-05-24 10:37:30 -07002072 """
Jon Hall5cf14d52015-07-16 12:15:19 -07002073 main.step( "Check the continuous pings to ensure that no packets " +
2074 "were dropped during component failure" )
2075 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2076 main.params[ 'TESTONIP' ] )
2077 LossInPings = main.FALSE
2078 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2079 for i in range( 8, 18 ):
2080 main.log.info(
2081 "Checking for a loss in pings along flow from s" +
2082 str( i ) )
2083 LossInPings = main.Mininet2.checkForLoss(
2084 "/tmp/ping.h" +
2085 str( i ) ) or LossInPings
2086 if LossInPings == main.TRUE:
2087 main.log.info( "Loss in ping detected" )
2088 elif LossInPings == main.ERROR:
2089 main.log.info( "There are multiple mininet process running" )
2090 elif LossInPings == main.FALSE:
2091 main.log.info( "No Loss in the pings" )
2092 main.log.info( "No loss of dataplane connectivity" )
2093 utilities.assert_equals(
2094 expect=main.FALSE,
2095 actual=LossInPings,
2096 onpass="No Loss of connectivity",
2097 onfail="Loss of dataplane connectivity detected" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002098 """
Jon Hall5cf14d52015-07-16 12:15:19 -07002099 main.step( "Leadership Election is still functional" )
2100 # Test of LeadershipElection
Jon Halla440e872016-03-31 15:15:50 -07002101 leaderList = []
2102
Jon Hall5cf14d52015-07-16 12:15:19 -07002103 # NOTE: this only works for the sanity test. In case of failures,
2104 # leader will likely change
Jon Halla440e872016-03-31 15:15:50 -07002105 leader = main.nodes[ main.activeNodes[ 0 ] ].ip_address
Jon Hall5cf14d52015-07-16 12:15:19 -07002106 leaderResult = main.TRUE
Jon Halla440e872016-03-31 15:15:50 -07002107
2108 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002109 cli = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002110 leaderN = cli.electionTestLeader()
Jon Halla440e872016-03-31 15:15:50 -07002111 leaderList.append( leaderN )
Jon Hall5cf14d52015-07-16 12:15:19 -07002112 # verify leader is ONOS1
2113 if leaderN == leader:
2114 # all is well
2115 # NOTE: In failure scenario, this could be a new node, maybe
2116 # check != ONOS1
2117 pass
2118 elif leaderN == main.FALSE:
2119 # error in response
2120 main.log.error( "Something is wrong with " +
2121 "electionTestLeader function, check the" +
2122 " error logs" )
2123 leaderResult = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002124 elif leaderN is None:
2125 main.log.error( cli.name +
2126 " shows no leader for the election-app was" +
2127 " elected after the old one died" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002128 leaderResult = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002129 if len( set( leaderList ) ) != 1:
2130 leaderResult = main.FALSE
2131 main.log.error(
2132 "Inconsistent view of leader for the election test app" )
2133 # TODO: print the list
Jon Hall5cf14d52015-07-16 12:15:19 -07002134 utilities.assert_equals(
2135 expect=main.TRUE,
2136 actual=leaderResult,
2137 onpass="Leadership election passed",
2138 onfail="Something went wrong with Leadership election" )
2139
2140 def CASE8( self, main ):
2141 """
2142 Compare topo
2143 """
2144 import json
2145 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002146 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002147 assert main, "main not defined"
2148 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002149 assert main.CLIs, "main.CLIs not defined"
2150 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002151
2152 main.case( "Compare ONOS Topology view to Mininet topology" )
Jon Hall783bbf92015-07-23 14:33:19 -07002153 main.caseExplanation = "Compare topology objects between Mininet" +\
Jon Hall5cf14d52015-07-16 12:15:19 -07002154 " and ONOS"
Jon Hall5cf14d52015-07-16 12:15:19 -07002155 topoResult = main.FALSE
Jon Halla440e872016-03-31 15:15:50 -07002156 topoFailMsg = "ONOS topology don't match Mininet"
Jon Hall5cf14d52015-07-16 12:15:19 -07002157 elapsed = 0
2158 count = 0
Jon Halle9b1fa32015-12-08 15:32:21 -08002159 main.step( "Comparing ONOS topology to MN topology" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002160 startTime = time.time()
2161 # Give time for Gossip to work
Jon Halle9b1fa32015-12-08 15:32:21 -08002162 while topoResult == main.FALSE and ( elapsed < 60 or count < 3 ):
Jon Hall96091e62015-09-21 17:34:17 -07002163 devicesResults = main.TRUE
2164 linksResults = main.TRUE
2165 hostsResults = main.TRUE
2166 hostAttachmentResults = True
Jon Hall5cf14d52015-07-16 12:15:19 -07002167 count += 1
2168 cliStart = time.time()
2169 devices = []
2170 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002171 for i in main.activeNodes:
2172 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002173 name="devices-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002174 args=[ main.CLIs[ i ].devices, [ None ] ],
2175 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Halla440e872016-03-31 15:15:50 -07002176 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002177 threads.append( t )
2178 t.start()
2179
2180 for t in threads:
2181 t.join()
2182 devices.append( t.result )
2183 hosts = []
2184 ipResult = main.TRUE
2185 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002186 for i in main.activeNodes:
Jon Halld8f6de82015-12-17 17:04:34 -08002187 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002188 name="hosts-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002189 args=[ main.CLIs[ i ].hosts, [ None ] ],
2190 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Halld8f6de82015-12-17 17:04:34 -08002191 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002192 threads.append( t )
2193 t.start()
2194
2195 for t in threads:
2196 t.join()
2197 try:
2198 hosts.append( json.loads( t.result ) )
2199 except ( ValueError, TypeError ):
2200 main.log.exception( "Error parsing hosts results" )
2201 main.log.error( repr( t.result ) )
Jon Hallf3d16e72015-12-16 17:45:08 -08002202 hosts.append( None )
Jon Hall5cf14d52015-07-16 12:15:19 -07002203 for controller in range( 0, len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002204 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hallacd1b182015-12-17 11:43:20 -08002205 if hosts[ controller ]:
2206 for host in hosts[ controller ]:
2207 if host is None or host.get( 'ipAddresses', [] ) == []:
2208 main.log.error(
2209 "Error with host ipAddresses on controller" +
2210 controllerStr + ": " + str( host ) )
2211 ipResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002212 ports = []
2213 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002214 for i in main.activeNodes:
2215 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002216 name="ports-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002217 args=[ main.CLIs[ i ].ports, [ None ] ],
2218 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Halla440e872016-03-31 15:15:50 -07002219 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002220 threads.append( t )
2221 t.start()
2222
2223 for t in threads:
2224 t.join()
2225 ports.append( t.result )
2226 links = []
2227 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002228 for i in main.activeNodes:
2229 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002230 name="links-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002231 args=[ main.CLIs[ i ].links, [ None ] ],
2232 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Halla440e872016-03-31 15:15:50 -07002233 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002234 threads.append( t )
2235 t.start()
2236
2237 for t in threads:
2238 t.join()
2239 links.append( t.result )
2240 clusters = []
2241 threads = []
Jon Halla440e872016-03-31 15:15:50 -07002242 for i in main.activeNodes:
2243 t = main.Thread( target=utilities.retry,
Jon Hall5cf14d52015-07-16 12:15:19 -07002244 name="clusters-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -07002245 args=[ main.CLIs[ i ].clusters, [ None ] ],
2246 kwargs={ 'sleep': 5, 'attempts': 5,
Jon Halla440e872016-03-31 15:15:50 -07002247 'randomTime': True } )
Jon Hall5cf14d52015-07-16 12:15:19 -07002248 threads.append( t )
2249 t.start()
2250
2251 for t in threads:
2252 t.join()
2253 clusters.append( t.result )
2254
2255 elapsed = time.time() - startTime
2256 cliTime = time.time() - cliStart
2257 print "Elapsed time: " + str( elapsed )
2258 print "CLI time: " + str( cliTime )
2259
Jon Halla440e872016-03-31 15:15:50 -07002260 if all( e is None for e in devices ) and\
2261 all( e is None for e in hosts ) and\
2262 all( e is None for e in ports ) and\
2263 all( e is None for e in links ) and\
2264 all( e is None for e in clusters ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002265 topoFailMsg = "Could not get topology from ONOS"
2266 main.log.error( topoFailMsg )
2267 continue # Try again, No use trying to compare
Jon Halla440e872016-03-31 15:15:50 -07002268
Jon Hall5cf14d52015-07-16 12:15:19 -07002269 mnSwitches = main.Mininet1.getSwitches()
2270 mnLinks = main.Mininet1.getLinks()
2271 mnHosts = main.Mininet1.getHosts()
Jon Halla440e872016-03-31 15:15:50 -07002272 for controller in range( len( main.activeNodes ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002273 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002274 if devices[ controller ] and ports[ controller ] and\
Jon Hallf37d44d2017-05-24 10:37:30 -07002275 "Error" not in devices[ controller ] and\
2276 "Error" not in ports[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002277
Jon Hallc6793552016-01-19 14:18:37 -08002278 try:
2279 currentDevicesResult = main.Mininet1.compareSwitches(
2280 mnSwitches,
2281 json.loads( devices[ controller ] ),
2282 json.loads( ports[ controller ] ) )
2283 except ( TypeError, ValueError ) as e:
2284 main.log.exception( "Object not as expected; devices={!r}\nports={!r}".format(
2285 devices[ controller ], ports[ controller ] ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002286 else:
2287 currentDevicesResult = main.FALSE
2288 utilities.assert_equals( expect=main.TRUE,
2289 actual=currentDevicesResult,
2290 onpass="ONOS" + controllerStr +
2291 " Switches view is correct",
2292 onfail="ONOS" + controllerStr +
2293 " Switches view is incorrect" )
2294
2295 if links[ controller ] and "Error" not in links[ controller ]:
2296 currentLinksResult = main.Mininet1.compareLinks(
2297 mnSwitches, mnLinks,
2298 json.loads( links[ controller ] ) )
2299 else:
2300 currentLinksResult = main.FALSE
2301 utilities.assert_equals( expect=main.TRUE,
2302 actual=currentLinksResult,
2303 onpass="ONOS" + controllerStr +
2304 " links view is correct",
2305 onfail="ONOS" + controllerStr +
2306 " links view is incorrect" )
Jon Hall657cdf62015-12-17 14:40:51 -08002307 if hosts[ controller ] and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002308 currentHostsResult = main.Mininet1.compareHosts(
2309 mnHosts,
2310 hosts[ controller ] )
Jon Hall13b446e2016-01-05 12:17:01 -08002311 elif hosts[ controller ] == []:
2312 currentHostsResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002313 else:
2314 currentHostsResult = main.FALSE
2315 utilities.assert_equals( expect=main.TRUE,
2316 actual=currentHostsResult,
2317 onpass="ONOS" + controllerStr +
2318 " hosts exist in Mininet",
2319 onfail="ONOS" + controllerStr +
2320 " hosts don't match Mininet" )
2321 # CHECKING HOST ATTACHMENT POINTS
2322 hostAttachment = True
2323 zeroHosts = False
2324 # FIXME: topo-HA/obelisk specific mappings:
2325 # key is mac and value is dpid
2326 mappings = {}
2327 for i in range( 1, 29 ): # hosts 1 through 28
2328 # set up correct variables:
Jon Hallf37d44d2017-05-24 10:37:30 -07002329 macId = "00:" * 5 + hex( i ).split( "0x" )[ 1 ].upper().zfill( 2 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002330 if i == 1:
Jon Hallf37d44d2017-05-24 10:37:30 -07002331 deviceId = "1000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002332 elif i == 2:
Jon Hallf37d44d2017-05-24 10:37:30 -07002333 deviceId = "2000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002334 elif i == 3:
Jon Hallf37d44d2017-05-24 10:37:30 -07002335 deviceId = "3000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002336 elif i == 4:
Jon Hallf37d44d2017-05-24 10:37:30 -07002337 deviceId = "3004".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002338 elif i == 5:
Jon Hallf37d44d2017-05-24 10:37:30 -07002339 deviceId = "5000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002340 elif i == 6:
Jon Hallf37d44d2017-05-24 10:37:30 -07002341 deviceId = "6000".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002342 elif i == 7:
Jon Hallf37d44d2017-05-24 10:37:30 -07002343 deviceId = "6007".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002344 elif i >= 8 and i <= 17:
2345 dpid = '3' + str( i ).zfill( 3 )
Jon Hallf37d44d2017-05-24 10:37:30 -07002346 deviceId = dpid.zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002347 elif i >= 18 and i <= 27:
2348 dpid = '6' + str( i ).zfill( 3 )
Jon Hallf37d44d2017-05-24 10:37:30 -07002349 deviceId = dpid.zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002350 elif i == 28:
Jon Hallf37d44d2017-05-24 10:37:30 -07002351 deviceId = "2800".zfill( 16 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002352 mappings[ macId ] = deviceId
Jon Halld8f6de82015-12-17 17:04:34 -08002353 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002354 if hosts[ controller ] == []:
2355 main.log.warn( "There are no hosts discovered" )
2356 zeroHosts = True
2357 else:
2358 for host in hosts[ controller ]:
2359 mac = None
2360 location = None
2361 device = None
2362 port = None
2363 try:
2364 mac = host.get( 'mac' )
2365 assert mac, "mac field could not be found for this host object"
2366
2367 location = host.get( 'location' )
2368 assert location, "location field could not be found for this host object"
2369
2370 # Trim the protocol identifier off deviceId
Jon Hallf37d44d2017-05-24 10:37:30 -07002371 device = str( location.get( 'elementId' ) ).split( ':' )[ 1 ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002372 assert device, "elementId field could not be found for this host location object"
2373
2374 port = location.get( 'port' )
2375 assert port, "port field could not be found for this host location object"
2376
2377 # Now check if this matches where they should be
2378 if mac and device and port:
2379 if str( port ) != "1":
2380 main.log.error( "The attachment port is incorrect for " +
2381 "host " + str( mac ) +
Jon Hallf37d44d2017-05-24 10:37:30 -07002382 ". Expected: 1 Actual: " + str( port ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002383 hostAttachment = False
2384 if device != mappings[ str( mac ) ]:
2385 main.log.error( "The attachment device is incorrect for " +
2386 "host " + str( mac ) +
2387 ". Expected: " + mappings[ str( mac ) ] +
2388 " Actual: " + device )
2389 hostAttachment = False
2390 else:
2391 hostAttachment = False
2392 except AssertionError:
2393 main.log.exception( "Json object not as expected" )
2394 main.log.error( repr( host ) )
2395 hostAttachment = False
2396 else:
2397 main.log.error( "No hosts json output or \"Error\"" +
2398 " in output. hosts = " +
2399 repr( hosts[ controller ] ) )
2400 if zeroHosts is False:
2401 hostAttachment = True
2402
2403 # END CHECKING HOST ATTACHMENT POINTS
2404 devicesResults = devicesResults and currentDevicesResult
2405 linksResults = linksResults and currentLinksResult
2406 hostsResults = hostsResults and currentHostsResult
2407 hostAttachmentResults = hostAttachmentResults and\
2408 hostAttachment
2409 topoResult = ( devicesResults and linksResults
2410 and hostsResults and ipResult and
2411 hostAttachmentResults )
Jon Halle9b1fa32015-12-08 15:32:21 -08002412 utilities.assert_equals( expect=True,
2413 actual=topoResult,
2414 onpass="ONOS topology matches Mininet",
Jon Halla440e872016-03-31 15:15:50 -07002415 onfail=topoFailMsg )
Jon Halle9b1fa32015-12-08 15:32:21 -08002416 # End of While loop to pull ONOS state
Jon Hall5cf14d52015-07-16 12:15:19 -07002417
2418 # Compare json objects for hosts and dataplane clusters
2419
2420 # hosts
2421 main.step( "Hosts view is consistent across all ONOS nodes" )
2422 consistentHostsResult = main.TRUE
2423 for controller in range( len( hosts ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002424 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall13b446e2016-01-05 12:17:01 -08002425 if hosts[ controller ] is not None and "Error" not in hosts[ controller ]:
Jon Hall5cf14d52015-07-16 12:15:19 -07002426 if hosts[ controller ] == hosts[ 0 ]:
2427 continue
2428 else: # hosts not consistent
2429 main.log.error( "hosts from ONOS" + controllerStr +
2430 " is inconsistent with ONOS1" )
2431 main.log.warn( repr( hosts[ controller ] ) )
2432 consistentHostsResult = main.FALSE
2433
2434 else:
2435 main.log.error( "Error in getting ONOS hosts from ONOS" +
2436 controllerStr )
2437 consistentHostsResult = main.FALSE
2438 main.log.warn( "ONOS" + controllerStr +
2439 " hosts response: " +
2440 repr( hosts[ controller ] ) )
2441 utilities.assert_equals(
2442 expect=main.TRUE,
2443 actual=consistentHostsResult,
2444 onpass="Hosts view is consistent across all ONOS nodes",
2445 onfail="ONOS nodes have different views of hosts" )
2446
2447 main.step( "Hosts information is correct" )
2448 hostsResults = hostsResults and ipResult
2449 utilities.assert_equals(
2450 expect=main.TRUE,
2451 actual=hostsResults,
2452 onpass="Host information is correct",
2453 onfail="Host information is incorrect" )
2454
2455 main.step( "Host attachment points to the network" )
2456 utilities.assert_equals(
2457 expect=True,
2458 actual=hostAttachmentResults,
2459 onpass="Hosts are correctly attached to the network",
2460 onfail="ONOS did not correctly attach hosts to the network" )
2461
2462 # Strongly connected clusters of devices
2463 main.step( "Clusters view is consistent across all ONOS nodes" )
2464 consistentClustersResult = main.TRUE
2465 for controller in range( len( clusters ) ):
Jon Hallf37d44d2017-05-24 10:37:30 -07002466 controllerStr = str( main.activeNodes[ controller ] + 1 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002467 if "Error" not in clusters[ controller ]:
2468 if clusters[ controller ] == clusters[ 0 ]:
2469 continue
2470 else: # clusters not consistent
2471 main.log.error( "clusters from ONOS" +
2472 controllerStr +
2473 " is inconsistent with ONOS1" )
2474 consistentClustersResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002475 else:
2476 main.log.error( "Error in getting dataplane clusters " +
2477 "from ONOS" + controllerStr )
2478 consistentClustersResult = main.FALSE
2479 main.log.warn( "ONOS" + controllerStr +
2480 " clusters response: " +
2481 repr( clusters[ controller ] ) )
2482 utilities.assert_equals(
2483 expect=main.TRUE,
2484 actual=consistentClustersResult,
2485 onpass="Clusters view is consistent across all ONOS nodes",
2486 onfail="ONOS nodes have different views of clusters" )
Jon Hall64948022016-05-12 13:38:50 -07002487 if not consistentClustersResult:
2488 main.log.debug( clusters )
Jon Hall5cf14d52015-07-16 12:15:19 -07002489
2490 main.step( "There is only one SCC" )
2491 # there should always only be one cluster
2492 try:
2493 numClusters = len( json.loads( clusters[ 0 ] ) )
2494 except ( ValueError, TypeError ):
2495 main.log.exception( "Error parsing clusters[0]: " +
Jon Hallf37d44d2017-05-24 10:37:30 -07002496 repr( clusters[ 0 ] ) )
Jon Halla440e872016-03-31 15:15:50 -07002497 numClusters = "ERROR"
Jon Hall5cf14d52015-07-16 12:15:19 -07002498 clusterResults = main.FALSE
2499 if numClusters == 1:
2500 clusterResults = main.TRUE
2501 utilities.assert_equals(
2502 expect=1,
2503 actual=numClusters,
2504 onpass="ONOS shows 1 SCC",
2505 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2506
2507 topoResult = ( devicesResults and linksResults
2508 and hostsResults and consistentHostsResult
2509 and consistentClustersResult and clusterResults
2510 and ipResult and hostAttachmentResults )
2511
2512 topoResult = topoResult and int( count <= 2 )
2513 note = "note it takes about " + str( int( cliTime ) ) + \
2514 " seconds for the test to make all the cli calls to fetch " +\
2515 "the topology from each ONOS instance"
2516 main.log.info(
2517 "Very crass estimate for topology discovery/convergence( " +
2518 str( note ) + " ): " + str( elapsed ) + " seconds, " +
2519 str( count ) + " tries" )
2520
2521 main.step( "Device information is correct" )
2522 utilities.assert_equals(
2523 expect=main.TRUE,
2524 actual=devicesResults,
2525 onpass="Device information is correct",
2526 onfail="Device information is incorrect" )
2527
2528 main.step( "Links are correct" )
2529 utilities.assert_equals(
2530 expect=main.TRUE,
2531 actual=linksResults,
2532 onpass="Link are correct",
2533 onfail="Links are incorrect" )
2534
2535 main.step( "Hosts are correct" )
2536 utilities.assert_equals(
2537 expect=main.TRUE,
2538 actual=hostsResults,
2539 onpass="Hosts are correct",
2540 onfail="Hosts are incorrect" )
2541
2542 # FIXME: move this to an ONOS state case
2543 main.step( "Checking ONOS nodes" )
Jon Hall41d39f12016-04-11 22:54:35 -07002544 nodeResults = utilities.retry( main.HA.nodesCheck,
2545 False,
Jon Hallf37d44d2017-05-24 10:37:30 -07002546 args=[ main.activeNodes ],
Jon Hall41d39f12016-04-11 22:54:35 -07002547 attempts=5 )
Jon Hall5cf14d52015-07-16 12:15:19 -07002548
Jon Hall41d39f12016-04-11 22:54:35 -07002549 utilities.assert_equals( expect=True, actual=nodeResults,
Jon Hall5cf14d52015-07-16 12:15:19 -07002550 onpass="Nodes check successful",
2551 onfail="Nodes check NOT successful" )
Jon Halla440e872016-03-31 15:15:50 -07002552 if not nodeResults:
Jon Hall41d39f12016-04-11 22:54:35 -07002553 for i in main.activeNodes:
Jon Halla440e872016-03-31 15:15:50 -07002554 main.log.debug( "{} components not ACTIVE: \n{}".format(
Jon Hallf37d44d2017-05-24 10:37:30 -07002555 main.CLIs[ i ].name,
2556 main.CLIs[ i ].sendline( "scr:list | grep -v ACTIVE" ) ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002557
Jon Halld2871c22016-07-26 11:01:14 -07002558 if not topoResult:
2559 main.cleanup()
2560 main.exit()
2561
Jon Hall5cf14d52015-07-16 12:15:19 -07002562 def CASE9( self, main ):
2563 """
2564 Link s3-s28 down
2565 """
2566 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002567 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002568 assert main, "main not defined"
2569 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002570 assert main.CLIs, "main.CLIs not defined"
2571 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002572 # NOTE: You should probably run a topology check after this
2573
2574 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2575
2576 description = "Turn off a link to ensure that Link Discovery " +\
2577 "is working properly"
2578 main.case( description )
2579
2580 main.step( "Kill Link between s3 and s28" )
2581 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
2582 main.log.info( "Waiting " + str( linkSleep ) +
2583 " seconds for link down to be discovered" )
2584 time.sleep( linkSleep )
2585 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
2586 onpass="Link down successful",
2587 onfail="Failed to bring link down" )
2588 # TODO do some sort of check here
2589
2590 def CASE10( self, main ):
2591 """
2592 Link s3-s28 up
2593 """
2594 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002595 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002596 assert main, "main not defined"
2597 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002598 assert main.CLIs, "main.CLIs not defined"
2599 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002600 # NOTE: You should probably run a topology check after this
2601
2602 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
2603
2604 description = "Restore a link to ensure that Link Discovery is " + \
2605 "working properly"
2606 main.case( description )
2607
2608 main.step( "Bring link between s3 and s28 back up" )
2609 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
2610 main.log.info( "Waiting " + str( linkSleep ) +
2611 " seconds for link up to be discovered" )
2612 time.sleep( linkSleep )
2613 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
2614 onpass="Link up successful",
2615 onfail="Failed to bring link up" )
2616 # TODO do some sort of check here
2617
2618 def CASE11( self, main ):
2619 """
2620 Switch Down
2621 """
2622 # NOTE: You should probably run a topology check after this
2623 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002624 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002625 assert main, "main not defined"
2626 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002627 assert main.CLIs, "main.CLIs not defined"
2628 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002629
2630 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2631
2632 description = "Killing a switch to ensure it is discovered correctly"
Jon Hallf37d44d2017-05-24 10:37:30 -07002633 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002634 main.case( description )
2635 switch = main.params[ 'kill' ][ 'switch' ]
2636 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2637
2638 # TODO: Make this switch parameterizable
2639 main.step( "Kill " + switch )
2640 main.log.info( "Deleting " + switch )
2641 main.Mininet1.delSwitch( switch )
2642 main.log.info( "Waiting " + str( switchSleep ) +
2643 " seconds for switch down to be discovered" )
2644 time.sleep( switchSleep )
Jon Halla440e872016-03-31 15:15:50 -07002645 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002646 # Peek at the deleted switch
2647 main.log.warn( str( device ) )
2648 result = main.FALSE
2649 if device and device[ 'available' ] is False:
2650 result = main.TRUE
2651 utilities.assert_equals( expect=main.TRUE, actual=result,
2652 onpass="Kill switch successful",
2653 onfail="Failed to kill switch?" )
2654
2655 def CASE12( self, main ):
2656 """
2657 Switch Up
2658 """
2659 # NOTE: You should probably run a topology check after this
2660 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002661 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002662 assert main, "main not defined"
2663 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002664 assert main.CLIs, "main.CLIs not defined"
2665 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002666 assert ONOS1Port, "ONOS1Port not defined"
2667 assert ONOS2Port, "ONOS2Port not defined"
2668 assert ONOS3Port, "ONOS3Port not defined"
2669 assert ONOS4Port, "ONOS4Port not defined"
2670 assert ONOS5Port, "ONOS5Port not defined"
2671 assert ONOS6Port, "ONOS6Port not defined"
2672 assert ONOS7Port, "ONOS7Port not defined"
2673
2674 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
2675 switch = main.params[ 'kill' ][ 'switch' ]
2676 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2677 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hallf37d44d2017-05-24 10:37:30 -07002678 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002679 description = "Adding a switch to ensure it is discovered correctly"
2680 main.case( description )
2681
2682 main.step( "Add back " + switch )
2683 main.Mininet1.addSwitch( switch, dpid=switchDPID )
2684 for peer in links:
2685 main.Mininet1.addLink( switch, peer )
Jon Halla440e872016-03-31 15:15:50 -07002686 ipList = [ node.ip_address for node in main.nodes ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002687 main.Mininet1.assignSwController( sw=switch, ip=ipList )
2688 main.log.info( "Waiting " + str( switchSleep ) +
2689 " seconds for switch up to be discovered" )
2690 time.sleep( switchSleep )
Jon Halla440e872016-03-31 15:15:50 -07002691 device = onosCli.getDevice( dpid=switchDPID )
Jon Hall5cf14d52015-07-16 12:15:19 -07002692 # Peek at the deleted switch
2693 main.log.warn( str( device ) )
2694 result = main.FALSE
2695 if device and device[ 'available' ]:
2696 result = main.TRUE
2697 utilities.assert_equals( expect=main.TRUE, actual=result,
2698 onpass="add switch successful",
2699 onfail="Failed to add switch?" )
2700
2701 def CASE13( self, main ):
2702 """
2703 Clean up
2704 """
2705 import os
2706 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002707 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002708 assert main, "main not defined"
2709 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002710 assert main.CLIs, "main.CLIs not defined"
2711 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002712
2713 # printing colors to terminal
2714 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2715 'blue': '\033[94m', 'green': '\033[92m',
2716 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
2717 main.case( "Test Cleanup" )
2718 main.step( "Killing tcpdumps" )
2719 main.Mininet2.stopTcpdump()
2720
2721 testname = main.TEST
Jon Hall96091e62015-09-21 17:34:17 -07002722 if main.params[ 'BACKUP' ][ 'ENABLED' ] == "True":
Jon Hall5cf14d52015-07-16 12:15:19 -07002723 main.step( "Copying MN pcap and ONOS log files to test station" )
2724 teststationUser = main.params[ 'BACKUP' ][ 'TESTONUSER' ]
2725 teststationIP = main.params[ 'BACKUP' ][ 'TESTONIP' ]
Jon Hall96091e62015-09-21 17:34:17 -07002726 # NOTE: MN Pcap file is being saved to logdir.
2727 # We scp this file as MN and TestON aren't necessarily the same vm
2728
2729 # FIXME: To be replaced with a Jenkin's post script
Jon Hall5cf14d52015-07-16 12:15:19 -07002730 # TODO: Load these from params
2731 # NOTE: must end in /
2732 logFolder = "/opt/onos/log/"
2733 logFiles = [ "karaf.log", "karaf.log.1" ]
2734 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002735 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002736 for node in main.nodes:
Jon Halla440e872016-03-31 15:15:50 -07002737 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002738 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2739 logFolder + f, dstName )
Jon Hall5cf14d52015-07-16 12:15:19 -07002740 # std*.log's
2741 # NOTE: must end in /
2742 logFolder = "/opt/onos/var/"
2743 logFiles = [ "stderr.log", "stdout.log" ]
2744 # NOTE: must end in /
Jon Hall5cf14d52015-07-16 12:15:19 -07002745 for f in logFiles:
Jon Halle1a3b752015-07-22 13:02:46 -07002746 for node in main.nodes:
Jon Halla440e872016-03-31 15:15:50 -07002747 dstName = main.logdir + "/" + node.name + "-" + f
Jon Hall96091e62015-09-21 17:34:17 -07002748 main.ONOSbench.secureCopy( node.user_name, node.ip_address,
2749 logFolder + f, dstName )
2750 else:
2751 main.log.debug( "skipping saving log files" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002752
2753 main.step( "Stopping Mininet" )
2754 mnResult = main.Mininet1.stopNet()
2755 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2756 onpass="Mininet stopped",
2757 onfail="MN cleanup NOT successful" )
2758
2759 main.step( "Checking ONOS Logs for errors" )
Jon Halle1a3b752015-07-22 13:02:46 -07002760 for node in main.nodes:
Jon Hall96091e62015-09-21 17:34:17 -07002761 main.log.debug( "Checking logs for errors on " + node.name + ":" )
2762 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
Jon Hall5cf14d52015-07-16 12:15:19 -07002763
2764 try:
Jon Hallf37d44d2017-05-24 10:37:30 -07002765 timerLog = open( main.logdir + "/Timers.csv", 'w' )
Jon Hall5cf14d52015-07-16 12:15:19 -07002766 # Overwrite with empty line and close
2767 labels = "Gossip Intents"
2768 data = str( gossipTime )
2769 timerLog.write( labels + "\n" + data )
2770 timerLog.close()
Jon Hallf37d44d2017-05-24 10:37:30 -07002771 except NameError as e:
2772 main.log.exception( e )
Jon Hall5cf14d52015-07-16 12:15:19 -07002773
2774 def CASE14( self, main ):
2775 """
2776 start election app on all onos nodes
2777 """
Jon Halle1a3b752015-07-22 13:02:46 -07002778 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002779 assert main, "main not defined"
2780 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002781 assert main.CLIs, "main.CLIs not defined"
2782 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002783
Jon Hallf37d44d2017-05-24 10:37:30 -07002784 main.case( "Start Leadership Election app" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002785 main.step( "Install leadership election app" )
Jon Hallf37d44d2017-05-24 10:37:30 -07002786 onosCli = main.CLIs[ main.activeNodes[ 0 ] ]
Jon Halla440e872016-03-31 15:15:50 -07002787 appResult = onosCli.activateApp( "org.onosproject.election" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002788 utilities.assert_equals(
2789 expect=main.TRUE,
2790 actual=appResult,
2791 onpass="Election app installed",
2792 onfail="Something went wrong with installing Leadership election" )
2793
2794 main.step( "Run for election on each node" )
Jon Halla440e872016-03-31 15:15:50 -07002795 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -07002796 main.CLIs[ i ].electionTestRun()
2797 time.sleep( 5 )
2798 activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
Jon Hall25463a82016-04-13 14:03:52 -07002799 sameResult, leaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall5cf14d52015-07-16 12:15:19 -07002800 utilities.assert_equals(
Jon Hall25463a82016-04-13 14:03:52 -07002801 expect=True,
2802 actual=sameResult,
2803 onpass="All nodes see the same leaderboards",
2804 onfail="Inconsistent leaderboards" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002805
Jon Hall25463a82016-04-13 14:03:52 -07002806 if sameResult:
2807 leader = leaders[ 0 ][ 0 ]
Jon Hallf37d44d2017-05-24 10:37:30 -07002808 if main.nodes[ main.activeNodes[ 0 ] ].ip_address in leader:
Jon Hall25463a82016-04-13 14:03:52 -07002809 correctLeader = True
2810 else:
2811 correctLeader = False
2812 main.step( "First node was elected leader" )
2813 utilities.assert_equals(
2814 expect=True,
2815 actual=correctLeader,
2816 onpass="Correct leader was elected",
2817 onfail="Incorrect leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002818
2819 def CASE15( self, main ):
2820 """
2821 Check that Leadership Election is still functional
acsmars71adceb2015-08-31 15:09:26 -07002822 15.1 Run election on each node
2823 15.2 Check that each node has the same leaders and candidates
2824 15.3 Find current leader and withdraw
2825 15.4 Check that a new node was elected leader
2826 15.5 Check that that new leader was the candidate of old leader
2827 15.6 Run for election on old leader
2828 15.7 Check that oldLeader is a candidate, and leader if only 1 node
2829 15.8 Make sure that the old leader was added to the candidate list
2830
2831 old and new variable prefixes refer to data from before vs after
2832 withdrawl and later before withdrawl vs after re-election
Jon Hall5cf14d52015-07-16 12:15:19 -07002833 """
2834 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002835 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002836 assert main, "main not defined"
2837 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07002838 assert main.CLIs, "main.CLIs not defined"
2839 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002840
Jon Halla440e872016-03-31 15:15:50 -07002841 description = "Check that Leadership Election is still functional"
Jon Hall5cf14d52015-07-16 12:15:19 -07002842 main.case( description )
Jon Halla440e872016-03-31 15:15:50 -07002843 # NOTE: Need to re-run after restarts since being a canidate is not persistant
Jon Hall5cf14d52015-07-16 12:15:19 -07002844
Jon Halla440e872016-03-31 15:15:50 -07002845 oldLeaders = [] # list of lists of each nodes' candidates before
2846 newLeaders = [] # list of lists of each nodes' candidates after
acsmars71adceb2015-08-31 15:09:26 -07002847 oldLeader = '' # the old leader from oldLeaders, None if not same
2848 newLeader = '' # the new leaders fron newLoeaders, None if not same
2849 oldLeaderCLI = None # the CLI of the old leader used for re-electing
2850 expectNoLeader = False # True when there is only one leader
2851 if main.numCtrls == 1:
2852 expectNoLeader = True
2853
2854 main.step( "Run for election on each node" )
2855 electionResult = main.TRUE
2856
Jon Halla440e872016-03-31 15:15:50 -07002857 for i in main.activeNodes: # run test election on each node
Jon Hallf37d44d2017-05-24 10:37:30 -07002858 if main.CLIs[ i ].electionTestRun() == main.FALSE:
acsmars71adceb2015-08-31 15:09:26 -07002859 electionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002860 utilities.assert_equals(
2861 expect=main.TRUE,
acsmars71adceb2015-08-31 15:09:26 -07002862 actual=electionResult,
2863 onpass="All nodes successfully ran for leadership",
2864 onfail="At least one node failed to run for leadership" )
2865
acsmars3a72bde2015-09-02 14:16:22 -07002866 if electionResult == main.FALSE:
2867 main.log.error(
Jon Halla440e872016-03-31 15:15:50 -07002868 "Skipping Test Case because Election Test App isn't loaded" )
acsmars3a72bde2015-09-02 14:16:22 -07002869 main.skipCase()
2870
acsmars71adceb2015-08-31 15:09:26 -07002871 main.step( "Check that each node shows the same leader and candidates" )
Jon Halla440e872016-03-31 15:15:50 -07002872 failMessage = "Nodes have different leaderboards"
Jon Hallf37d44d2017-05-24 10:37:30 -07002873 activeCLIs = [ main.CLIs[ i ] for i in main.activeNodes ]
Jon Hall41d39f12016-04-11 22:54:35 -07002874 sameResult, oldLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Halla440e872016-03-31 15:15:50 -07002875 if sameResult:
2876 oldLeader = oldLeaders[ 0 ][ 0 ]
2877 main.log.warn( oldLeader )
acsmars71adceb2015-08-31 15:09:26 -07002878 else:
Jon Halla440e872016-03-31 15:15:50 -07002879 oldLeader = None
acsmars71adceb2015-08-31 15:09:26 -07002880 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002881 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002882 actual=sameResult,
Jon Halla440e872016-03-31 15:15:50 -07002883 onpass="Leaderboards are consistent for the election topic",
acsmars71adceb2015-08-31 15:09:26 -07002884 onfail=failMessage )
Jon Hall5cf14d52015-07-16 12:15:19 -07002885
2886 main.step( "Find current leader and withdraw" )
acsmars71adceb2015-08-31 15:09:26 -07002887 withdrawResult = main.TRUE
Jon Hall5cf14d52015-07-16 12:15:19 -07002888 # do some sanity checking on leader before using it
acsmars71adceb2015-08-31 15:09:26 -07002889 if oldLeader is None:
2890 main.log.error( "Leadership isn't consistent." )
2891 withdrawResult = main.FALSE
2892 # Get the CLI of the oldLeader
Jon Halla440e872016-03-31 15:15:50 -07002893 for i in main.activeNodes:
acsmars71adceb2015-08-31 15:09:26 -07002894 if oldLeader == main.nodes[ i ].ip_address:
2895 oldLeaderCLI = main.CLIs[ i ]
Jon Hall5cf14d52015-07-16 12:15:19 -07002896 break
2897 else: # FOR/ELSE statement
2898 main.log.error( "Leader election, could not find current leader" )
2899 if oldLeader:
acsmars71adceb2015-08-31 15:09:26 -07002900 withdrawResult = oldLeaderCLI.electionTestWithdraw()
Jon Hall5cf14d52015-07-16 12:15:19 -07002901 utilities.assert_equals(
2902 expect=main.TRUE,
2903 actual=withdrawResult,
2904 onpass="Node was withdrawn from election",
2905 onfail="Node was not withdrawn from election" )
2906
acsmars71adceb2015-08-31 15:09:26 -07002907 main.step( "Check that a new node was elected leader" )
acsmars71adceb2015-08-31 15:09:26 -07002908 failMessage = "Nodes have different leaders"
acsmars71adceb2015-08-31 15:09:26 -07002909 # Get new leaders and candidates
Jon Hall41d39f12016-04-11 22:54:35 -07002910 newLeaderResult, newLeaders = main.HA.consistentLeaderboards( activeCLIs )
Jon Hall3a7843a2016-04-12 03:01:09 -07002911 newLeader = None
Jon Halla440e872016-03-31 15:15:50 -07002912 if newLeaderResult:
Jon Hall3a7843a2016-04-12 03:01:09 -07002913 if newLeaders[ 0 ][ 0 ] == 'none':
2914 main.log.error( "No leader was elected on at least 1 node" )
2915 if not expectNoLeader:
2916 newLeaderResult = False
Jon Hall25463a82016-04-13 14:03:52 -07002917 newLeader = newLeaders[ 0 ][ 0 ]
acsmars71adceb2015-08-31 15:09:26 -07002918
2919 # Check that the new leader is not the older leader, which was withdrawn
2920 if newLeader == oldLeader:
Jon Halla440e872016-03-31 15:15:50 -07002921 newLeaderResult = False
Jon Hall6e709752016-02-01 13:38:46 -08002922 main.log.error( "All nodes still see old leader: " + str( oldLeader ) +
Jon Hallf37d44d2017-05-24 10:37:30 -07002923 " as the current leader" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002924 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002925 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002926 actual=newLeaderResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07002927 onpass="Leadership election passed",
2928 onfail="Something went wrong with Leadership election" )
2929
Jon Halla440e872016-03-31 15:15:50 -07002930 main.step( "Check that that new leader was the candidate of old leader" )
2931 # candidates[ 2 ] should become the top candidate after withdrawl
acsmars71adceb2015-08-31 15:09:26 -07002932 correctCandidateResult = main.TRUE
2933 if expectNoLeader:
2934 if newLeader == 'none':
2935 main.log.info( "No leader expected. None found. Pass" )
2936 correctCandidateResult = main.TRUE
2937 else:
2938 main.log.info( "Expected no leader, got: " + str( newLeader ) )
2939 correctCandidateResult = main.FALSE
Jon Hallf37d44d2017-05-24 10:37:30 -07002940 elif len( oldLeaders[ 0 ] ) >= 3:
Jon Halla440e872016-03-31 15:15:50 -07002941 if newLeader == oldLeaders[ 0 ][ 2 ]:
2942 # correct leader was elected
2943 correctCandidateResult = main.TRUE
2944 else:
2945 correctCandidateResult = main.FALSE
2946 main.log.error( "Candidate {} was elected. {} should have had priority.".format(
2947 newLeader, oldLeaders[ 0 ][ 2 ] ) )
2948 else:
2949 main.log.warn( "Could not determine who should be the correct leader" )
2950 main.log.debug( oldLeaders[ 0 ] )
acsmars71adceb2015-08-31 15:09:26 -07002951 correctCandidateResult = main.FALSE
acsmars71adceb2015-08-31 15:09:26 -07002952 utilities.assert_equals(
2953 expect=main.TRUE,
2954 actual=correctCandidateResult,
2955 onpass="Correct Candidate Elected",
2956 onfail="Incorrect Candidate Elected" )
2957
Jon Hall5cf14d52015-07-16 12:15:19 -07002958 main.step( "Run for election on old leader( just so everyone " +
2959 "is in the hat )" )
acsmars71adceb2015-08-31 15:09:26 -07002960 if oldLeaderCLI is not None:
2961 runResult = oldLeaderCLI.electionTestRun()
Jon Hall5cf14d52015-07-16 12:15:19 -07002962 else:
acsmars71adceb2015-08-31 15:09:26 -07002963 main.log.error( "No old leader to re-elect" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002964 runResult = main.FALSE
2965 utilities.assert_equals(
2966 expect=main.TRUE,
2967 actual=runResult,
2968 onpass="App re-ran for election",
2969 onfail="App failed to run for election" )
Jon Halla440e872016-03-31 15:15:50 -07002970
acsmars71adceb2015-08-31 15:09:26 -07002971 main.step(
2972 "Check that oldLeader is a candidate, and leader if only 1 node" )
Jon Hall5cf14d52015-07-16 12:15:19 -07002973 # verify leader didn't just change
Jon Halla440e872016-03-31 15:15:50 -07002974 # Get new leaders and candidates
2975 reRunLeaders = []
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002976 time.sleep( 5 ) # Paremterize
Jon Hall41d39f12016-04-11 22:54:35 -07002977 positionResult, reRunLeaders = main.HA.consistentLeaderboards( activeCLIs )
acsmars71adceb2015-08-31 15:09:26 -07002978
2979 # Check that the re-elected node is last on the candidate List
Jon Hallf37d44d2017-05-24 10:37:30 -07002980 if not reRunLeaders[ 0 ]:
Jon Hall3a7843a2016-04-12 03:01:09 -07002981 positionResult = main.FALSE
2982 elif oldLeader != reRunLeaders[ 0 ][ -1 ]:
Jon Hallf37d44d2017-05-24 10:37:30 -07002983 main.log.error( "Old Leader ({}) not in the proper position: {} ".format( str( oldLeader ),
Jon Halla440e872016-03-31 15:15:50 -07002984 str( reRunLeaders[ 0 ] ) ) )
acsmars71adceb2015-08-31 15:09:26 -07002985 positionResult = main.FALSE
Jon Hall5cf14d52015-07-16 12:15:19 -07002986 utilities.assert_equals(
Jon Halla440e872016-03-31 15:15:50 -07002987 expect=True,
acsmars71adceb2015-08-31 15:09:26 -07002988 actual=positionResult,
Jon Hall5cf14d52015-07-16 12:15:19 -07002989 onpass="Old leader successfully re-ran for election",
2990 onfail="Something went wrong with Leadership election after " +
2991 "the old leader re-ran for election" )
2992
2993 def CASE16( self, main ):
2994 """
2995 Install Distributed Primitives app
2996 """
2997 import time
Jon Halle1a3b752015-07-22 13:02:46 -07002998 assert main.numCtrls, "main.numCtrls not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07002999 assert main, "main not defined"
3000 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Halle1a3b752015-07-22 13:02:46 -07003001 assert main.CLIs, "main.CLIs not defined"
3002 assert main.nodes, "main.nodes not defined"
Jon Hall5cf14d52015-07-16 12:15:19 -07003003
3004 # Variables for the distributed primitives tests
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003005 main.pCounterName = "TestON-Partitions"
3006 main.pCounterValue = 0
Jon Hallf37d44d2017-05-24 10:37:30 -07003007 main.onosSet = set( [] )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003008 main.onosSetName = "TestON-set"
Jon Hall5cf14d52015-07-16 12:15:19 -07003009
3010 description = "Install Primitives app"
3011 main.case( description )
3012 main.step( "Install Primitives app" )
3013 appName = "org.onosproject.distributedprimitives"
Jon Hallf37d44d2017-05-24 10:37:30 -07003014 node = main.activeNodes[ 0 ]
3015 appResults = main.CLIs[ node ].activateApp( appName )
Jon Hall5cf14d52015-07-16 12:15:19 -07003016 utilities.assert_equals( expect=main.TRUE,
3017 actual=appResults,
3018 onpass="Primitives app activated",
3019 onfail="Primitives app not activated" )
3020 time.sleep( 5 ) # To allow all nodes to activate
3021
3022 def CASE17( self, main ):
3023 """
3024 Check for basic functionality with distributed primitives
3025 """
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003026 main.HA.CASE17( main )