blob: c08fc964cd4412558ed0fabbcbee9fec5ab96407 [file] [log] [blame]
Jon Hall6aec96b2015-01-19 14:49:31 -08001"""
Jon Hall73cf9cc2014-11-20 22:28:38 -08002Description: This test is to determine if ONOS can handle
3 all of it's nodes restarting
4
5List of test cases:
6CASE1: Compile ONOS and push it to the test machines
Jon Hallc9eabec2015-06-10 14:33:14 -07007CASE2: Assign devices to controllers
8CASE21: Assign mastership to controllers
Jon Hall73cf9cc2014-11-20 22:28:38 -08009CASE3: Assign intents
10CASE4: Ping across added host intents
11CASE5: Reading state of ONOS
12CASE6: The Failure case.
13CASE7: Check state after control plane failure
14CASE8: Compare topo
15CASE9: Link s3-s28 down
16CASE10: Link s3-s28 up
17CASE11: Switch down
18CASE12: Switch up
19CASE13: Clean up
Jon Hall669173b2014-12-17 11:36:30 -080020CASE14: start election app on all onos nodes
21CASE15: Check that Leadership Election is still functional
Jon Hall390696c2015-05-05 17:13:41 -070022CASE16: Install Distributed Primitives app
23CASE17: Check for basic functionality with distributed primitives
Jon Hall6aec96b2015-01-19 14:49:31 -080024"""
Jon Hall8f89dda2015-01-22 16:03:33 -080025
26
Jon Hall73cf9cc2014-11-20 22:28:38 -080027class HATestClusterRestart:
28
Jon Hall6aec96b2015-01-19 14:49:31 -080029 def __init__( self ):
Jon Hall73cf9cc2014-11-20 22:28:38 -080030 self.default = ''
31
Jon Hall6aec96b2015-01-19 14:49:31 -080032 def CASE1( self, main ):
33 """
Jon Hall73cf9cc2014-11-20 22:28:38 -080034 CASE1 is to compile ONOS and push it to the test machines
35
36 Startup sequence:
Jon Hall73cf9cc2014-11-20 22:28:38 -080037 cell <name>
38 onos-verify-cell
39 NOTE: temporary - onos-remove-raft-logs
Jon Hall58c76b72015-02-23 11:09:24 -080040 onos-uninstall
41 start mininet
42 git pull
43 mvn clean install
44 onos-package
Jon Hall73cf9cc2014-11-20 22:28:38 -080045 onos-install -f
46 onos-wait-for-start
Jon Hall58c76b72015-02-23 11:09:24 -080047 start cli sessions
48 start tcpdump
Jon Hall6aec96b2015-01-19 14:49:31 -080049 """
Jon Hall40d2cbd2015-06-03 16:24:29 -070050 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
Jon Hall6aec96b2015-01-19 14:49:31 -080051 "initialization" )
52 main.case( "Setting up test environment" )
Jon Hallfeff3082015-05-19 10:23:26 -070053 main.caseExplaination = "Setup the test environment including " +\
54 "installing ONOS, starting Mininet and ONOS" +\
55 "cli sessions."
Jon Hall6aec96b2015-01-19 14:49:31 -080056 # TODO: save all the timers and output them for plotting
Jon Hall73cf9cc2014-11-20 22:28:38 -080057
Jon Hall5cfd23c2015-03-19 11:40:57 -070058 # load some variables from the params file
Jon Hall8f89dda2015-01-22 16:03:33 -080059 PULLCODE = False
Jon Hall6aec96b2015-01-19 14:49:31 -080060 if main.params[ 'Git' ] == 'True':
Jon Hall8f89dda2015-01-22 16:03:33 -080061 PULLCODE = True
Jon Hall529a37f2015-01-28 10:02:00 -080062 gitBranch = main.params[ 'branch' ]
Jon Hall8f89dda2015-01-22 16:03:33 -080063 cellName = main.params[ 'ENV' ][ 'cellName' ]
Jon Hall6aec96b2015-01-19 14:49:31 -080064
65 # set global variables
Jon Hall8f89dda2015-01-22 16:03:33 -080066 global ONOS1Port
Jon Hall8f89dda2015-01-22 16:03:33 -080067 global ONOS2Port
Jon Hall8f89dda2015-01-22 16:03:33 -080068 global ONOS3Port
Jon Hall8f89dda2015-01-22 16:03:33 -080069 global ONOS4Port
Jon Hall8f89dda2015-01-22 16:03:33 -080070 global ONOS5Port
Jon Hall8f89dda2015-01-22 16:03:33 -080071 global ONOS6Port
Jon Hall8f89dda2015-01-22 16:03:33 -080072 global ONOS7Port
73 global numControllers
Jon Hallc9eabec2015-06-10 14:33:14 -070074 # These are for csv plotting in jenkins
75 global labels
76 global data
77 labels = []
78 data = []
Jon Hall8f89dda2015-01-22 16:03:33 -080079 numControllers = int( main.params[ 'num_controllers' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -080080
Jon Hall5cfd23c2015-03-19 11:40:57 -070081 # FIXME: just get controller port from params?
82 # TODO: do we really need all these?
83 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
84 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
85 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
86 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
87 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
88 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
89 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
90
91 global CLIs
92 CLIs = []
93 global nodes
94 nodes = []
95 for i in range( 1, numControllers + 1 ):
96 CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
97 nodes.append( getattr( main, 'ONOS' + str( i ) ) )
98
Jon Hall6aec96b2015-01-19 14:49:31 -080099 main.step( "Applying cell variable to environment" )
Jon Hall8f89dda2015-01-22 16:03:33 -0800100 cellResult = main.ONOSbench.setCell( cellName )
101 verifyResult = main.ONOSbench.verifyCell()
Jon Hall73cf9cc2014-11-20 22:28:38 -0800102
Jon Hall6aec96b2015-01-19 14:49:31 -0800103 # FIXME:this is short term fix
Jon Hall40d2cbd2015-06-03 16:24:29 -0700104 main.log.info( "Removing raft logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -0800105 main.ONOSbench.onosRemoveRaftLogs()
Jon Hall5cfd23c2015-03-19 11:40:57 -0700106
Jon Hall40d2cbd2015-06-03 16:24:29 -0700107 main.log.info( "Uninstalling ONOS" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700108 for node in nodes:
109 main.ONOSbench.onosUninstall( node.ip_address )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800110
Jon Hall390696c2015-05-05 17:13:41 -0700111 # Make sure ONOS is DEAD
Jon Hall40d2cbd2015-06-03 16:24:29 -0700112 main.log.info( "Killing any ONOS processes" )
Jon Hall390696c2015-05-05 17:13:41 -0700113 killResults = main.TRUE
114 for node in nodes:
115 killed = main.ONOSbench.onosKill( node.ip_address )
116 killResults = killResults and killed
117
Jon Hall8f89dda2015-01-22 16:03:33 -0800118 cleanInstallResult = main.TRUE
119 gitPullResult = main.TRUE
Jon Hall73cf9cc2014-11-20 22:28:38 -0800120
Jon Hall97f31752015-02-04 12:01:04 -0800121 main.step( "Starting Mininet" )
Jon Hall390696c2015-05-05 17:13:41 -0700122 mnResult = main.Mininet1.startNet( )
123 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
124 onpass="Mininet Started",
125 onfail="Error starting Mininet" )
Jon Hall97f31752015-02-04 12:01:04 -0800126
Jon Hallfeff3082015-05-19 10:23:26 -0700127 main.step( "Git checkout and pull " + gitBranch )
Jon Hall8f89dda2015-01-22 16:03:33 -0800128 if PULLCODE:
Jon Hall529a37f2015-01-28 10:02:00 -0800129 main.ONOSbench.gitCheckout( gitBranch )
Jon Hall8f89dda2015-01-22 16:03:33 -0800130 gitPullResult = main.ONOSbench.gitPull()
Jon Hall390696c2015-05-05 17:13:41 -0700131 # values of 1 or 3 are good
132 utilities.assert_lesser( expect=0, actual=gitPullResult,
133 onpass="Git pull successful",
134 onfail="Git pull failed" )
Jon Hall1b8f54a2015-02-04 13:24:20 -0800135 main.ONOSbench.getVersion( report=True )
Jon Hallfeff3082015-05-19 10:23:26 -0700136
137 main.step( "Using mvn clean install" )
138 cleanInstallResult = main.TRUE
Jon Hall40d2cbd2015-06-03 16:24:29 -0700139 if PULLCODE and gitPullResult == main.TRUE:
Jon Hallfeff3082015-05-19 10:23:26 -0700140 cleanInstallResult = main.ONOSbench.cleanInstall()
Jon Hall40d2cbd2015-06-03 16:24:29 -0700141 else:
142 main.log.warn( "Did not pull new code so skipping mvn " +
143 "clean install" )
Jon Hallfeff3082015-05-19 10:23:26 -0700144 utilities.assert_equals( expect=main.TRUE,
145 actual=cleanInstallResult,
146 onpass="MCI successful",
147 onfail="MCI failed" )
Jon Hall390696c2015-05-05 17:13:41 -0700148 # GRAPHS
149 # NOTE: important params here:
150 # job = name of Jenkins job
151 # Plot Name = Plot-HA, only can be used if multiple plots
152 # index = The number of the graph under plot name
153 job = "HAClusterRestart"
Jon Hall40d2cbd2015-06-03 16:24:29 -0700154 plotName = "Plot-HA"
Jon Hall390696c2015-05-05 17:13:41 -0700155 graphs = '<ac:structured-macro ac:name="html">\n'
156 graphs += '<ac:plain-text-body><![CDATA[\n'
157 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Hall40d2cbd2015-06-03 16:24:29 -0700158 '/plot/' + plotName + '/getPlot?index=0' +\
159 '&width=500&height=300"' +\
Jon Hall390696c2015-05-05 17:13:41 -0700160 'noborder="0" width="500" height="300" scrolling="yes" ' +\
161 'seamless="seamless"></iframe>\n'
162 graphs += ']]></ac:plain-text-body>\n'
163 graphs += '</ac:structured-macro>\n'
164 main.log.wiki(graphs)
Jon Hall73cf9cc2014-11-20 22:28:38 -0800165
Jon Hall6aec96b2015-01-19 14:49:31 -0800166 main.step( "Creating ONOS package" )
Jon Hall8f89dda2015-01-22 16:03:33 -0800167 packageResult = main.ONOSbench.onosPackage()
Jon Hall390696c2015-05-05 17:13:41 -0700168 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
169 onpass="ONOS package successful",
170 onfail="ONOS package failed" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800171
Jon Hall6aec96b2015-01-19 14:49:31 -0800172 main.step( "Installing ONOS package" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700173 onosInstallResult = main.TRUE
174 for node in nodes:
175 tmpResult = main.ONOSbench.onosInstall( options="-f",
176 node=node.ip_address )
177 onosInstallResult = onosInstallResult and tmpResult
Jon Hall390696c2015-05-05 17:13:41 -0700178 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
179 onpass="ONOS install successful",
180 onfail="ONOS install failed" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800181
Jon Hall6aec96b2015-01-19 14:49:31 -0800182 main.step( "Checking if ONOS is up yet" )
Jon Hall6aec96b2015-01-19 14:49:31 -0800183 for i in range( 2 ):
Jon Hall5cfd23c2015-03-19 11:40:57 -0700184 onosIsupResult = main.TRUE
185 for node in nodes:
186 started = main.ONOSbench.isup( node.ip_address )
187 if not started:
Jon Hall40d2cbd2015-06-03 16:24:29 -0700188 main.log.error( node.name + " didn't start!" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700189 main.ONOSbench.onosStop( node.ip_address )
190 main.ONOSbench.onosStart( node.ip_address )
191 onosIsupResult = onosIsupResult and started
Jon Hall8f89dda2015-01-22 16:03:33 -0800192 if onosIsupResult == main.TRUE:
Jon Hall94fd0472014-12-08 11:52:42 -0800193 break
Jon Hall390696c2015-05-05 17:13:41 -0700194 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
195 onpass="ONOS startup successful",
196 onfail="ONOS startup failed" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800197
Jon Hall5cfd23c2015-03-19 11:40:57 -0700198 main.log.step( "Starting ONOS CLI sessions" )
199 cliResults = main.TRUE
200 threads = []
201 for i in range( numControllers ):
202 t = main.Thread( target=CLIs[i].startOnosCli,
203 name="startOnosCli-" + str( i ),
204 args=[nodes[i].ip_address] )
205 threads.append( t )
206 t.start()
207
208 for t in threads:
209 t.join()
210 cliResults = cliResults and t.result
Jon Hall390696c2015-05-05 17:13:41 -0700211 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
212 onpass="ONOS cli startup successful",
213 onfail="ONOS cli startup failed" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800214
Jon Hall40d2cbd2015-06-03 16:24:29 -0700215 if main.params[ 'tcpdump' ].lower() == "true":
216 main.step( "Start Packet Capture MN" )
217 main.Mininet2.startTcpdump(
218 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
219 + "-MN.pcap",
220 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
221 port=main.params[ 'MNtcpdump' ][ 'port' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800222
Jon Hall390696c2015-05-05 17:13:41 -0700223 main.step( "App Ids check" )
Jon Halla9d26da2015-03-30 16:45:32 -0700224 appCheck = main.TRUE
225 threads = []
226 for i in range( numControllers ):
227 t = main.Thread( target=CLIs[i].appToIDCheck,
228 name="appToIDCheck-" + str( i ),
229 args=[] )
230 threads.append( t )
231 t.start()
232
233 for t in threads:
234 t.join()
235 appCheck = appCheck and t.result
Jon Halla9d26da2015-03-30 16:45:32 -0700236 if appCheck != main.TRUE:
237 main.log.warn( CLIs[0].apps() )
238 main.log.warn( CLIs[0].appIDs() )
Jon Hall390696c2015-05-05 17:13:41 -0700239 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
240 onpass="App Ids seem to be correct",
241 onfail="Something is wrong with app Ids" )
Jon Halla9d26da2015-03-30 16:45:32 -0700242
Jon Hallfeff3082015-05-19 10:23:26 -0700243 if cliResults == main.FALSE:
244 main.log.error( "Failed to start ONOS, stopping test" )
Jon Hall94fd0472014-12-08 11:52:42 -0800245 main.cleanup()
246 main.exit()
Jon Hall73cf9cc2014-11-20 22:28:38 -0800247
Jon Hall6aec96b2015-01-19 14:49:31 -0800248 def CASE2( self, main ):
249 """
Jon Hallc9eabec2015-06-10 14:33:14 -0700250 Assign devices to controllers
Jon Hall6aec96b2015-01-19 14:49:31 -0800251 """
Jon Hall73cf9cc2014-11-20 22:28:38 -0800252 import re
Jon Hall390696c2015-05-05 17:13:41 -0700253 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -0700254 assert numControllers, "numControllers not defined"
255 assert main, "main not defined"
256 assert utilities.assert_equals, "utilities.assert_equals not defined"
257 assert CLIs, "CLIs not defined"
258 assert nodes, "nodes not defined"
259 assert ONOS1Port, "ONOS1Port not defined"
260 assert ONOS2Port, "ONOS2Port not defined"
261 assert ONOS3Port, "ONOS3Port not defined"
262 assert ONOS4Port, "ONOS4Port not defined"
263 assert ONOS5Port, "ONOS5Port not defined"
264 assert ONOS6Port, "ONOS6Port not defined"
265 assert ONOS7Port, "ONOS7Port not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -0800266
Jon Hallc9eabec2015-06-10 14:33:14 -0700267 main.case( "Assigning devices to controllers" )
Jon Hallfeff3082015-05-19 10:23:26 -0700268 main.caseExplaination = "Assign switches to ONOS using 'ovs-vsctl' " +\
269 "and check that an ONOS node becomes the " +\
Jon Hallc9eabec2015-06-10 14:33:14 -0700270 "master of the device."
Jon Hall6aec96b2015-01-19 14:49:31 -0800271 main.step( "Assign switches to controllers" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800272
Jon Hall0f523f22015-07-06 09:31:09 -0700273 ipList = []
274 for i in range( numControllers ):
275 ipList.append( nodes[ i ].ip_address )
276 swList = []
Jon Hall6aec96b2015-01-19 14:49:31 -0800277 for i in range( 1, 29 ):
Jon Hall0f523f22015-07-06 09:31:09 -0700278 swList.append( "s" + str( i ) )
279 main.Mininet1.assignSwController( sw=swList, ip=ipList )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800280
Jon Hall8f89dda2015-01-22 16:03:33 -0800281 mastershipCheck = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -0800282 for i in range( 1, 29 ):
Jon Hall8f89dda2015-01-22 16:03:33 -0800283 response = main.Mininet1.getSwController( "s" + str( i ) )
Jon Hallffb386d2014-11-21 13:43:38 -0800284 try:
Jon Hall6aec96b2015-01-19 14:49:31 -0800285 main.log.info( str( response ) )
Jon Hallfebb1c72015-03-05 13:30:09 -0800286 except Exception:
Jon Hall6aec96b2015-01-19 14:49:31 -0800287 main.log.info( repr( response ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700288 for node in nodes:
289 if re.search( "tcp:" + node.ip_address, response ):
290 mastershipCheck = mastershipCheck and main.TRUE
291 else:
Jon Halla9d26da2015-03-30 16:45:32 -0700292 main.log.error( "Error, node " + node.ip_address + " is " +
293 "not in the list of controllers s" +
294 str( i ) + " is connecting to." )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700295 mastershipCheck = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -0800296 utilities.assert_equals(
297 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800298 actual=mastershipCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -0800299 onpass="Switch mastership assigned correctly",
300 onfail="Switches not assigned correctly to controllers" )
Jon Hall390696c2015-05-05 17:13:41 -0700301
Jon Hallc9eabec2015-06-10 14:33:14 -0700302 def CASE21( self, main ):
303 """
304 Assign mastership to controllers
305 """
306 import re
307 import time
308 assert numControllers, "numControllers not defined"
309 assert main, "main not defined"
310 assert utilities.assert_equals, "utilities.assert_equals not defined"
311 assert CLIs, "CLIs not defined"
312 assert nodes, "nodes not defined"
313 assert ONOS1Port, "ONOS1Port not defined"
314 assert ONOS2Port, "ONOS2Port not defined"
315 assert ONOS3Port, "ONOS3Port not defined"
316 assert ONOS4Port, "ONOS4Port not defined"
317 assert ONOS5Port, "ONOS5Port not defined"
318 assert ONOS6Port, "ONOS6Port not defined"
319 assert ONOS7Port, "ONOS7Port not defined"
320
321 main.case( "Assigning Controller roles for switches" )
322 main.caseExplaination = "Check that ONOS is connected to each " +\
323 "device. Then manually assign" +\
324 " mastership to specific ONOS nodes using" +\
325 " 'device-role'"
Jon Hall390696c2015-05-05 17:13:41 -0700326 main.step( "Assign mastership of switches to specific controllers" )
Jon Hall6aec96b2015-01-19 14:49:31 -0800327 # Manually assign mastership to the controller we want
Jon Hall8f89dda2015-01-22 16:03:33 -0800328 roleCall = main.TRUE
Jon Hall390696c2015-05-05 17:13:41 -0700329
330 ipList = [ ]
331 deviceList = []
Jon Hall58c76b72015-02-23 11:09:24 -0800332 try:
Jon Halla9d26da2015-03-30 16:45:32 -0700333 for i in range( 1, 29 ): # switches 1 through 28
334 # set up correct variables:
335 if i == 1:
336 ip = nodes[ 0 ].ip_address # ONOS1
337 deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
338 elif i == 2:
339 ip = nodes[ 1 ].ip_address # ONOS2
340 deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
341 elif i == 3:
342 ip = nodes[ 1 ].ip_address # ONOS2
343 deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
344 elif i == 4:
345 ip = nodes[ 3 ].ip_address # ONOS4
346 deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
347 elif i == 5:
348 ip = nodes[ 2 ].ip_address # ONOS3
349 deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
350 elif i == 6:
351 ip = nodes[ 2 ].ip_address # ONOS3
352 deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
353 elif i == 7:
354 ip = nodes[ 5 ].ip_address # ONOS6
355 deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
356 elif i >= 8 and i <= 17:
357 ip = nodes[ 4 ].ip_address # ONOS5
358 dpid = '3' + str( i ).zfill( 3 )
359 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
360 elif i >= 18 and i <= 27:
361 ip = nodes[ 6 ].ip_address # ONOS7
362 dpid = '6' + str( i ).zfill( 3 )
363 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
364 elif i == 28:
365 ip = nodes[ 0 ].ip_address # ONOS1
366 deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
367 else:
368 main.log.error( "You didn't write an else statement for " +
369 "switch s" + str( i ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700370 roleCall = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -0700371 # Assign switch
372 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
373 # TODO: make this controller dynamic
374 roleCall = roleCall and main.ONOScli1.deviceRole( deviceId,
375 ip )
Jon Hall390696c2015-05-05 17:13:41 -0700376 ipList.append( ip )
377 deviceList.append( deviceId )
Jon Hall58c76b72015-02-23 11:09:24 -0800378 except ( AttributeError, AssertionError ):
379 main.log.exception( "Something is wrong with ONOS device view" )
380 main.log.info( main.ONOScli1.devices() )
Jon Hall6aec96b2015-01-19 14:49:31 -0800381 utilities.assert_equals(
382 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800383 actual=roleCall,
Jon Hall6aec96b2015-01-19 14:49:31 -0800384 onpass="Re-assigned switch mastership to designated controller",
Jon Hall8f89dda2015-01-22 16:03:33 -0800385 onfail="Something wrong with deviceRole calls" )
Jon Hall94fd0472014-12-08 11:52:42 -0800386
Jon Hall390696c2015-05-05 17:13:41 -0700387 main.step( "Check mastership was correctly assigned" )
388 roleCheck = main.TRUE
389 # NOTE: This is due to the fact that device mastership change is not
390 # atomic and is actually a multi step process
391 time.sleep( 5 )
392 for i in range( len( ipList ) ):
393 ip = ipList[i]
394 deviceId = deviceList[i]
395 # Check assignment
396 master = main.ONOScli1.getRole( deviceId ).get( 'master' )
397 if ip in master:
398 roleCheck = roleCheck and main.TRUE
399 else:
400 roleCheck = roleCheck and main.FALSE
401 main.log.error( "Error, controller " + ip + " is not" +
402 " master " + "of device " +
403 str( deviceId ) + ". Master is " +
404 repr( master ) + "." )
Jon Hall6aec96b2015-01-19 14:49:31 -0800405 utilities.assert_equals(
406 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800407 actual=roleCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -0800408 onpass="Switches were successfully reassigned to designated " +
409 "controller",
410 onfail="Switches were not successfully reassigned" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800411
Jon Hall6aec96b2015-01-19 14:49:31 -0800412 def CASE3( self, main ):
Jon Hall73cf9cc2014-11-20 22:28:38 -0800413 """
414 Assign intents
Jon Hall73cf9cc2014-11-20 22:28:38 -0800415 """
416 import time
Jon Hall58c76b72015-02-23 11:09:24 -0800417 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -0700418 assert numControllers, "numControllers not defined"
419 assert main, "main not defined"
420 assert utilities.assert_equals, "utilities.assert_equals not defined"
421 assert CLIs, "CLIs not defined"
422 assert nodes, "nodes not defined"
Jon Hallc9eabec2015-06-10 14:33:14 -0700423 try:
424 labels
425 except NameError:
426 main.log.error( "labels not defined, setting to []" )
427 labels = []
428 try:
429 data
430 except NameError:
431 main.log.error( "data not defined, setting to []" )
432 data = []
Jon Hallfeff3082015-05-19 10:23:26 -0700433 # NOTE: we must reinstall intents until we have a persistant intent
434 # datastore!
Jon Hall6aec96b2015-01-19 14:49:31 -0800435 main.case( "Adding host Intents" )
Jon Hallfeff3082015-05-19 10:23:26 -0700436 main.caseExplaination = "Discover hosts by using pingall then " +\
437 "assign predetermined host-to-host intents." +\
438 " After installation, check that the intent" +\
439 " is distributed to all nodes and the state" +\
440 " is INSTALLED"
Jon Hall73cf9cc2014-11-20 22:28:38 -0800441
Jon Hall6aec96b2015-01-19 14:49:31 -0800442 # install onos-app-fwd
Jon Hall390696c2015-05-05 17:13:41 -0700443 main.step( "Install reactive forwarding app" )
444 installResults = CLIs[0].activateApp( "org.onosproject.fwd" )
445 utilities.assert_equals( expect=main.TRUE, actual=installResults,
446 onpass="Install fwd successful",
447 onfail="Install fwd failed" )
Jon Halla9d26da2015-03-30 16:45:32 -0700448
Jon Hallfeff3082015-05-19 10:23:26 -0700449 main.step( "Check app ids" )
Jon Halla9d26da2015-03-30 16:45:32 -0700450 appCheck = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -0700451 threads = []
452 for i in range( numControllers ):
Jon Halla9d26da2015-03-30 16:45:32 -0700453 t = main.Thread( target=CLIs[i].appToIDCheck,
454 name="appToIDCheck-" + str( i ),
455 args=[] )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700456 threads.append( t )
457 t.start()
458
459 for t in threads:
460 t.join()
Jon Halla9d26da2015-03-30 16:45:32 -0700461 appCheck = appCheck and t.result
Jon Halla9d26da2015-03-30 16:45:32 -0700462 if appCheck != main.TRUE:
463 main.log.warn( CLIs[0].apps() )
464 main.log.warn( CLIs[0].appIDs() )
Jon Hall390696c2015-05-05 17:13:41 -0700465 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
466 onpass="App Ids seem to be correct",
467 onfail="Something is wrong with app Ids" )
Jon Hall94fd0472014-12-08 11:52:42 -0800468
Jon Hallfeff3082015-05-19 10:23:26 -0700469 main.step( "Discovering Hosts( Via pingall for now )" )
470 # FIXME: Once we have a host discovery mechanism, use that instead
Jon Hall6aec96b2015-01-19 14:49:31 -0800471 # REACTIVE FWD test
Jon Hall8f89dda2015-01-22 16:03:33 -0800472 pingResult = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -0700473 for i in range(2): # Retry if pingall fails first time
474 time1 = time.time()
475 pingResult = main.Mininet1.pingall()
Jon Hall0f523f22015-07-06 09:31:09 -0700476 if i == 0:
477 utilities.assert_equals(
478 expect=main.TRUE,
479 actual=pingResult,
480 onpass="Reactive Pingall test passed",
481 onfail="Reactive Pingall failed, " +
482 "one or more ping pairs failed" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700483 time2 = time.time()
Jon Hall390696c2015-05-05 17:13:41 -0700484 main.log.info( "Time for pingall: %2f seconds" %
485 ( time2 - time1 ) )
486 # timeout for fwd flows
487 time.sleep( 11 )
Jon Hall6aec96b2015-01-19 14:49:31 -0800488 # uninstall onos-app-fwd
Jon Hall390696c2015-05-05 17:13:41 -0700489 main.step( "Uninstall reactive forwarding app" )
490 uninstallResult = CLIs[0].deactivateApp( "org.onosproject.fwd" )
491 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
492 onpass="Uninstall fwd successful",
493 onfail="Uninstall fwd failed" )
Jon Hallfeff3082015-05-19 10:23:26 -0700494
495 main.step( "Check app ids" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700496 threads = []
Jon Hallfeff3082015-05-19 10:23:26 -0700497 appCheck2 = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -0700498 for i in range( numControllers ):
Jon Halla9d26da2015-03-30 16:45:32 -0700499 t = main.Thread( target=CLIs[i].appToIDCheck,
500 name="appToIDCheck-" + str( i ),
501 args=[] )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700502 threads.append( t )
503 t.start()
Jon Hall73cf9cc2014-11-20 22:28:38 -0800504
Jon Hall5cfd23c2015-03-19 11:40:57 -0700505 for t in threads:
506 t.join()
Jon Hallfeff3082015-05-19 10:23:26 -0700507 appCheck2 = appCheck2 and t.result
508 if appCheck2 != main.TRUE:
Jon Halla9d26da2015-03-30 16:45:32 -0700509 main.log.warn( CLIs[0].apps() )
510 main.log.warn( CLIs[0].appIDs() )
Jon Hallfeff3082015-05-19 10:23:26 -0700511 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
Jon Hall390696c2015-05-05 17:13:41 -0700512 onpass="App Ids seem to be correct",
513 onfail="Something is wrong with app Ids" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700514
Jon Hallfeff3082015-05-19 10:23:26 -0700515 main.step( "Add host intents via cli" )
Jon Hall58c76b72015-02-23 11:09:24 -0800516 intentIds = []
Jon Hall6aec96b2015-01-19 14:49:31 -0800517 # TODO: move the host numbers to params
Jon Hall58c76b72015-02-23 11:09:24 -0800518 # Maybe look at all the paths we ping?
Jon Hall8f89dda2015-01-22 16:03:33 -0800519 intentAddResult = True
Jon Hall58c76b72015-02-23 11:09:24 -0800520 hostResult = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -0800521 for i in range( 8, 18 ):
522 main.log.info( "Adding host intent between h" + str( i ) +
523 " and h" + str( i + 10 ) )
524 host1 = "00:00:00:00:00:" + \
525 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
526 host2 = "00:00:00:00:00:" + \
527 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
Jon Hall1b8f54a2015-02-04 13:24:20 -0800528 # NOTE: getHost can return None
529 host1Dict = main.ONOScli1.getHost( host1 )
530 host2Dict = main.ONOScli1.getHost( host2 )
531 host1Id = None
532 host2Id = None
533 if host1Dict and host2Dict:
534 host1Id = host1Dict.get( 'id', None )
535 host2Id = host2Dict.get( 'id', None )
Jon Hall8f89dda2015-01-22 16:03:33 -0800536 if host1Id and host2Id:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700537 nodeNum = ( i % 7 )
538 tmpId = CLIs[ nodeNum ].addHostIntent( host1Id, host2Id )
Jon Hall63604932015-02-26 17:09:50 -0800539 if tmpId:
540 main.log.info( "Added intent with id: " + tmpId )
541 intentIds.append( tmpId )
542 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700543 main.log.error( "addHostIntent returned: " +
544 repr( tmpId ) )
Jon Hall669173b2014-12-17 11:36:30 -0800545 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700546 main.log.error( "Error, getHost() failed for h" + str( i ) +
547 " and/or h" + str( i + 10 ) )
548 hosts = CLIs[ 0 ].hosts()
549 main.log.warn( "Hosts output: " )
550 try:
551 main.log.warn( json.dumps( json.loads( hosts ),
552 sort_keys=True,
553 indent=4,
554 separators=( ',', ': ' ) ) )
555 except ( ValueError, TypeError ):
556 main.log.warn( repr( hosts ) )
Jon Hall58c76b72015-02-23 11:09:24 -0800557 hostResult = main.FALSE
Jon Hallfeff3082015-05-19 10:23:26 -0700558 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
559 onpass="Found a host id for each host",
560 onfail="Error looking up host ids" )
561
Jon Halla9d26da2015-03-30 16:45:32 -0700562 intentStart = time.time()
Jon Hall58c76b72015-02-23 11:09:24 -0800563 onosIds = main.ONOScli1.getAllIntentsId()
564 main.log.info( "Submitted intents: " + str( intentIds ) )
565 main.log.info( "Intents in ONOS: " + str( onosIds ) )
566 for intent in intentIds:
567 if intent in onosIds:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700568 pass # intent submitted is in onos
Jon Hall58c76b72015-02-23 11:09:24 -0800569 else:
570 intentAddResult = False
Jon Halla9d26da2015-03-30 16:45:32 -0700571 if intentAddResult:
572 intentStop = time.time()
573 else:
574 intentStop = None
Jon Hall1b8f54a2015-02-04 13:24:20 -0800575 # Print the intent states
Jon Hall58c76b72015-02-23 11:09:24 -0800576 intents = main.ONOScli1.intents()
Jon Hall1b8f54a2015-02-04 13:24:20 -0800577 intentStates = []
Jon Hall63604932015-02-26 17:09:50 -0800578 installedCheck = True
Jon Hall58c76b72015-02-23 11:09:24 -0800579 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
580 count = 0
Jon Hall5cfd23c2015-03-19 11:40:57 -0700581 try:
582 for intent in json.loads( intents ):
583 state = intent.get( 'state', None )
584 if "INSTALLED" not in state:
585 installedCheck = False
586 intentId = intent.get( 'id', None )
587 intentStates.append( ( intentId, state ) )
588 except ( ValueError, TypeError ):
589 main.log.exception( "Error parsing intents" )
Jon Hall58c76b72015-02-23 11:09:24 -0800590 # add submitted intents not in the store
591 tmplist = [ i for i, s in intentStates ]
592 missingIntents = False
593 for i in intentIds:
594 if i not in tmplist:
595 intentStates.append( ( i, " - " ) )
596 missingIntents = True
597 intentStates.sort()
598 for i, s in intentStates:
599 count += 1
600 main.log.info( "%-6s%-15s%-15s" %
601 ( str( count ), str( i ), str( s ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700602 leaders = main.ONOScli1.leaders()
603 try:
Jon Hallc9eabec2015-06-10 14:33:14 -0700604 missing = False
Jon Hall5cfd23c2015-03-19 11:40:57 -0700605 if leaders:
606 parsedLeaders = json.loads( leaders )
607 main.log.warn( json.dumps( parsedLeaders,
608 sort_keys=True,
609 indent=4,
610 separators=( ',', ': ' ) ) )
611 # check for all intent partitions
Jon Hall5cfd23c2015-03-19 11:40:57 -0700612 topics = []
613 for i in range( 14 ):
614 topics.append( "intent-partition-" + str( i ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700615 main.log.debug( topics )
616 ONOStopics = [ j['topic'] for j in parsedLeaders ]
617 for topic in topics:
618 if topic not in ONOStopics:
619 main.log.error( "Error: " + topic +
620 " not in leaders" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700621 missing = True
Jon Hall5cfd23c2015-03-19 11:40:57 -0700622 else:
623 main.log.error( "leaders() returned None" )
624 except ( ValueError, TypeError ):
625 main.log.exception( "Error parsing leaders" )
626 main.log.error( repr( leaders ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700627 # Check all nodes
628 if missing:
629 for node in CLIs:
630 response = node.leaders( jsonFormat=False)
631 main.log.warn( str( node.name ) + " leaders output: \n" +
632 str( response ) )
633
Jon Hall5cfd23c2015-03-19 11:40:57 -0700634 partitions = main.ONOScli1.partitions()
635 try:
636 if partitions :
637 parsedPartitions = json.loads( partitions )
638 main.log.warn( json.dumps( parsedPartitions,
639 sort_keys=True,
640 indent=4,
641 separators=( ',', ': ' ) ) )
642 # TODO check for a leader in all paritions
643 # TODO check for consistency among nodes
644 else:
645 main.log.error( "partitions() returned None" )
646 except ( ValueError, TypeError ):
647 main.log.exception( "Error parsing partitions" )
648 main.log.error( repr( partitions ) )
Jon Hall63604932015-02-26 17:09:50 -0800649 pendingMap = main.ONOScli1.pendingMap()
Jon Hall5cfd23c2015-03-19 11:40:57 -0700650 try:
651 if pendingMap :
652 parsedPending = json.loads( pendingMap )
653 main.log.warn( json.dumps( parsedPending,
654 sort_keys=True,
655 indent=4,
656 separators=( ',', ': ' ) ) )
657 # TODO check something here?
658 else:
659 main.log.error( "pendingMap() returned None" )
660 except ( ValueError, TypeError ):
661 main.log.exception( "Error parsing pending map" )
662 main.log.error( repr( pendingMap ) )
663
Jon Hallfeff3082015-05-19 10:23:26 -0700664 intentAddResult = bool( intentAddResult and not missingIntents and
665 installedCheck )
666 if not intentAddResult:
667 main.log.error( "Error in pushing host intents to ONOS" )
668
Jon Hall390696c2015-05-05 17:13:41 -0700669 main.step( "Intent Anti-Entropy dispersion" )
Jon Halla9d26da2015-03-30 16:45:32 -0700670 for i in range(100):
Jon Hall390696c2015-05-05 17:13:41 -0700671 correct = True
Jon Halla9d26da2015-03-30 16:45:32 -0700672 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Hall390696c2015-05-05 17:13:41 -0700673 for cli in CLIs:
674 onosIds = []
675 ids = cli.getAllIntentsId()
676 onosIds.append( ids )
677 main.log.debug( "Intents in " + cli.name + ": " +
678 str( sorted( onosIds ) ) )
679 if sorted( ids ) != sorted( intentIds ):
Jon Hallb87f3db2015-07-06 03:10:27 -0700680 main.log.debug( "Set of intent IDs doesn't match" )
Jon Hall390696c2015-05-05 17:13:41 -0700681 correct = False
Jon Hall40d2cbd2015-06-03 16:24:29 -0700682 break
683 else:
684 intents = json.loads( cli.intents() )
685 for intent in intents:
686 if intent[ 'state' ] != "INSTALLED":
Jon Hallc9eabec2015-06-10 14:33:14 -0700687 main.log.warn( "Intent " + intent[ 'id' ] +
688 " is " + intent[ 'state' ] )
Jon Hall40d2cbd2015-06-03 16:24:29 -0700689 correct = False
690 break
Jon Hall390696c2015-05-05 17:13:41 -0700691 if correct:
Jon Halla9d26da2015-03-30 16:45:32 -0700692 break
693 else:
694 time.sleep(1)
Jon Halla9d26da2015-03-30 16:45:32 -0700695 if not intentStop:
696 intentStop = time.time()
Jon Hall390696c2015-05-05 17:13:41 -0700697 global gossipTime
Jon Halla9d26da2015-03-30 16:45:32 -0700698 gossipTime = intentStop - intentStart
699 main.log.info( "It took about " + str( gossipTime ) +
Jon Hall390696c2015-05-05 17:13:41 -0700700 " seconds for all intents to appear in each node" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700701 append = False
702 title = "Gossip Intents"
703 count = 1
704 while append is False:
705 curTitle = title + str( count )
706 if curTitle not in labels:
707 labels.append( curTitle )
708 data.append( str( gossipTime ) )
709 append = True
710 else:
711 count += 1
Jon Halla9d26da2015-03-30 16:45:32 -0700712 # FIXME: make this time configurable/calculate based off of number of
713 # nodes and gossip rounds
714 utilities.assert_greater_equals(
Jon Hall390696c2015-05-05 17:13:41 -0700715 expect=40, actual=gossipTime,
Jon Halla9d26da2015-03-30 16:45:32 -0700716 onpass="ECM anti-entropy for intents worked within " +
717 "expected time",
718 onfail="Intent ECM anti-entropy took too long" )
Jon Hall390696c2015-05-05 17:13:41 -0700719 if gossipTime <= 40:
Jon Hall678f4512015-03-31 09:48:31 -0700720 intentAddResult = True
Jon Hall58c76b72015-02-23 11:09:24 -0800721
Jon Hall63604932015-02-26 17:09:50 -0800722 if not intentAddResult or "key" in pendingMap:
Jon Hall58c76b72015-02-23 11:09:24 -0800723 import time
Jon Hall63604932015-02-26 17:09:50 -0800724 installedCheck = True
Jon Hall58c76b72015-02-23 11:09:24 -0800725 main.log.info( "Sleeping 60 seconds to see if intents are found" )
726 time.sleep( 60 )
727 onosIds = main.ONOScli1.getAllIntentsId()
728 main.log.info( "Submitted intents: " + str( intentIds ) )
729 main.log.info( "Intents in ONOS: " + str( onosIds ) )
730 # Print the intent states
731 intents = main.ONOScli1.intents()
732 intentStates = []
733 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
734 count = 0
Jon Hall5cfd23c2015-03-19 11:40:57 -0700735 try:
736 for intent in json.loads( intents ):
737 # Iter through intents of a node
738 state = intent.get( 'state', None )
739 if "INSTALLED" not in state:
740 installedCheck = False
741 intentId = intent.get( 'id', None )
742 intentStates.append( ( intentId, state ) )
743 except ( ValueError, TypeError ):
744 main.log.exception( "Error parsing intents" )
Jon Hall58c76b72015-02-23 11:09:24 -0800745 # add submitted intents not in the store
746 tmplist = [ i for i, s in intentStates ]
747 for i in intentIds:
748 if i not in tmplist:
749 intentStates.append( ( i, " - " ) )
750 intentStates.sort()
751 for i, s in intentStates:
752 count += 1
753 main.log.info( "%-6s%-15s%-15s" %
754 ( str( count ), str( i ), str( s ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700755 leaders = main.ONOScli1.leaders()
756 try:
Jon Hallc9eabec2015-06-10 14:33:14 -0700757 missing = False
Jon Hall5cfd23c2015-03-19 11:40:57 -0700758 if leaders:
759 parsedLeaders = json.loads( leaders )
760 main.log.warn( json.dumps( parsedLeaders,
761 sort_keys=True,
762 indent=4,
763 separators=( ',', ': ' ) ) )
764 # check for all intent partitions
765 # check for election
766 topics = []
767 for i in range( 14 ):
768 topics.append( "intent-partition-" + str( i ) )
769 # FIXME: this should only be after we start the app
770 topics.append( "org.onosproject.election" )
771 main.log.debug( topics )
772 ONOStopics = [ j['topic'] for j in parsedLeaders ]
773 for topic in topics:
774 if topic not in ONOStopics:
775 main.log.error( "Error: " + topic +
776 " not in leaders" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700777 missing = True
Jon Hall5cfd23c2015-03-19 11:40:57 -0700778 else:
779 main.log.error( "leaders() returned None" )
780 except ( ValueError, TypeError ):
781 main.log.exception( "Error parsing leaders" )
782 main.log.error( repr( leaders ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700783 # Check all nodes
784 if missing:
785 for node in CLIs:
786 response = node.leaders( jsonFormat=False)
787 main.log.warn( str( node.name ) + " leaders output: \n" +
788 str( response ) )
789
Jon Hall5cfd23c2015-03-19 11:40:57 -0700790 partitions = main.ONOScli1.partitions()
791 try:
792 if partitions :
793 parsedPartitions = json.loads( partitions )
794 main.log.warn( json.dumps( parsedPartitions,
795 sort_keys=True,
796 indent=4,
797 separators=( ',', ': ' ) ) )
798 # TODO check for a leader in all paritions
799 # TODO check for consistency among nodes
800 else:
801 main.log.error( "partitions() returned None" )
802 except ( ValueError, TypeError ):
803 main.log.exception( "Error parsing partitions" )
804 main.log.error( repr( partitions ) )
805 pendingMap = main.ONOScli1.pendingMap()
806 try:
807 if pendingMap :
808 parsedPending = json.loads( pendingMap )
809 main.log.warn( json.dumps( parsedPending,
810 sort_keys=True,
811 indent=4,
812 separators=( ',', ': ' ) ) )
813 # TODO check something here?
814 else:
815 main.log.error( "pendingMap() returned None" )
816 except ( ValueError, TypeError ):
817 main.log.exception( "Error parsing pending map" )
818 main.log.error( repr( pendingMap ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800819
Jon Hall6aec96b2015-01-19 14:49:31 -0800820 def CASE4( self, main ):
Jon Hall73cf9cc2014-11-20 22:28:38 -0800821 """
822 Ping across added host intents
823 """
Jon Hall58c76b72015-02-23 11:09:24 -0800824 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -0700825 import time
826 assert numControllers, "numControllers not defined"
827 assert main, "main not defined"
828 assert utilities.assert_equals, "utilities.assert_equals not defined"
829 assert CLIs, "CLIs not defined"
830 assert nodes, "nodes not defined"
Jon Hallfeff3082015-05-19 10:23:26 -0700831 main.case( "Verify connectivity by sendind traffic across Intents" )
832 main.caseExplaination = "Ping across added host intents to check " +\
833 "functionality and check the state of " +\
834 "the intent"
835 main.step( "Ping across added host intents" )
Jon Hall8f89dda2015-01-22 16:03:33 -0800836 PingResult = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -0800837 for i in range( 8, 18 ):
Jon Hall58c76b72015-02-23 11:09:24 -0800838 ping = main.Mininet1.pingHost( src="h" + str( i ),
839 target="h" + str( i + 10 ) )
Jon Hall8f89dda2015-01-22 16:03:33 -0800840 PingResult = PingResult and ping
Jon Hall6aec96b2015-01-19 14:49:31 -0800841 if ping == main.FALSE:
842 main.log.warn( "Ping failed between h" + str( i ) +
843 " and h" + str( i + 10 ) )
844 elif ping == main.TRUE:
845 main.log.info( "Ping test passed!" )
Jon Hall21270ac2015-02-16 17:59:55 -0800846 # Don't set PingResult or you'd override failures
Jon Hall8f89dda2015-01-22 16:03:33 -0800847 if PingResult == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -0700848 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -0800849 "Intents have not been installed correctly, pings failed." )
Jon Hall58c76b72015-02-23 11:09:24 -0800850 # TODO: pretty print
Jon Hall5cfd23c2015-03-19 11:40:57 -0700851 main.log.warn( "ONOS1 intents: " )
852 try:
853 tmpIntents = main.ONOScli1.intents()
854 main.log.warn( json.dumps( json.loads( tmpIntents ),
855 sort_keys=True,
856 indent=4,
857 separators=( ',', ': ' ) ) )
858 except ( ValueError, TypeError ):
859 main.log.warn( repr( tmpIntents ) )
Jon Hall6aec96b2015-01-19 14:49:31 -0800860 utilities.assert_equals(
861 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800862 actual=PingResult,
Jon Hall6aec96b2015-01-19 14:49:31 -0800863 onpass="Intents have been installed correctly and pings work",
864 onfail="Intents have not been installed correctly, pings failed." )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800865
Jon Hallfeff3082015-05-19 10:23:26 -0700866 main.step( "Check Intent state" )
Jon Hall40d2cbd2015-06-03 16:24:29 -0700867 installedCheck = False
Jon Hallc9eabec2015-06-10 14:33:14 -0700868 loopCount = 0
869 while not installedCheck and loopCount < 40:
Jon Hall40d2cbd2015-06-03 16:24:29 -0700870 installedCheck = True
871 # Print the intent states
872 intents = main.ONOScli1.intents()
873 intentStates = []
874 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
Jon Hall40d2cbd2015-06-03 16:24:29 -0700875 # Iter through intents of a node
876 try:
877 for intent in json.loads( intents ):
878 state = intent.get( 'state', None )
879 if "INSTALLED" not in state:
880 installedCheck = False
881 intentId = intent.get( 'id', None )
882 intentStates.append( ( intentId, state ) )
883 except ( ValueError, TypeError ):
884 main.log.exception( "Error parsing intents." )
885 # Print states
886 intentStates.sort()
887 for i, s in intentStates:
888 count += 1
889 main.log.info( "%-6s%-15s%-15s" %
890 ( str( count ), str( i ), str( s ) ) )
891 if not installedCheck:
892 time.sleep( 1 )
Jon Hallc9eabec2015-06-10 14:33:14 -0700893 loopCount += 1
Jon Hallfeff3082015-05-19 10:23:26 -0700894 utilities.assert_equals( expect=True, actual=installedCheck,
895 onpass="Intents are all INSTALLED",
Jon Hall40d2cbd2015-06-03 16:24:29 -0700896 onfail="Intents are not all in " +
Jon Hallfeff3082015-05-19 10:23:26 -0700897 "INSTALLED state" )
898
899 main.step( "Check leadership of topics" )
900 leaders = main.ONOScli1.leaders()
901 topicCheck = main.TRUE
902 try:
903 if leaders:
904 parsedLeaders = json.loads( leaders )
905 main.log.warn( json.dumps( parsedLeaders,
906 sort_keys=True,
907 indent=4,
908 separators=( ',', ': ' ) ) )
909 # check for all intent partitions
910 # check for election
911 # TODO: Look at Devices as topics now that it uses this system
912 topics = []
913 for i in range( 14 ):
914 topics.append( "intent-partition-" + str( i ) )
915 # FIXME: this should only be after we start the app
916 # FIXME: topics.append( "org.onosproject.election" )
917 # Print leaders output
918 main.log.debug( topics )
919 ONOStopics = [ j['topic'] for j in parsedLeaders ]
920 for topic in topics:
921 if topic not in ONOStopics:
922 main.log.error( "Error: " + topic +
923 " not in leaders" )
924 topicCheck = main.FALSE
925 else:
926 main.log.error( "leaders() returned None" )
927 topicCheck = main.FALSE
928 except ( ValueError, TypeError ):
929 topicCheck = main.FALSE
930 main.log.exception( "Error parsing leaders" )
931 main.log.error( repr( leaders ) )
932 # TODO: Check for a leader of these topics
Jon Hallc9eabec2015-06-10 14:33:14 -0700933 # Check all nodes
934 if topicCheck:
935 for node in CLIs:
936 response = node.leaders( jsonFormat=False)
937 main.log.warn( str( node.name ) + " leaders output: \n" +
938 str( response ) )
939
Jon Hallfeff3082015-05-19 10:23:26 -0700940 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
941 onpass="intent Partitions is in leaders",
942 onfail="Some topics were lost " )
943 # Print partitions
944 partitions = main.ONOScli1.partitions()
945 try:
946 if partitions :
947 parsedPartitions = json.loads( partitions )
948 main.log.warn( json.dumps( parsedPartitions,
949 sort_keys=True,
950 indent=4,
951 separators=( ',', ': ' ) ) )
952 # TODO check for a leader in all paritions
953 # TODO check for consistency among nodes
954 else:
955 main.log.error( "partitions() returned None" )
956 except ( ValueError, TypeError ):
957 main.log.exception( "Error parsing partitions" )
958 main.log.error( repr( partitions ) )
959 # Print Pending Map
960 pendingMap = main.ONOScli1.pendingMap()
961 try:
962 if pendingMap :
963 parsedPending = json.loads( pendingMap )
964 main.log.warn( json.dumps( parsedPending,
965 sort_keys=True,
966 indent=4,
967 separators=( ',', ': ' ) ) )
968 # TODO check something here?
969 else:
970 main.log.error( "pendingMap() returned None" )
971 except ( ValueError, TypeError ):
972 main.log.exception( "Error parsing pending map" )
973 main.log.error( repr( pendingMap ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700974
Jon Hall63604932015-02-26 17:09:50 -0800975 if not installedCheck:
Jon Hallc9eabec2015-06-10 14:33:14 -0700976 main.log.info( "Waiting 60 seconds to see if the state of " +
977 "intents change" )
978 time.sleep( 60 )
Jon Hall63604932015-02-26 17:09:50 -0800979 # Print the intent states
980 intents = main.ONOScli1.intents()
981 intentStates = []
982 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
983 count = 0
984 # Iter through intents of a node
Jon Hall5cfd23c2015-03-19 11:40:57 -0700985 try:
986 for intent in json.loads( intents ):
987 state = intent.get( 'state', None )
988 if "INSTALLED" not in state:
989 installedCheck = False
990 intentId = intent.get( 'id', None )
991 intentStates.append( ( intentId, state ) )
992 except ( ValueError, TypeError ):
993 main.log.exception( "Error parsing intents." )
Jon Hall63604932015-02-26 17:09:50 -0800994 intentStates.sort()
995 for i, s in intentStates:
996 count += 1
997 main.log.info( "%-6s%-15s%-15s" %
998 ( str( count ), str( i ), str( s ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700999 leaders = main.ONOScli1.leaders()
1000 try:
Jon Hallc9eabec2015-06-10 14:33:14 -07001001 missing = False
Jon Hall5cfd23c2015-03-19 11:40:57 -07001002 if leaders:
1003 parsedLeaders = json.loads( leaders )
1004 main.log.warn( json.dumps( parsedLeaders,
1005 sort_keys=True,
1006 indent=4,
1007 separators=( ',', ': ' ) ) )
1008 # check for all intent partitions
1009 # check for election
1010 topics = []
1011 for i in range( 14 ):
1012 topics.append( "intent-partition-" + str( i ) )
1013 # FIXME: this should only be after we start the app
1014 topics.append( "org.onosproject.election" )
1015 main.log.debug( topics )
1016 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1017 for topic in topics:
1018 if topic not in ONOStopics:
1019 main.log.error( "Error: " + topic +
1020 " not in leaders" )
Jon Hallc9eabec2015-06-10 14:33:14 -07001021 missing = True
Jon Hall5cfd23c2015-03-19 11:40:57 -07001022 else:
1023 main.log.error( "leaders() returned None" )
1024 except ( ValueError, TypeError ):
1025 main.log.exception( "Error parsing leaders" )
1026 main.log.error( repr( leaders ) )
Jon Hallc9eabec2015-06-10 14:33:14 -07001027 if missing:
1028 for node in CLIs:
1029 response = node.leaders( jsonFormat=False)
1030 main.log.warn( str( node.name ) + " leaders output: \n" +
1031 str( response ) )
1032
Jon Hall5cfd23c2015-03-19 11:40:57 -07001033 partitions = main.ONOScli1.partitions()
1034 try:
1035 if partitions :
1036 parsedPartitions = json.loads( partitions )
1037 main.log.warn( json.dumps( parsedPartitions,
1038 sort_keys=True,
1039 indent=4,
1040 separators=( ',', ': ' ) ) )
1041 # TODO check for a leader in all paritions
1042 # TODO check for consistency among nodes
1043 else:
1044 main.log.error( "partitions() returned None" )
1045 except ( ValueError, TypeError ):
1046 main.log.exception( "Error parsing partitions" )
1047 main.log.error( repr( partitions ) )
1048 pendingMap = main.ONOScli1.pendingMap()
1049 try:
1050 if pendingMap :
1051 parsedPending = json.loads( pendingMap )
1052 main.log.warn( json.dumps( parsedPending,
1053 sort_keys=True,
1054 indent=4,
1055 separators=( ',', ': ' ) ) )
1056 # TODO check something here?
1057 else:
1058 main.log.error( "pendingMap() returned None" )
1059 except ( ValueError, TypeError ):
1060 main.log.exception( "Error parsing pending map" )
1061 main.log.error( repr( pendingMap ) )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001062 # Print flowrules
1063 main.log.debug( CLIs[0].flows( jsonFormat=False ) )
Jon Hallfeff3082015-05-19 10:23:26 -07001064 main.step( "Wait a minute then ping again" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001065 # the wait is above
Jon Hallfeff3082015-05-19 10:23:26 -07001066 PingResult = main.TRUE
1067 for i in range( 8, 18 ):
1068 ping = main.Mininet1.pingHost( src="h" + str( i ),
1069 target="h" + str( i + 10 ) )
1070 PingResult = PingResult and ping
1071 if ping == main.FALSE:
1072 main.log.warn( "Ping failed between h" + str( i ) +
1073 " and h" + str( i + 10 ) )
1074 elif ping == main.TRUE:
1075 main.log.info( "Ping test passed!" )
1076 # Don't set PingResult or you'd override failures
1077 if PingResult == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001078 main.log.error(
Jon Hallfeff3082015-05-19 10:23:26 -07001079 "Intents have not been installed correctly, pings failed." )
1080 # TODO: pretty print
1081 main.log.warn( "ONOS1 intents: " )
1082 try:
1083 tmpIntents = main.ONOScli1.intents()
1084 main.log.warn( json.dumps( json.loads( tmpIntents ),
1085 sort_keys=True,
1086 indent=4,
1087 separators=( ',', ': ' ) ) )
1088 except ( ValueError, TypeError ):
1089 main.log.warn( repr( tmpIntents ) )
1090 utilities.assert_equals(
1091 expect=main.TRUE,
1092 actual=PingResult,
1093 onpass="Intents have been installed correctly and pings work",
1094 onfail="Intents have not been installed correctly, pings failed." )
1095
Jon Hall6aec96b2015-01-19 14:49:31 -08001096 def CASE5( self, main ):
1097 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001098 Reading state of ONOS
Jon Hall6aec96b2015-01-19 14:49:31 -08001099 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001100 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -07001101 import time
1102 assert numControllers, "numControllers not defined"
1103 assert main, "main not defined"
1104 assert utilities.assert_equals, "utilities.assert_equals not defined"
1105 assert CLIs, "CLIs not defined"
1106 assert nodes, "nodes not defined"
Jon Hallb87f3db2015-07-06 03:10:27 -07001107 # assumes that sts is already in you PYTHONPATH
1108 from sts.topology.teston_topology import TestONTopology
Jon Hall73cf9cc2014-11-20 22:28:38 -08001109
Jon Hall6aec96b2015-01-19 14:49:31 -08001110 main.case( "Setting up and gathering data for current state" )
1111 # The general idea for this test case is to pull the state of
1112 # ( intents,flows, topology,... ) from each ONOS node
Jon Hall5cfd23c2015-03-19 11:40:57 -07001113 # We can then compare them with each other and also with past states
Jon Hall73cf9cc2014-11-20 22:28:38 -08001114
Jon Hall5cfd23c2015-03-19 11:40:57 -07001115 main.step( "Check that each switch has a master" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001116 global mastershipState
Jon Hall5cfd23c2015-03-19 11:40:57 -07001117 mastershipState = '[]'
Jon Hall94fd0472014-12-08 11:52:42 -08001118
Jon Hall6aec96b2015-01-19 14:49:31 -08001119 # Assert that each device has a master
Jon Hall5cfd23c2015-03-19 11:40:57 -07001120 rolesNotNull = main.TRUE
1121 threads = []
1122 for i in range( numControllers ):
1123 t = main.Thread( target=CLIs[i].rolesNotNull,
1124 name="rolesNotNull-" + str( i ),
1125 args=[] )
1126 threads.append( t )
1127 t.start()
1128
1129 for t in threads:
1130 t.join()
1131 rolesNotNull = rolesNotNull and t.result
Jon Hall6aec96b2015-01-19 14:49:31 -08001132 utilities.assert_equals(
1133 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001134 actual=rolesNotNull,
Jon Hall6aec96b2015-01-19 14:49:31 -08001135 onpass="Each device has a master",
1136 onfail="Some devices don't have a master assigned" )
Jon Hall94fd0472014-12-08 11:52:42 -08001137
Jon Hall5cfd23c2015-03-19 11:40:57 -07001138 main.step( "Get the Mastership of each switch from each controller" )
1139 ONOSMastership = []
1140 mastershipCheck = main.FALSE
1141 consistentMastership = True
1142 rolesResults = True
1143 threads = []
1144 for i in range( numControllers ):
1145 t = main.Thread( target=CLIs[i].roles,
1146 name="roles-" + str( i ),
1147 args=[] )
1148 threads.append( t )
1149 t.start()
1150
1151 for t in threads:
1152 t.join()
1153 ONOSMastership.append( t.result )
1154
1155 for i in range( numControllers ):
1156 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001157 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001158 " roles" )
1159 main.log.warn(
1160 "ONOS" + str( i + 1 ) + " mastership response: " +
1161 repr( ONOSMastership[i] ) )
1162 rolesResults = False
1163 utilities.assert_equals(
1164 expect=True,
1165 actual=rolesResults,
1166 onpass="No error in reading roles output",
1167 onfail="Error in reading roles from ONOS" )
1168
1169 main.step( "Check for consistency in roles from each controller" )
1170 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001171 main.log.info(
Jon Hall6aec96b2015-01-19 14:49:31 -08001172 "Switch roles are consistent across all ONOS nodes" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001173 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001174 consistentMastership = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001175 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001176 expect=True,
Jon Hall8f89dda2015-01-22 16:03:33 -08001177 actual=consistentMastership,
Jon Hall6aec96b2015-01-19 14:49:31 -08001178 onpass="Switch roles are consistent across all ONOS nodes",
1179 onfail="ONOS nodes have different views of switch roles" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001180
Jon Hall5cfd23c2015-03-19 11:40:57 -07001181 if rolesResults and not consistentMastership:
1182 for i in range( numControllers ):
1183 try:
1184 main.log.warn(
1185 "ONOS" + str( i + 1 ) + " roles: ",
1186 json.dumps(
1187 json.loads( ONOSMastership[ i ] ),
1188 sort_keys=True,
1189 indent=4,
1190 separators=( ',', ': ' ) ) )
1191 except ( ValueError, TypeError ):
1192 main.log.warn( repr( ONOSMastership[ i ] ) )
1193 elif rolesResults and consistentMastership:
1194 mastershipCheck = main.TRUE
1195 mastershipState = ONOSMastership[ 0 ]
1196
Jon Hall6aec96b2015-01-19 14:49:31 -08001197 main.step( "Get the intents from each controller" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001198 global intentState
1199 intentState = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001200 ONOSIntents = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001201 intentCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001202 consistentIntents = True
1203 intentsResults = True
1204 threads = []
1205 for i in range( numControllers ):
1206 t = main.Thread( target=CLIs[i].intents,
1207 name="intents-" + str( i ),
1208 args=[],
1209 kwargs={ 'jsonFormat': True } )
1210 threads.append( t )
1211 t.start()
1212
1213 for t in threads:
1214 t.join()
1215 ONOSIntents.append( t.result )
1216
1217 for i in range( numControllers ):
1218 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001219 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001220 " intents" )
1221 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1222 repr( ONOSIntents[ i ] ) )
1223 intentsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001224 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001225 expect=True,
1226 actual=intentsResults,
1227 onpass="No error in reading intents output",
1228 onfail="Error in reading intents from ONOS" )
1229
1230 main.step( "Check for consistency in Intents from each controller" )
1231 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001232 main.log.info( "Intents are consistent across all ONOS " +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001233 "nodes" )
1234 else:
1235 consistentIntents = False
Jon Hall40d2cbd2015-06-03 16:24:29 -07001236 main.log.error( "Intents not consistent" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001237 utilities.assert_equals(
1238 expect=True,
1239 actual=consistentIntents,
Jon Hall6aec96b2015-01-19 14:49:31 -08001240 onpass="Intents are consistent across all ONOS nodes",
1241 onfail="ONOS nodes have different views of intents" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001242
Jon Hall390696c2015-05-05 17:13:41 -07001243 if intentsResults:
1244 # Try to make it easy to figure out what is happening
1245 #
1246 # Intent ONOS1 ONOS2 ...
1247 # 0x01 INSTALLED INSTALLING
1248 # ... ... ...
1249 # ... ... ...
1250 title = " Id"
1251 for n in range( numControllers ):
1252 title += " " * 10 + "ONOS" + str( n + 1 )
1253 main.log.warn( title )
1254 # get all intent keys in the cluster
1255 keys = []
1256 for nodeStr in ONOSIntents:
1257 node = json.loads( nodeStr )
1258 for intent in node:
1259 keys.append( intent.get( 'id' ) )
1260 keys = set( keys )
1261 for key in keys:
1262 row = "%-13s" % key
1263 for nodeStr in ONOSIntents:
1264 node = json.loads( nodeStr )
1265 for intent in node:
1266 if intent.get( 'id', "Error" ) == key:
1267 row += "%-15s" % intent.get( 'state' )
1268 main.log.warn( row )
1269 # End table view
1270
Jon Hall5cfd23c2015-03-19 11:40:57 -07001271 if intentsResults and not consistentIntents:
Jon Hall390696c2015-05-05 17:13:41 -07001272 # print the json objects
Jon Hall5cfd23c2015-03-19 11:40:57 -07001273 n = len(ONOSIntents)
Jon Hall390696c2015-05-05 17:13:41 -07001274 main.log.debug( "ONOS" + str( n ) + " intents: " )
1275 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1276 sort_keys=True,
1277 indent=4,
1278 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001279 for i in range( numControllers ):
1280 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hall390696c2015-05-05 17:13:41 -07001281 main.log.debug( "ONOS" + str( i + 1 ) + " intents: " )
1282 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1283 sort_keys=True,
1284 indent=4,
1285 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001286 else:
Jon Hall390696c2015-05-05 17:13:41 -07001287 main.log.debug( nodes[ i ].name + " intents match ONOS" +
1288 str( n ) + " intents" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001289 elif intentsResults and consistentIntents:
1290 intentCheck = main.TRUE
1291 intentState = ONOSIntents[ 0 ]
1292
Jon Hall6aec96b2015-01-19 14:49:31 -08001293 main.step( "Get the flows from each controller" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001294 global flowState
1295 flowState = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001296 ONOSFlows = []
1297 ONOSFlowsJson = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001298 flowCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001299 consistentFlows = True
1300 flowsResults = True
1301 threads = []
1302 for i in range( numControllers ):
1303 t = main.Thread( target=CLIs[i].flows,
1304 name="flows-" + str( i ),
1305 args=[],
1306 kwargs={ 'jsonFormat': True } )
1307 threads.append( t )
1308 t.start()
1309
Jon Halla9d26da2015-03-30 16:45:32 -07001310 # NOTE: Flows command can take some time to run
Jon Hall5cfd23c2015-03-19 11:40:57 -07001311 time.sleep(30)
1312 for t in threads:
1313 t.join()
1314 result = t.result
1315 ONOSFlows.append( result )
1316
1317 for i in range( numControllers ):
1318 num = str( i + 1 )
1319 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001320 main.log.error( "Error in getting ONOS" + num + " flows" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001321 main.log.warn( "ONOS" + num + " flows response: " +
1322 repr( ONOSFlows[ i ] ) )
1323 flowsResults = False
1324 ONOSFlowsJson.append( None )
Jon Hall58c76b72015-02-23 11:09:24 -08001325 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001326 try:
1327 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1328 except ( ValueError, TypeError ):
1329 # FIXME: change this to log.error?
1330 main.log.exception( "Error in parsing ONOS" + num +
1331 " response as json." )
1332 main.log.error( repr( ONOSFlows[ i ] ) )
1333 ONOSFlowsJson.append( None )
1334 flowsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001335 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001336 expect=True,
1337 actual=flowsResults,
1338 onpass="No error in reading flows output",
1339 onfail="Error in reading flows from ONOS" )
1340
1341 main.step( "Check for consistency in Flows from each controller" )
1342 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1343 if all( tmp ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001344 main.log.info( "Flow count is consistent across all ONOS nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001345 else:
1346 consistentFlows = False
1347 utilities.assert_equals(
1348 expect=True,
1349 actual=consistentFlows,
Jon Hall6aec96b2015-01-19 14:49:31 -08001350 onpass="The flow count is consistent across all ONOS nodes",
1351 onfail="ONOS nodes have different flow counts" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001352
Jon Hall5cfd23c2015-03-19 11:40:57 -07001353 if flowsResults and not consistentFlows:
1354 for i in range( numControllers ):
1355 try:
1356 main.log.warn(
1357 "ONOS" + str( i + 1 ) + " flows: " +
1358 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1359 indent=4, separators=( ',', ': ' ) ) )
1360 except ( ValueError, TypeError ):
1361 main.log.warn(
1362 "ONOS" + str( i + 1 ) + " flows: " +
1363 repr( ONOSFlows[ i ] ) )
1364 elif flowsResults and consistentFlows:
1365 flowCheck = main.TRUE
1366 flowState = ONOSFlows[ 0 ]
1367
Jon Hall6aec96b2015-01-19 14:49:31 -08001368 main.step( "Get the OF Table entries" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001369 global flows
Jon Hall6aec96b2015-01-19 14:49:31 -08001370 flows = []
1371 for i in range( 1, 29 ):
Jon Hall8f89dda2015-01-22 16:03:33 -08001372 flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001373 if flowCheck == main.FALSE:
1374 for table in flows:
1375 main.log.warn( table )
Jon Hall6aec96b2015-01-19 14:49:31 -08001376 # TODO: Compare switch flow tables with ONOS flow tables
Jon Hall73cf9cc2014-11-20 22:28:38 -08001377
Jon Hall6aec96b2015-01-19 14:49:31 -08001378 main.step( "Start continuous pings" )
1379 main.Mininet2.pingLong(
1380 src=main.params[ 'PING' ][ 'source1' ],
1381 target=main.params[ 'PING' ][ 'target1' ],
1382 pingTime=500 )
1383 main.Mininet2.pingLong(
1384 src=main.params[ 'PING' ][ 'source2' ],
1385 target=main.params[ 'PING' ][ 'target2' ],
1386 pingTime=500 )
1387 main.Mininet2.pingLong(
1388 src=main.params[ 'PING' ][ 'source3' ],
1389 target=main.params[ 'PING' ][ 'target3' ],
1390 pingTime=500 )
1391 main.Mininet2.pingLong(
1392 src=main.params[ 'PING' ][ 'source4' ],
1393 target=main.params[ 'PING' ][ 'target4' ],
1394 pingTime=500 )
1395 main.Mininet2.pingLong(
1396 src=main.params[ 'PING' ][ 'source5' ],
1397 target=main.params[ 'PING' ][ 'target5' ],
1398 pingTime=500 )
1399 main.Mininet2.pingLong(
1400 src=main.params[ 'PING' ][ 'source6' ],
1401 target=main.params[ 'PING' ][ 'target6' ],
1402 pingTime=500 )
1403 main.Mininet2.pingLong(
1404 src=main.params[ 'PING' ][ 'source7' ],
1405 target=main.params[ 'PING' ][ 'target7' ],
1406 pingTime=500 )
1407 main.Mininet2.pingLong(
1408 src=main.params[ 'PING' ][ 'source8' ],
1409 target=main.params[ 'PING' ][ 'target8' ],
1410 pingTime=500 )
1411 main.Mininet2.pingLong(
1412 src=main.params[ 'PING' ][ 'source9' ],
1413 target=main.params[ 'PING' ][ 'target9' ],
1414 pingTime=500 )
1415 main.Mininet2.pingLong(
1416 src=main.params[ 'PING' ][ 'source10' ],
1417 target=main.params[ 'PING' ][ 'target10' ],
1418 pingTime=500 )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001419
Jon Hallb87f3db2015-07-06 03:10:27 -07001420 main.step( "Create TestONTopology object" )
1421 ctrls = []
1422 for node in nodes:
1423 temp = ( node, node.name, node.ip_address, 6633 )
1424 ctrls.append( temp )
1425 MNTopo = TestONTopology( main.Mininet1, ctrls )
1426
Jon Hall6aec96b2015-01-19 14:49:31 -08001427 main.step( "Collecting topology information from ONOS" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001428 devices = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001429 threads = []
1430 for i in range( numControllers ):
1431 t = main.Thread( target=CLIs[i].devices,
1432 name="devices-" + str( i ),
1433 args=[ ] )
1434 threads.append( t )
1435 t.start()
1436
1437 for t in threads:
1438 t.join()
1439 devices.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001440 hosts = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001441 threads = []
1442 for i in range( numControllers ):
1443 t = main.Thread( target=CLIs[i].hosts,
1444 name="hosts-" + str( i ),
1445 args=[ ] )
1446 threads.append( t )
1447 t.start()
1448
1449 for t in threads:
1450 t.join()
1451 try:
1452 hosts.append( json.loads( t.result ) )
1453 except ( ValueError, TypeError ):
1454 # FIXME: better handling of this, print which node
1455 # Maybe use thread name?
1456 main.log.exception( "Error parsing json output of hosts" )
1457 # FIXME: should this be an empty json object instead?
1458 hosts.append( None )
1459
Jon Hall73cf9cc2014-11-20 22:28:38 -08001460 ports = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001461 threads = []
1462 for i in range( numControllers ):
1463 t = main.Thread( target=CLIs[i].ports,
1464 name="ports-" + str( i ),
1465 args=[ ] )
1466 threads.append( t )
1467 t.start()
1468
1469 for t in threads:
1470 t.join()
1471 ports.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001472 links = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001473 threads = []
1474 for i in range( numControllers ):
1475 t = main.Thread( target=CLIs[i].links,
1476 name="links-" + str( i ),
1477 args=[ ] )
1478 threads.append( t )
1479 t.start()
1480
1481 for t in threads:
1482 t.join()
1483 links.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08001484 clusters = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001485 threads = []
1486 for i in range( numControllers ):
1487 t = main.Thread( target=CLIs[i].clusters,
1488 name="clusters-" + str( i ),
1489 args=[ ] )
1490 threads.append( t )
1491 t.start()
1492
1493 for t in threads:
1494 t.join()
1495 clusters.append( t.result )
Jon Hall529a37f2015-01-28 10:02:00 -08001496 # Compare json objects for hosts and dataplane clusters
Jon Hall94fd0472014-12-08 11:52:42 -08001497
Jon Hall6aec96b2015-01-19 14:49:31 -08001498 # hosts
Jon Hall390696c2015-05-05 17:13:41 -07001499 main.step( "Host view is consistent across ONOS nodes" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001500 consistentHostsResult = main.TRUE
Jon Hall94fd0472014-12-08 11:52:42 -08001501 for controller in range( len( hosts ) ):
Jon Hall8f89dda2015-01-22 16:03:33 -08001502 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08001503 if "Error" not in hosts[ controller ]:
1504 if hosts[ controller ] == hosts[ 0 ]:
Jon Hall94fd0472014-12-08 11:52:42 -08001505 continue
Jon Hall6aec96b2015-01-19 14:49:31 -08001506 else: # hosts not consistent
Jon Hall40d2cbd2015-06-03 16:24:29 -07001507 main.log.error( "hosts from ONOS" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001508 controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001509 " is inconsistent with ONOS1" )
1510 main.log.warn( repr( hosts[ controller ] ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001511 consistentHostsResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08001512
1513 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001514 main.log.error( "Error in getting ONOS hosts from ONOS" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001515 controllerStr )
1516 consistentHostsResult = main.FALSE
1517 main.log.warn( "ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001518 " hosts response: " +
1519 repr( hosts[ controller ] ) )
1520 utilities.assert_equals(
1521 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001522 actual=consistentHostsResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08001523 onpass="Hosts view is consistent across all ONOS nodes",
1524 onfail="ONOS nodes have different views of hosts" )
Jon Hall94fd0472014-12-08 11:52:42 -08001525
Jon Hall390696c2015-05-05 17:13:41 -07001526 main.step( "Each host has an IP address" )
Jon Hall58c76b72015-02-23 11:09:24 -08001527 ipResult = main.TRUE
1528 for controller in range( 0, len( hosts ) ):
1529 controllerStr = str( controller + 1 )
1530 for host in hosts[ controller ]:
Jon Hallfeff3082015-05-19 10:23:26 -07001531 if not host.get( 'ipAddresses', [ ] ):
Jon Hall5cfd23c2015-03-19 11:40:57 -07001532 main.log.error( "DEBUG:Error with host ips on controller" +
1533 controllerStr + ": " + str( host ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001534 ipResult = main.FALSE
1535 utilities.assert_equals(
1536 expect=main.TRUE,
1537 actual=ipResult,
1538 onpass="The ips of the hosts aren't empty",
1539 onfail="The ip of at least one host is missing" )
1540
Jon Hall6aec96b2015-01-19 14:49:31 -08001541 # Strongly connected clusters of devices
Jon Hall390696c2015-05-05 17:13:41 -07001542 main.step( "Cluster view is consistent across ONOS nodes" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001543 consistentClustersResult = main.TRUE
Jon Hall94fd0472014-12-08 11:52:42 -08001544 for controller in range( len( clusters ) ):
Jon Hall5cfd23c2015-03-19 11:40:57 -07001545 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08001546 if "Error" not in clusters[ controller ]:
1547 if clusters[ controller ] == clusters[ 0 ]:
Jon Hall94fd0472014-12-08 11:52:42 -08001548 continue
Jon Hall6aec96b2015-01-19 14:49:31 -08001549 else: # clusters not consistent
Jon Hall40d2cbd2015-06-03 16:24:29 -07001550 main.log.error( "clusters from ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001551 " is inconsistent with ONOS1" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001552 consistentClustersResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08001553
1554 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001555 main.log.error( "Error in getting dataplane clusters " +
Jon Hall8f89dda2015-01-22 16:03:33 -08001556 "from ONOS" + controllerStr )
1557 consistentClustersResult = main.FALSE
1558 main.log.warn( "ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001559 " clusters response: " +
1560 repr( clusters[ controller ] ) )
1561 utilities.assert_equals(
1562 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001563 actual=consistentClustersResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08001564 onpass="Clusters view is consistent across all ONOS nodes",
1565 onfail="ONOS nodes have different views of clusters" )
1566 # there should always only be one cluster
Jon Hall390696c2015-05-05 17:13:41 -07001567 main.step( "Cluster view correct across ONOS nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001568 try:
1569 numClusters = len( json.loads( clusters[ 0 ] ) )
1570 except ( ValueError, TypeError ):
1571 main.log.exception( "Error parsing clusters[0]: " +
1572 repr( clusters[ 0 ] ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001573 clusterResults = main.FALSE
1574 if numClusters == 1:
1575 clusterResults = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08001576 utilities.assert_equals(
1577 expect=1,
Jon Hall8f89dda2015-01-22 16:03:33 -08001578 actual=numClusters,
Jon Hall6aec96b2015-01-19 14:49:31 -08001579 onpass="ONOS shows 1 SCC",
Jon Hall58c76b72015-02-23 11:09:24 -08001580 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
Jon Hall94fd0472014-12-08 11:52:42 -08001581
Jon Hall6aec96b2015-01-19 14:49:31 -08001582 main.step( "Comparing ONOS topology to MN" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001583 devicesResults = main.TRUE
Jon Hallb87f3db2015-07-06 03:10:27 -07001584 portsResults = main.TRUE
Jon Hall8f89dda2015-01-22 16:03:33 -08001585 linksResults = main.TRUE
1586 for controller in range( numControllers ):
1587 controllerStr = str( controller + 1 )
Jon Hallb87f3db2015-07-06 03:10:27 -07001588 if devices[ controller ] or "Error" not in devices[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08001589 currentDevicesResult = main.Mininet1.compareSwitches(
Jon Hallb87f3db2015-07-06 03:10:27 -07001590 MNTopo,
1591 json.loads( devices[ controller ] ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001592 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08001593 currentDevicesResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001594 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08001595 actual=currentDevicesResult,
1596 onpass="ONOS" + controllerStr +
1597 " Switches view is correct",
1598 onfail="ONOS" + controllerStr +
1599 " Switches view is incorrect" )
Jon Hallb87f3db2015-07-06 03:10:27 -07001600
1601 if ports[ controller ] or "Error" not in ports[ controller ]:
1602 currentPortsResult = main.Mininet1.comparePorts(
1603 MNTopo,
1604 json.loads( ports[ controller ] ) )
1605 else:
1606 currentPortsResult = main.FALSE
1607 utilities.assert_equals( expect=main.TRUE,
1608 actual=currentPortsResult,
1609 onpass="ONOS" + controllerStr +
1610 " ports view is correct",
1611 onfail="ONOS" + controllerStr +
1612 " ports view is incorrect" )
1613
1614 if links[ controller ] or "Error" not in links[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08001615 currentLinksResult = main.Mininet1.compareLinks(
Jon Hallb87f3db2015-07-06 03:10:27 -07001616 MNTopo,
1617 json.loads( links[ controller ] ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001618 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08001619 currentLinksResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001620 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08001621 actual=currentLinksResult,
1622 onpass="ONOS" + controllerStr +
1623 " links view is correct",
1624 onfail="ONOS" + controllerStr +
1625 " links view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001626
Jon Hallb6a54872015-06-12 14:02:42 -07001627 devicesResults = devicesResults and currentDevicesResult
Jon Hallb87f3db2015-07-06 03:10:27 -07001628 portsResults = portsResults and currentPortsResult
Jon Hallb6a54872015-06-12 14:02:42 -07001629 linksResults = linksResults and currentLinksResult
Jon Hallb6a54872015-06-12 14:02:42 -07001630
Jon Hallb87f3db2015-07-06 03:10:27 -07001631 topoResult = ( devicesResults and portsResults and linksResults
1632 and consistentHostsResult and consistentClustersResult
1633 and clusterResults and ipResult )
1634 utilities.assert_equals( expect=main.TRUE, actual=topoResult,
1635 onpass="Topology Check Test successful",
1636 onfail="Topology Check Test NOT successful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001637
Jon Hall6aec96b2015-01-19 14:49:31 -08001638 def CASE6( self, main ):
1639 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001640 The Failure case.
Jon Hall6aec96b2015-01-19 14:49:31 -08001641 """
Jon Hallfeff3082015-05-19 10:23:26 -07001642 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07001643 assert numControllers, "numControllers not defined"
1644 assert main, "main not defined"
1645 assert utilities.assert_equals, "utilities.assert_equals not defined"
1646 assert CLIs, "CLIs not defined"
1647 assert nodes, "nodes not defined"
Jon Hallc9eabec2015-06-10 14:33:14 -07001648 try:
1649 labels
1650 except NameError:
1651 main.log.error( "labels not defined, setting to []" )
1652 global labels
1653 labels = []
1654 try:
1655 data
1656 except NameError:
1657 main.log.error( "data not defined, setting to []" )
1658 global data
1659 data = []
Jon Hall390696c2015-05-05 17:13:41 -07001660 # Reset non-persistent variables
1661 try:
1662 iCounterValue = 0
1663 except NameError:
1664 main.log.error( "iCounterValue not defined, setting to 0" )
1665 iCounterValue = 0
1666
Jon Hall5cfd23c2015-03-19 11:40:57 -07001667 main.case( "Restart entire ONOS cluster" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001668
Jon Hall5cfd23c2015-03-19 11:40:57 -07001669 main.step( "Killing ONOS nodes" )
1670 killResults = main.TRUE
Jon Hallfeff3082015-05-19 10:23:26 -07001671 killTime = time.time()
Jon Hall5cfd23c2015-03-19 11:40:57 -07001672 for node in nodes:
1673 killed = main.ONOSbench.onosKill( node.ip_address )
1674 killResults = killResults and killed
Jon Hall390696c2015-05-05 17:13:41 -07001675 utilities.assert_equals( expect=main.TRUE, actual=killResults,
1676 onpass="ONOS nodes killed",
1677 onfail="ONOS kill unsuccessful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001678
Jon Hall6aec96b2015-01-19 14:49:31 -08001679 main.step( "Checking if ONOS is up yet" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001680 for i in range( 2 ):
1681 onosIsupResult = main.TRUE
1682 for node in nodes:
1683 started = main.ONOSbench.isup( node.ip_address )
1684 if not started:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001685 main.log.error( node.name + " didn't start!" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001686 onosIsupResult = onosIsupResult and started
1687 if onosIsupResult == main.TRUE:
1688 break
Jon Hall390696c2015-05-05 17:13:41 -07001689 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1690 onpass="ONOS restarted",
1691 onfail="ONOS restart NOT successful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001692
Jon Hall5cfd23c2015-03-19 11:40:57 -07001693 main.log.step( "Starting ONOS CLI sessions" )
1694 cliResults = main.TRUE
1695 threads = []
1696 for i in range( numControllers ):
1697 t = main.Thread( target=CLIs[i].startOnosCli,
1698 name="startOnosCli-" + str( i ),
1699 args=[nodes[i].ip_address] )
1700 threads.append( t )
1701 t.start()
1702
1703 for t in threads:
1704 t.join()
1705 cliResults = cliResults and t.result
Jon Hall390696c2015-05-05 17:13:41 -07001706 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1707 onpass="ONOS cli started",
1708 onfail="ONOS clis did not restart" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001709
Jon Hallfeff3082015-05-19 10:23:26 -07001710 # Grab the time of restart so we chan check how long the gossip
1711 # protocol has had time to work
1712 main.restartTime = time.time() - killTime
1713 main.log.debug( "Restart time: " + str( main.restartTime ) )
Jon Hallc9eabec2015-06-10 14:33:14 -07001714 labels.append( "Restart" )
1715 data.append( str( main.restartTime ) )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001716
Jon Hallfeff3082015-05-19 10:23:26 -07001717 # FIXME: revisit test plan for election with madan
1718 # Rerun for election on restarted nodes
Jon Hall40d2cbd2015-06-03 16:24:29 -07001719 runResults = main.TRUE
1720 for cli in CLIs:
1721 run = CLIs[0].electionTestRun()
1722 if run != main.TRUE:
1723 main.log.error( "Error running for election on " + cli.name )
1724 runResults = runResults and run
Jon Hallfeff3082015-05-19 10:23:26 -07001725 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1726 onpass="Reran for election",
1727 onfail="Failed to rerun for election" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001728
1729 # TODO: Make this configurable
Jon Hallfeff3082015-05-19 10:23:26 -07001730 time.sleep( 60 )
1731 main.log.debug( CLIs[0].nodes( jsonFormat=False ) )
1732 main.log.debug( CLIs[0].leaders( jsonFormat=False ) )
1733 main.log.debug( CLIs[0].partitions( jsonFormat=False ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001734
Jon Hall6aec96b2015-01-19 14:49:31 -08001735 def CASE7( self, main ):
1736 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001737 Check state after ONOS failure
Jon Hall6aec96b2015-01-19 14:49:31 -08001738 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001739 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -07001740 assert numControllers, "numControllers not defined"
1741 assert main, "main not defined"
1742 assert utilities.assert_equals, "utilities.assert_equals not defined"
1743 assert CLIs, "CLIs not defined"
1744 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08001745 main.case( "Running ONOS Constant State Tests" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001746
Jon Hall5cfd23c2015-03-19 11:40:57 -07001747 main.step( "Check that each switch has a master" )
Jon Hall6aec96b2015-01-19 14:49:31 -08001748 # Assert that each device has a master
Jon Hall5cfd23c2015-03-19 11:40:57 -07001749 rolesNotNull = main.TRUE
1750 threads = []
1751 for i in range( numControllers ):
1752 t = main.Thread( target=CLIs[i].rolesNotNull,
1753 name="rolesNotNull-" + str( i ),
1754 args=[ ] )
1755 threads.append( t )
1756 t.start()
1757
1758 for t in threads:
1759 t.join()
1760 rolesNotNull = rolesNotNull and t.result
Jon Hall6aec96b2015-01-19 14:49:31 -08001761 utilities.assert_equals(
1762 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001763 actual=rolesNotNull,
Jon Hall6aec96b2015-01-19 14:49:31 -08001764 onpass="Each device has a master",
1765 onfail="Some devices don't have a master assigned" )
Jon Hall94fd0472014-12-08 11:52:42 -08001766
Jon Hall390696c2015-05-05 17:13:41 -07001767 main.step( "Read device roles from ONOS" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001768 ONOSMastership = []
1769 mastershipCheck = main.FALSE
1770 consistentMastership = True
1771 rolesResults = True
1772 threads = []
1773 for i in range( numControllers ):
1774 t = main.Thread( target=CLIs[i].roles,
1775 name="roles-" + str( i ),
1776 args=[] )
1777 threads.append( t )
1778 t.start()
1779
1780 for t in threads:
1781 t.join()
1782 ONOSMastership.append( t.result )
1783
1784 for i in range( numControllers ):
1785 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001786 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001787 " roles" )
1788 main.log.warn(
1789 "ONOS" + str( i + 1 ) + " mastership response: " +
1790 repr( ONOSMastership[i] ) )
1791 rolesResults = False
1792 utilities.assert_equals(
1793 expect=True,
1794 actual=rolesResults,
1795 onpass="No error in reading roles output",
1796 onfail="Error in reading roles from ONOS" )
1797
1798 main.step( "Check for consistency in roles from each controller" )
1799 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001800 main.log.info(
Jon Hall6aec96b2015-01-19 14:49:31 -08001801 "Switch roles are consistent across all ONOS nodes" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001802 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001803 consistentMastership = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001804 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001805 expect=True,
Jon Hall8f89dda2015-01-22 16:03:33 -08001806 actual=consistentMastership,
Jon Hall6aec96b2015-01-19 14:49:31 -08001807 onpass="Switch roles are consistent across all ONOS nodes",
1808 onfail="ONOS nodes have different views of switch roles" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001809
Jon Hall5cfd23c2015-03-19 11:40:57 -07001810 if rolesResults and not consistentMastership:
1811 for i in range( numControllers ):
1812 main.log.warn(
1813 "ONOS" + str( i + 1 ) + " roles: ",
1814 json.dumps(
1815 json.loads( ONOSMastership[ i ] ),
1816 sort_keys=True,
1817 indent=4,
1818 separators=( ',', ': ' ) ) )
1819 elif rolesResults and not consistentMastership:
1820 mastershipCheck = main.TRUE
1821
Jon Hallfeff3082015-05-19 10:23:26 -07001822 '''
Jon Hall73cf9cc2014-11-20 22:28:38 -08001823 description2 = "Compare switch roles from before failure"
Jon Hall6aec96b2015-01-19 14:49:31 -08001824 main.step( description2 )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001825 try:
1826 currentJson = json.loads( ONOSMastership[0] )
1827 oldJson = json.loads( mastershipState )
1828 except ( ValueError, TypeError ):
1829 main.log.exception( "Something is wrong with parsing " +
1830 "ONOSMastership[0] or mastershipState" )
1831 main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[0] ) )
1832 main.log.error( "mastershipState" + repr( mastershipState ) )
1833 main.cleanup()
1834 main.exit()
Jon Hall8f89dda2015-01-22 16:03:33 -08001835 mastershipCheck = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08001836 for i in range( 1, 29 ):
1837 switchDPID = str(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001838 main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001839 current = [ switch[ 'master' ] for switch in currentJson
Jon Hall6aec96b2015-01-19 14:49:31 -08001840 if switchDPID in switch[ 'id' ] ]
Jon Hall8f89dda2015-01-22 16:03:33 -08001841 old = [ switch[ 'master' ] for switch in oldJson
Jon Hall6aec96b2015-01-19 14:49:31 -08001842 if switchDPID in switch[ 'id' ] ]
Jon Hall73cf9cc2014-11-20 22:28:38 -08001843 if current == old:
Jon Hall8f89dda2015-01-22 16:03:33 -08001844 mastershipCheck = mastershipCheck and main.TRUE
Jon Hall73cf9cc2014-11-20 22:28:38 -08001845 else:
Jon Hall6aec96b2015-01-19 14:49:31 -08001846 main.log.warn( "Mastership of switch %s changed" % switchDPID )
Jon Hall8f89dda2015-01-22 16:03:33 -08001847 mastershipCheck = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001848 utilities.assert_equals(
1849 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001850 actual=mastershipCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -08001851 onpass="Mastership of Switches was not changed",
1852 onfail="Mastership of some switches changed" )
Jon Hallfeff3082015-05-19 10:23:26 -07001853 '''
Jon Hall6aec96b2015-01-19 14:49:31 -08001854 # NOTE: we expect mastership to change on controller failure
Jon Hall73cf9cc2014-11-20 22:28:38 -08001855
Jon Hall6aec96b2015-01-19 14:49:31 -08001856 main.step( "Get the intents and compare across all nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001857 ONOSIntents = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001858 intentCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001859 consistentIntents = True
1860 intentsResults = True
1861 threads = []
1862 for i in range( numControllers ):
1863 t = main.Thread( target=CLIs[i].intents,
1864 name="intents-" + str( i ),
1865 args=[],
1866 kwargs={ 'jsonFormat': True } )
1867 threads.append( t )
1868 t.start()
1869
1870 for t in threads:
1871 t.join()
1872 ONOSIntents.append( t.result )
1873
1874 for i in range( numControllers ):
1875 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001876 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001877 " intents" )
1878 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1879 repr( ONOSIntents[ i ] ) )
1880 intentsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001881 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001882 expect=True,
1883 actual=intentsResults,
1884 onpass="No error in reading intents output",
1885 onfail="Error in reading intents from ONOS" )
1886
1887 main.step( "Check for consistency in Intents from each controller" )
1888 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001889 main.log.info( "Intents are consistent across all ONOS " +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001890 "nodes" )
1891 else:
1892 consistentIntents = False
Jon Hall390696c2015-05-05 17:13:41 -07001893
1894 # Try to make it easy to figure out what is happening
1895 #
1896 # Intent ONOS1 ONOS2 ...
1897 # 0x01 INSTALLED INSTALLING
1898 # ... ... ...
1899 # ... ... ...
1900 title = " ID"
1901 for n in range( numControllers ):
1902 title += " " * 10 + "ONOS" + str( n + 1 )
1903 main.log.warn( title )
1904 # get all intent keys in the cluster
1905 keys = []
1906 for nodeStr in ONOSIntents:
1907 node = json.loads( nodeStr )
1908 for intent in node:
1909 keys.append( intent.get( 'id' ) )
1910 keys = set( keys )
1911 for key in keys:
1912 row = "%-13s" % key
1913 for nodeStr in ONOSIntents:
1914 node = json.loads( nodeStr )
1915 for intent in node:
1916 if intent.get( 'id' ) == key:
1917 row += "%-15s" % intent.get( 'state' )
1918 main.log.warn( row )
1919 # End table view
1920
Jon Hall5cfd23c2015-03-19 11:40:57 -07001921 utilities.assert_equals(
1922 expect=True,
1923 actual=consistentIntents,
Jon Hall6aec96b2015-01-19 14:49:31 -08001924 onpass="Intents are consistent across all ONOS nodes",
1925 onfail="ONOS nodes have different views of intents" )
Jon Hall1b8f54a2015-02-04 13:24:20 -08001926 intentStates = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001927 for node in ONOSIntents: # Iter through ONOS nodes
Jon Hall1b8f54a2015-02-04 13:24:20 -08001928 nodeStates = []
Jon Hall58c76b72015-02-23 11:09:24 -08001929 # Iter through intents of a node
Jon Hall5cfd23c2015-03-19 11:40:57 -07001930 try:
1931 for intent in json.loads( node ):
1932 nodeStates.append( intent[ 'state' ] )
1933 except ( ValueError, TypeError ):
1934 main.log.exception( "Error in parsing intents" )
1935 main.log.error( repr( node ) )
Jon Hall1b8f54a2015-02-04 13:24:20 -08001936 intentStates.append( nodeStates )
1937 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
1938 main.log.info( dict( out ) )
1939
Jon Hall5cfd23c2015-03-19 11:40:57 -07001940 if intentsResults and not consistentIntents:
1941 for i in range( numControllers ):
1942 main.log.warn( "ONOS" + str( i + 1 ) + " intents: " )
1943 main.log.warn( json.dumps(
1944 json.loads( ONOSIntents[ i ] ),
1945 sort_keys=True,
1946 indent=4,
1947 separators=( ',', ': ' ) ) )
1948 elif intentsResults and consistentIntents:
1949 intentCheck = main.TRUE
1950
Jon Hall58c76b72015-02-23 11:09:24 -08001951 # NOTE: Store has no durability, so intents are lost across system
1952 # restarts
Jon Hall6aec96b2015-01-19 14:49:31 -08001953 """
1954 main.step( "Compare current intents with intents before the failure" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001955 # NOTE: this requires case 5 to pass for intentState to be set.
Jon Hall94fd0472014-12-08 11:52:42 -08001956 # maybe we should stop the test if that fails?
Jon Hall40d2cbd2015-06-03 16:24:29 -07001957 sameIntents = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001958 if intentState and intentState == ONOSIntents[ 0 ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08001959 sameIntents = main.TRUE
Jon Hallfeff3082015-05-19 10:23:26 -07001960 main.log.info( "Intents are consistent with before failure" )
Jon Hall6aec96b2015-01-19 14:49:31 -08001961 # TODO: possibly the states have changed? we may need to figure out
Jon Hall5cfd23c2015-03-19 11:40:57 -07001962 # what the acceptable states are
Jon Hall40d2cbd2015-06-03 16:24:29 -07001963 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
1964 sameIntents = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08001965 try:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001966 before = json.loads( intentState )
1967 after = json.loads( ONOSIntents[ 0 ] )
1968 for intent in before:
1969 if intent not in after:
1970 sameIntents = main.FALSE
Jon Hallc9eabec2015-06-10 14:33:14 -07001971 main.log.debug( "Intent is not currently in ONOS " +
Jon Hall40d2cbd2015-06-03 16:24:29 -07001972 "(at least in the same form):" )
1973 main.log.debug( json.dumps( intent ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001974 except ( ValueError, TypeError ):
1975 main.log.exception( "Exception printing intents" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001976 main.log.debug( repr( ONOSIntents[0] ) )
1977 main.log.debug( repr( intentState ) )
1978 if sameIntents == main.FALSE:
1979 try:
1980 main.log.debug( "ONOS intents before: " )
1981 main.log.debug( json.dumps( json.loads( intentState ),
1982 sort_keys=True, indent=4,
1983 separators=( ',', ': ' ) ) )
1984 main.log.debug( "Current ONOS intents: " )
1985 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
1986 sort_keys=True, indent=4,
1987 separators=( ',', ': ' ) ) )
1988 except ( ValueError, TypeError ):
1989 main.log.exception( "Exception printing intents" )
1990 main.log.debug( repr( ONOSIntents[0] ) )
1991 main.log.debug( repr( intentState ) )
Jon Hall6aec96b2015-01-19 14:49:31 -08001992 utilities.assert_equals(
1993 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001994 actual=sameIntents,
Jon Hall6aec96b2015-01-19 14:49:31 -08001995 onpass="Intents are consistent with before failure",
1996 onfail="The Intents changed during failure" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001997 intentCheck = intentCheck and sameIntents
Jon Hall6aec96b2015-01-19 14:49:31 -08001998 """
1999 main.step( "Get the OF Table entries and compare to before " +
2000 "component failure" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002001 FlowTables = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002002 flows2 = []
2003 for i in range( 28 ):
2004 main.log.info( "Checking flow table on s" + str( i + 1 ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08002005 tmpFlows = main.Mininet2.getFlowTable( 1.3, "s" + str( i + 1 ) )
2006 flows2.append( tmpFlows )
2007 tempResult = main.Mininet2.flowComp(
Jon Hall6aec96b2015-01-19 14:49:31 -08002008 flow1=flows[ i ],
Jon Hall8f89dda2015-01-22 16:03:33 -08002009 flow2=tmpFlows )
2010 FlowTables = FlowTables and tempResult
2011 if FlowTables == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002012 main.log.info( "Differences in flow table for switch: s" +
2013 str( i + 1 ) )
Jon Hall6aec96b2015-01-19 14:49:31 -08002014 utilities.assert_equals(
2015 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002016 actual=FlowTables,
Jon Hall6aec96b2015-01-19 14:49:31 -08002017 onpass="No changes were found in the flow tables",
2018 onfail="Changes were found in the flow tables" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002019
Jon Hall40d2cbd2015-06-03 16:24:29 -07002020 # main.step( "Check the continuous pings to ensure that no packets " +
2021 # "were dropped during component failure" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002022 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2023 main.params[ 'TESTONIP' ] )
Jon Hall8f89dda2015-01-22 16:03:33 -08002024 LossInPings = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002025 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2026 for i in range( 8, 18 ):
2027 main.log.info(
2028 "Checking for a loss in pings along flow from s" +
2029 str( i ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08002030 LossInPings = main.Mininet2.checkForLoss(
Jon Hall6aec96b2015-01-19 14:49:31 -08002031 "/tmp/ping.h" +
Jon Hall8f89dda2015-01-22 16:03:33 -08002032 str( i ) ) or LossInPings
2033 if LossInPings == main.TRUE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002034 main.log.info( "Loss in ping detected" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002035 elif LossInPings == main.ERROR:
Jon Hall6aec96b2015-01-19 14:49:31 -08002036 main.log.info( "There are multiple mininet process running" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002037 elif LossInPings == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002038 main.log.info( "No Loss in the pings" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002039 main.log.info( "No loss of dataplane connectivity" )
2040 # utilities.assert_equals(
2041 # expect=main.FALSE,
2042 # actual=LossInPings,
2043 # onpass="No Loss of connectivity",
2044 # onfail="Loss of dataplane connectivity detected" )
2045
Jon Hall58c76b72015-02-23 11:09:24 -08002046 # NOTE: Since intents are not persisted with IntnentStore,
2047 # we expect loss in dataplane connectivity
Jon Hall8f89dda2015-01-22 16:03:33 -08002048 LossInPings = main.FALSE
Jon Hall73cf9cc2014-11-20 22:28:38 -08002049
Jon Hall390696c2015-05-05 17:13:41 -07002050 main.step( "Leadership Election is still functional" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002051 # Test of LeadershipElection
Jon Hall8f89dda2015-01-22 16:03:33 -08002052 leaderList = []
2053 leaderResult = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002054 for cli in CLIs:
2055 leaderN = cli.electionTestLeader()
Jon Hall8f89dda2015-01-22 16:03:33 -08002056 leaderList.append( leaderN )
Jon Hall669173b2014-12-17 11:36:30 -08002057 if leaderN == main.FALSE:
Jon Hallfeff3082015-05-19 10:23:26 -07002058 # error in response
Jon Hall40d2cbd2015-06-03 16:24:29 -07002059 main.log.error( "Something is wrong with " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002060 "electionTestLeader function, check the" +
Jon Hall6aec96b2015-01-19 14:49:31 -08002061 " error logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002062 leaderResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002063 elif leaderN is None:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002064 main.log.error( cli.name +
2065 " shows no leader for the election-app." )
Jon Hall8f89dda2015-01-22 16:03:33 -08002066 leaderResult = main.FALSE
2067 if len( set( leaderList ) ) != 1:
2068 leaderResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002069 main.log.error(
2070 "Inconsistent view of leader for the election test app" )
2071 # TODO: print the list
Jon Hall6aec96b2015-01-19 14:49:31 -08002072 utilities.assert_equals(
2073 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002074 actual=leaderResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002075 onpass="Leadership election passed",
2076 onfail="Something went wrong with Leadership election" )
Jon Hall669173b2014-12-17 11:36:30 -08002077
Jon Hall6aec96b2015-01-19 14:49:31 -08002078 def CASE8( self, main ):
2079 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002080 Compare topo
Jon Hall6aec96b2015-01-19 14:49:31 -08002081 """
Jon Hallb87f3db2015-07-06 03:10:27 -07002082 import sys
2083 # FIXME add this path to params
2084 sys.path.append( "/home/admin/sts" )
2085 # assumes that sts is already in you PYTHONPATH
2086 from sts.topology.teston_topology import TestONTopology
Jon Hall73cf9cc2014-11-20 22:28:38 -08002087 import json
2088 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002089 assert numControllers, "numControllers not defined"
2090 assert main, "main not defined"
2091 assert utilities.assert_equals, "utilities.assert_equals not defined"
2092 assert CLIs, "CLIs not defined"
2093 assert nodes, "nodes not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002094
Jon Hallfeff3082015-05-19 10:23:26 -07002095 main.case( "Compare ONOS Topology view to Mininet topology" )
2096 main.caseExplaination = "Compare topology objects between Mininet" +\
2097 " and ONOS"
Jon Hallb87f3db2015-07-06 03:10:27 -07002098 main.step( "Create TestONTopology object" )
2099 try:
2100 ctrls = []
2101 for node in nodes:
2102 temp = ( node, node.name, node.ip_address, 6633 )
2103 ctrls.append( temp )
2104 MNTopo = TestONTopology( main.Mininet1, ctrls )
2105 except Exception:
2106 objResult = main.FALSE
2107 else:
2108 objResult = main.TRUE
2109 utilities.assert_equals( expect=main.TRUE, actual=objResult,
2110 onpass="Created TestONTopology object",
2111 onfail="Exception while creating " +
2112 "TestONTopology object" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002113
Jon Hallfeff3082015-05-19 10:23:26 -07002114 main.step( "Comparing ONOS topology to MN" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002115 devicesResults = main.TRUE
Jon Hallb87f3db2015-07-06 03:10:27 -07002116 portsResults = main.TRUE
Jon Hall8f89dda2015-01-22 16:03:33 -08002117 linksResults = main.TRUE
Jon Hall58c76b72015-02-23 11:09:24 -08002118 hostsResults = main.TRUE
Jon Hallc9eabec2015-06-10 14:33:14 -07002119 hostAttachmentResults = True
Jon Hall8f89dda2015-01-22 16:03:33 -08002120 topoResult = main.FALSE
Jon Hall73cf9cc2014-11-20 22:28:38 -08002121 elapsed = 0
Jon Hallffb386d2014-11-21 13:43:38 -08002122 count = 0
Jon Hall6aec96b2015-01-19 14:49:31 -08002123 main.step( "Collecting topology information from ONOS" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002124 startTime = time.time()
Jon Hall21270ac2015-02-16 17:59:55 -08002125 # Give time for Gossip to work
Jon Hallc9eabec2015-06-10 14:33:14 -07002126 while topoResult == main.FALSE and elapsed < 60:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002127 count += 1
Jon Hallb87f3db2015-07-06 03:10:27 -07002128 if count > 1:
2129 # TODO: Deprecate STS usage
2130 MNTopo = TestONTopology( main.Mininet1, ctrls )
Jon Hall8f89dda2015-01-22 16:03:33 -08002131 cliStart = time.time()
Jon Hall94fd0472014-12-08 11:52:42 -08002132 devices = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002133 threads = []
2134 for i in range( numControllers ):
2135 t = main.Thread( target=CLIs[i].devices,
2136 name="devices-" + str( i ),
2137 args=[ ] )
2138 threads.append( t )
2139 t.start()
2140
2141 for t in threads:
2142 t.join()
2143 devices.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002144 hosts = []
Jon Hall58c76b72015-02-23 11:09:24 -08002145 ipResult = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002146 threads = []
2147 for i in range( numControllers ):
2148 t = main.Thread( target=CLIs[i].hosts,
2149 name="hosts-" + str( i ),
2150 args=[ ] )
2151 threads.append( t )
2152 t.start()
2153
2154 for t in threads:
2155 t.join()
2156 try:
2157 hosts.append( json.loads( t.result ) )
2158 except ( ValueError, TypeError ):
2159 main.log.exception( "Error parsing hosts results" )
2160 main.log.error( repr( t.result ) )
Jon Hall529a37f2015-01-28 10:02:00 -08002161 for controller in range( 0, len( hosts ) ):
2162 controllerStr = str( controller + 1 )
2163 for host in hosts[ controller ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002164 if host is None or host.get( 'ipAddresses', [] ) == []:
Jon Hall529a37f2015-01-28 10:02:00 -08002165 main.log.error(
Jon Hallfeff3082015-05-19 10:23:26 -07002166 "DEBUG:Error with host ipAddresses on controller" +
Jon Hall529a37f2015-01-28 10:02:00 -08002167 controllerStr + ": " + str( host ) )
Jon Hall58c76b72015-02-23 11:09:24 -08002168 ipResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002169 ports = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002170 threads = []
2171 for i in range( numControllers ):
2172 t = main.Thread( target=CLIs[i].ports,
2173 name="ports-" + str( i ),
2174 args=[ ] )
2175 threads.append( t )
2176 t.start()
2177
2178 for t in threads:
2179 t.join()
2180 ports.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002181 links = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002182 threads = []
2183 for i in range( numControllers ):
2184 t = main.Thread( target=CLIs[i].links,
2185 name="links-" + str( i ),
2186 args=[ ] )
2187 threads.append( t )
2188 t.start()
2189
2190 for t in threads:
2191 t.join()
2192 links.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002193 clusters = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002194 threads = []
2195 for i in range( numControllers ):
2196 t = main.Thread( target=CLIs[i].clusters,
2197 name="clusters-" + str( i ),
2198 args=[ ] )
2199 threads.append( t )
2200 t.start()
2201
2202 for t in threads:
2203 t.join()
2204 clusters.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002205
Jon Hall8f89dda2015-01-22 16:03:33 -08002206 elapsed = time.time() - startTime
2207 cliTime = time.time() - cliStart
Jon Hall40d2cbd2015-06-03 16:24:29 -07002208 print "Elapsed time: " + str( elapsed )
Jon Hall8f89dda2015-01-22 16:03:33 -08002209 print "CLI time: " + str( cliTime )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002210
Jon Hall8f89dda2015-01-22 16:03:33 -08002211 for controller in range( numControllers ):
2212 controllerStr = str( controller + 1 )
Jon Hallb87f3db2015-07-06 03:10:27 -07002213 if devices[ controller ] or "Error" not in devices[
2214 controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08002215 currentDevicesResult = main.Mininet1.compareSwitches(
Jon Hallb87f3db2015-07-06 03:10:27 -07002216 MNTopo,
2217 json.loads( devices[ controller ] ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002218 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08002219 currentDevicesResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002220 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08002221 actual=currentDevicesResult,
2222 onpass="ONOS" + controllerStr +
2223 " Switches view is correct",
2224 onfail="ONOS" + controllerStr +
2225 " Switches view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002226
Jon Hallb87f3db2015-07-06 03:10:27 -07002227 if ports[ controller ] or "Error" not in ports[ controller ]:
2228 currentPortsResult = main.Mininet1.comparePorts(
2229 MNTopo,
2230 json.loads( ports[ controller ] ) )
2231 else:
2232 currentPortsResult = main.FALSE
2233 utilities.assert_equals( expect=main.TRUE,
2234 actual=currentPortsResult,
2235 onpass="ONOS" + controllerStr +
2236 " ports view is correct",
2237 onfail="ONOS" + controllerStr +
2238 " ports view is incorrect" )
2239
2240 if links[ controller ] or "Error" not in links[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08002241 currentLinksResult = main.Mininet1.compareLinks(
Jon Hallb87f3db2015-07-06 03:10:27 -07002242 MNTopo,
2243 json.loads( links[ controller ] ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002244 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08002245 currentLinksResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002246 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08002247 actual=currentLinksResult,
2248 onpass="ONOS" + controllerStr +
2249 " links view is correct",
2250 onfail="ONOS" + controllerStr +
2251 " links view is incorrect" )
2252
2253 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2254 currentHostsResult = main.Mininet1.compareHosts(
Jon Hallb87f3db2015-07-06 03:10:27 -07002255 MNTopo, hosts[ controller ] )
Jon Hall58c76b72015-02-23 11:09:24 -08002256 else:
2257 currentHostsResult = main.FALSE
2258 utilities.assert_equals( expect=main.TRUE,
2259 actual=currentHostsResult,
2260 onpass="ONOS" + controllerStr +
2261 " hosts exist in Mininet",
2262 onfail="ONOS" + controllerStr +
2263 " hosts don't match Mininet" )
Jon Hallc9eabec2015-06-10 14:33:14 -07002264 # CHECKING HOST ATTACHMENT POINTS
2265 hostAttachment = True
Jon Hall0f523f22015-07-06 09:31:09 -07002266 noHosts = False
Jon Hallc9eabec2015-06-10 14:33:14 -07002267 # FIXME: topo-HA/obelisk specific mappings:
2268 # key is mac and value is dpid
2269 mappings = {}
2270 for i in range( 1, 29 ): # hosts 1 through 28
2271 # set up correct variables:
2272 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2273 if i == 1:
2274 deviceId = "1000".zfill(16)
2275 elif i == 2:
2276 deviceId = "2000".zfill(16)
2277 elif i == 3:
2278 deviceId = "3000".zfill(16)
2279 elif i == 4:
2280 deviceId = "3004".zfill(16)
2281 elif i == 5:
2282 deviceId = "5000".zfill(16)
2283 elif i == 6:
2284 deviceId = "6000".zfill(16)
2285 elif i == 7:
2286 deviceId = "6007".zfill(16)
2287 elif i >= 8 and i <= 17:
2288 dpid = '3' + str( i ).zfill( 3 )
2289 deviceId = dpid.zfill(16)
2290 elif i >= 18 and i <= 27:
2291 dpid = '6' + str( i ).zfill( 3 )
2292 deviceId = dpid.zfill(16)
2293 elif i == 28:
2294 deviceId = "2800".zfill(16)
2295 mappings[ macId ] = deviceId
2296 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2297 if hosts[ controller ] == []:
2298 main.log.warn( "There are no hosts discovered" )
Jon Hall0f523f22015-07-06 09:31:09 -07002299 noHosts = True
Jon Hallc9eabec2015-06-10 14:33:14 -07002300 else:
2301 for host in hosts[ controller ]:
2302 mac = None
2303 location = None
2304 device = None
2305 port = None
2306 try:
2307 mac = host.get( 'mac' )
2308 assert mac, "mac field could not be found for this host object"
Jon Hall58c76b72015-02-23 11:09:24 -08002309
Jon Hallc9eabec2015-06-10 14:33:14 -07002310 location = host.get( 'location' )
2311 assert location, "location field could not be found for this host object"
2312
2313 # Trim the protocol identifier off deviceId
2314 device = str( location.get( 'elementId' ) ).split(':')[1]
2315 assert device, "elementId field could not be found for this host location object"
2316
2317 port = location.get( 'port' )
2318 assert port, "port field could not be found for this host location object"
2319
2320 # Now check if this matches where they should be
2321 if mac and device and port:
2322 if str( port ) != "1":
2323 main.log.error( "The attachment port is incorrect for " +
2324 "host " + str( mac ) +
2325 ". Expected: 1 Actual: " + str( port) )
2326 hostAttachment = False
2327 if device != mappings[ str( mac ) ]:
2328 main.log.error( "The attachment device is incorrect for " +
2329 "host " + str( mac ) +
2330 ". Expected: " + mappings[ str( mac ) ] +
2331 " Actual: " + device )
2332 hostAttachment = False
2333 else:
2334 hostAttachment = False
2335 except AssertionError:
2336 main.log.exception( "Json object not as expected" )
2337 main.log.error( repr( host ) )
2338 hostAttachment = False
2339 else:
2340 main.log.error( "No hosts json output or \"Error\"" +
2341 " in output. hosts = " +
2342 repr( hosts[ controller ] ) )
Jon Hall0f523f22015-07-06 09:31:09 -07002343 if noHosts is False:
Jon Hallc9eabec2015-06-10 14:33:14 -07002344 # TODO: Find a way to know if there should be hosts in a
2345 # given point of the test
2346 hostAttachment = True
2347
2348 # END CHECKING HOST ATTACHMENT POINTS
Jon Hall58c76b72015-02-23 11:09:24 -08002349 devicesResults = devicesResults and currentDevicesResult
Jon Hallb87f3db2015-07-06 03:10:27 -07002350 portsResults = portsResults and currentPortsResult
Jon Hall58c76b72015-02-23 11:09:24 -08002351 linksResults = linksResults and currentLinksResult
2352 hostsResults = hostsResults and currentHostsResult
Jon Hallb87f3db2015-07-06 03:10:27 -07002353 hostAttachmentResults = hostAttachmentResults and hostAttachment
Jon Hall94fd0472014-12-08 11:52:42 -08002354
Jon Hallc9eabec2015-06-10 14:33:14 -07002355 # Compare json objects for hosts and dataplane clusters
Jon Hall94fd0472014-12-08 11:52:42 -08002356
Jon Hallc9eabec2015-06-10 14:33:14 -07002357 # hosts
2358 main.step( "Hosts view is consistent across all ONOS nodes" )
2359 consistentHostsResult = main.TRUE
2360 for controller in range( len( hosts ) ):
2361 controllerStr = str( controller + 1 )
2362 if "Error" not in hosts[ controller ]:
2363 if hosts[ controller ] == hosts[ 0 ]:
2364 continue
2365 else: # hosts not consistent
2366 main.log.error( "hosts from ONOS" + controllerStr +
2367 " is inconsistent with ONOS1" )
2368 main.log.warn( repr( hosts[ controller ] ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08002369 consistentHostsResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002370
Jon Hallc9eabec2015-06-10 14:33:14 -07002371 else:
2372 main.log.error( "Error in getting ONOS hosts from ONOS" +
2373 controllerStr )
2374 consistentHostsResult = main.FALSE
2375 main.log.warn( "ONOS" + controllerStr +
2376 " hosts response: " +
2377 repr( hosts[ controller ] ) )
2378 utilities.assert_equals(
2379 expect=main.TRUE,
2380 actual=consistentHostsResult,
2381 onpass="Hosts view is consistent across all ONOS nodes",
2382 onfail="ONOS nodes have different views of hosts" )
Jon Hall94fd0472014-12-08 11:52:42 -08002383
Jon Hallc9eabec2015-06-10 14:33:14 -07002384 main.step( "Hosts information is correct" )
2385 hostsResults = hostsResults and ipResult
2386 utilities.assert_equals(
2387 expect=main.TRUE,
2388 actual=hostsResults,
2389 onpass="Host information is correct",
2390 onfail="Host information is incorrect" )
2391
2392 main.step( "Host attachment points to the network" )
2393 utilities.assert_equals(
2394 expect=True,
2395 actual=hostAttachmentResults,
2396 onpass="Hosts are correctly attached to the network",
2397 onfail="ONOS did not correctly attach hosts to the network" )
2398
2399 # Strongly connected clusters of devices
2400 main.step( "Clusters view is consistent across all ONOS nodes" )
2401 consistentClustersResult = main.TRUE
2402 for controller in range( len( clusters ) ):
2403 controllerStr = str( controller + 1 )
2404 if "Error" not in clusters[ controller ]:
2405 if clusters[ controller ] == clusters[ 0 ]:
2406 continue
2407 else: # clusters not consistent
2408 main.log.error( "clusters from ONOS" +
2409 controllerStr +
2410 " is inconsistent with ONOS1" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002411 consistentClustersResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002412
Jon Hallc9eabec2015-06-10 14:33:14 -07002413 else:
2414 main.log.error( "Error in getting dataplane clusters " +
2415 "from ONOS" + controllerStr )
2416 consistentClustersResult = main.FALSE
2417 main.log.warn( "ONOS" + controllerStr +
2418 " clusters response: " +
2419 repr( clusters[ controller ] ) )
2420 utilities.assert_equals(
2421 expect=main.TRUE,
2422 actual=consistentClustersResult,
2423 onpass="Clusters view is consistent across all ONOS nodes",
2424 onfail="ONOS nodes have different views of clusters" )
2425
2426 main.step( "There is only one SCC" )
2427 # there should always only be one cluster
2428 try:
2429 numClusters = len( json.loads( clusters[ 0 ] ) )
2430 except ( ValueError, TypeError ):
2431 main.log.exception( "Error parsing clusters[0]: " +
2432 repr( clusters[0] ) )
2433 clusterResults = main.FALSE
2434 if numClusters == 1:
2435 clusterResults = main.TRUE
2436 utilities.assert_equals(
2437 expect=1,
2438 actual=numClusters,
2439 onpass="ONOS shows 1 SCC",
2440 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2441
Jon Hallb87f3db2015-07-06 03:10:27 -07002442 topoResult = ( devicesResults and portsResults and linksResults
Jon Hallc9eabec2015-06-10 14:33:14 -07002443 and hostsResults and consistentHostsResult
2444 and consistentClustersResult and clusterResults
2445 and ipResult and hostAttachmentResults )
Jon Hall94fd0472014-12-08 11:52:42 -08002446
Jon Hall8f89dda2015-01-22 16:03:33 -08002447 topoResult = topoResult and int( count <= 2 )
2448 note = "note it takes about " + str( int( cliTime ) ) + \
2449 " seconds for the test to make all the cli calls to fetch " +\
2450 "the topology from each ONOS instance"
Jon Hall1b8f54a2015-02-04 13:24:20 -08002451 main.log.info(
Jon Hall8f89dda2015-01-22 16:03:33 -08002452 "Very crass estimate for topology discovery/convergence( " +
2453 str( note ) + " ): " + str( elapsed ) + " seconds, " +
Jon Hall6aec96b2015-01-19 14:49:31 -08002454 str( count ) + " tries" )
Jon Hallc9eabec2015-06-10 14:33:14 -07002455
2456 main.step( "Device information is correct" )
2457 utilities.assert_equals(
2458 expect=main.TRUE,
2459 actual=devicesResults,
2460 onpass="Device information is correct",
2461 onfail="Device information is incorrect" )
2462
Jon Hallb87f3db2015-07-06 03:10:27 -07002463 main.step( "Port information is correct" )
2464 utilities.assert_equals(
2465 expect=main.TRUE,
2466 actual=portsResults,
2467 onpass="Port information is correct",
2468 onfail="Port information is incorrect" )
2469
Jon Hallc9eabec2015-06-10 14:33:14 -07002470 main.step( "Links are correct" )
2471 utilities.assert_equals(
2472 expect=main.TRUE,
2473 actual=linksResults,
2474 onpass="Link are correct",
2475 onfail="Links are incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002476
Jon Halla9d26da2015-03-30 16:45:32 -07002477 # FIXME: move this to an ONOS state case
2478 main.step( "Checking ONOS nodes" )
2479 nodesOutput = []
Jon Hall390696c2015-05-05 17:13:41 -07002480 nodeResults = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002481 threads = []
2482 for i in range( numControllers ):
2483 t = main.Thread( target=CLIs[i].nodes,
2484 name="nodes-" + str( i ),
2485 args=[ ] )
2486 threads.append( t )
2487 t.start()
2488
2489 for t in threads:
2490 t.join()
2491 nodesOutput.append( t.result )
2492 ips = [ node.ip_address for node in nodes ]
2493 for i in nodesOutput:
2494 try:
2495 current = json.loads( i )
2496 for node in current:
Jon Hall390696c2015-05-05 17:13:41 -07002497 currentResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002498 if node['ip'] in ips: # node in nodes() output is in cell
2499 if node['state'] == 'ACTIVE':
Jon Hall390696c2015-05-05 17:13:41 -07002500 currentResult = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002501 else:
2502 main.log.error( "Error in ONOS node availability" )
2503 main.log.error(
2504 json.dumps( current,
2505 sort_keys=True,
2506 indent=4,
2507 separators=( ',', ': ' ) ) )
2508 break
Jon Hall390696c2015-05-05 17:13:41 -07002509 nodeResults = nodeResults and currentResult
Jon Halla9d26da2015-03-30 16:45:32 -07002510 except ( ValueError, TypeError ):
2511 main.log.error( "Error parsing nodes output" )
2512 main.log.warn( repr( i ) )
Jon Hall390696c2015-05-05 17:13:41 -07002513 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
2514 onpass="Nodes check successful",
2515 onfail="Nodes check NOT successful" )
Jon Halla9d26da2015-03-30 16:45:32 -07002516
Jon Hall6aec96b2015-01-19 14:49:31 -08002517 def CASE9( self, main ):
2518 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002519 Link s3-s28 down
Jon Hall6aec96b2015-01-19 14:49:31 -08002520 """
2521 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002522 assert numControllers, "numControllers not defined"
2523 assert main, "main not defined"
2524 assert utilities.assert_equals, "utilities.assert_equals not defined"
2525 assert CLIs, "CLIs not defined"
2526 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002527 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002528
Jon Hall8f89dda2015-01-22 16:03:33 -08002529 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002530
Jon Hall6aec96b2015-01-19 14:49:31 -08002531 description = "Turn off a link to ensure that Link Discovery " +\
Jon Hall58c76b72015-02-23 11:09:24 -08002532 "is working properly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002533 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002534
Jon Hall6aec96b2015-01-19 14:49:31 -08002535 main.step( "Kill Link between s3 and s28" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002536 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
Jon Hall58c76b72015-02-23 11:09:24 -08002537 main.log.info( "Waiting " + str( linkSleep ) +
2538 " seconds for link down to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002539 time.sleep( linkSleep )
2540 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002541 onpass="Link down successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002542 onfail="Failed to bring link down" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002543 # TODO do some sort of check here
Jon Hall73cf9cc2014-11-20 22:28:38 -08002544
Jon Hall6aec96b2015-01-19 14:49:31 -08002545 def CASE10( self, main ):
2546 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002547 Link s3-s28 up
Jon Hall6aec96b2015-01-19 14:49:31 -08002548 """
2549 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002550 assert numControllers, "numControllers not defined"
2551 assert main, "main not defined"
2552 assert utilities.assert_equals, "utilities.assert_equals not defined"
2553 assert CLIs, "CLIs not defined"
2554 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002555 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002556
Jon Hall8f89dda2015-01-22 16:03:33 -08002557 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002558
Jon Hall6aec96b2015-01-19 14:49:31 -08002559 description = "Restore a link to ensure that Link Discovery is " + \
Jon Hall63604932015-02-26 17:09:50 -08002560 "working properly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002561 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002562
Jon Hall6aec96b2015-01-19 14:49:31 -08002563 main.step( "Bring link between s3 and s28 back up" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002564 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
Jon Hall58c76b72015-02-23 11:09:24 -08002565 main.log.info( "Waiting " + str( linkSleep ) +
2566 " seconds for link up to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002567 time.sleep( linkSleep )
2568 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002569 onpass="Link up successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002570 onfail="Failed to bring link up" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002571 # TODO do some sort of check here
Jon Hall73cf9cc2014-11-20 22:28:38 -08002572
Jon Hall6aec96b2015-01-19 14:49:31 -08002573 def CASE11( self, main ):
2574 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002575 Switch Down
Jon Hall6aec96b2015-01-19 14:49:31 -08002576 """
2577 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002578 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002579 assert numControllers, "numControllers not defined"
2580 assert main, "main not defined"
2581 assert utilities.assert_equals, "utilities.assert_equals not defined"
2582 assert CLIs, "CLIs not defined"
2583 assert nodes, "nodes not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002584
Jon Hall8f89dda2015-01-22 16:03:33 -08002585 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002586
2587 description = "Killing a switch to ensure it is discovered correctly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002588 main.case( description )
2589 switch = main.params[ 'kill' ][ 'switch' ]
2590 switchDPID = main.params[ 'kill' ][ 'dpid' ]
Jon Hall73cf9cc2014-11-20 22:28:38 -08002591
Jon Hall6aec96b2015-01-19 14:49:31 -08002592 # TODO: Make this switch parameterizable
2593 main.step( "Kill " + switch )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002594 main.log.info( "Deleting " + switch )
Jon Hall8f89dda2015-01-22 16:03:33 -08002595 main.Mininet1.delSwitch( switch )
2596 main.log.info( "Waiting " + str( switchSleep ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002597 " seconds for switch down to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002598 time.sleep( switchSleep )
2599 device = main.ONOScli1.getDevice( dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002600 # Peek at the deleted switch
2601 main.log.warn( str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002602 result = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002603 if device and device[ 'available' ] is False:
Jon Hall94fd0472014-12-08 11:52:42 -08002604 result = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002605 utilities.assert_equals( expect=main.TRUE, actual=result,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002606 onpass="Kill switch successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002607 onfail="Failed to kill switch?" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002608
Jon Hall6aec96b2015-01-19 14:49:31 -08002609 def CASE12( self, main ):
2610 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002611 Switch Up
Jon Hall6aec96b2015-01-19 14:49:31 -08002612 """
2613 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002614 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002615 assert numControllers, "numControllers not defined"
2616 assert main, "main not defined"
2617 assert utilities.assert_equals, "utilities.assert_equals not defined"
2618 assert CLIs, "CLIs not defined"
2619 assert nodes, "nodes not defined"
2620 assert ONOS1Port, "ONOS1Port not defined"
2621 assert ONOS2Port, "ONOS2Port not defined"
2622 assert ONOS3Port, "ONOS3Port not defined"
2623 assert ONOS4Port, "ONOS4Port not defined"
2624 assert ONOS5Port, "ONOS5Port not defined"
2625 assert ONOS6Port, "ONOS6Port not defined"
2626 assert ONOS7Port, "ONOS7Port not defined"
Jon Hall669173b2014-12-17 11:36:30 -08002627
Jon Hall8f89dda2015-01-22 16:03:33 -08002628 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
Jon Hall6aec96b2015-01-19 14:49:31 -08002629 switch = main.params[ 'kill' ][ 'switch' ]
2630 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2631 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hall73cf9cc2014-11-20 22:28:38 -08002632 description = "Adding a switch to ensure it is discovered correctly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002633 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002634
Jon Hall6aec96b2015-01-19 14:49:31 -08002635 main.step( "Add back " + switch )
Jon Hall8f89dda2015-01-22 16:03:33 -08002636 main.Mininet1.addSwitch( switch, dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002637 for peer in links:
Jon Hall8f89dda2015-01-22 16:03:33 -08002638 main.Mininet1.addLink( switch, peer )
Jon Hall0f523f22015-07-06 09:31:09 -07002639 ipList = []
2640 for i in range( numControllers ):
2641 ipList.append( nodes[ i ].ip_address )
2642 main.Mininet1.assignSwController( sw=switch, ip=ipList )
Jon Hall58c76b72015-02-23 11:09:24 -08002643 main.log.info( "Waiting " + str( switchSleep ) +
2644 " seconds for switch up to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002645 time.sleep( switchSleep )
2646 device = main.ONOScli1.getDevice( dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002647 # Peek at the deleted switch
2648 main.log.warn( str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002649 result = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002650 if device and device[ 'available' ]:
Jon Hall94fd0472014-12-08 11:52:42 -08002651 result = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002652 utilities.assert_equals( expect=main.TRUE, actual=result,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002653 onpass="add switch successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002654 onfail="Failed to add switch?" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002655
Jon Hall6aec96b2015-01-19 14:49:31 -08002656 def CASE13( self, main ):
2657 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002658 Clean up
Jon Hall6aec96b2015-01-19 14:49:31 -08002659 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002660 import os
2661 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002662 assert numControllers, "numControllers not defined"
2663 assert main, "main not defined"
2664 assert utilities.assert_equals, "utilities.assert_equals not defined"
2665 assert CLIs, "CLIs not defined"
2666 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002667
2668 # printing colors to terminal
Jon Hall5cfd23c2015-03-19 11:40:57 -07002669 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2670 'blue': '\033[94m', 'green': '\033[92m',
2671 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
Jon Hall40d2cbd2015-06-03 16:24:29 -07002672 main.case( "Test Cleanup" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002673 main.step( "Killing tcpdumps" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002674 main.Mininet2.stopTcpdump()
Jon Hall73cf9cc2014-11-20 22:28:38 -08002675
Jon Hall6aec96b2015-01-19 14:49:31 -08002676 main.step( "Copying MN pcap and ONOS log files to test station" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002677 testname = main.TEST
Jon Hall8f89dda2015-01-22 16:03:33 -08002678 teststationUser = main.params[ 'TESTONUSER' ]
2679 teststationIP = main.params[ 'TESTONIP' ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002680 # NOTE: MN Pcap file is being saved to ~/packet_captures
Jon Hall73cf9cc2014-11-20 22:28:38 -08002681 # scp this file as MN and TestON aren't necessarily the same vm
Jon Hall6aec96b2015-01-19 14:49:31 -08002682 # FIXME: scp
2683 # mn files
2684 # TODO: Load these from params
2685 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002686 logFolder = "/opt/onos/log/"
2687 logFiles = [ "karaf.log", "karaf.log.1" ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002688 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002689 dstDir = "~/packet_captures/"
2690 for f in logFiles:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002691 for node in nodes:
2692 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2693 ":" + logFolder + f + " " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002694 teststationUser + "@" +
2695 teststationIP + ":" +
2696 dstDir + str( testname ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002697 "-" + node.name + "-" + f )
Jon Hall58c76b72015-02-23 11:09:24 -08002698 main.ONOSbench.handle.expect( "\$" )
2699
Jon Hall6aec96b2015-01-19 14:49:31 -08002700 # std*.log's
2701 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002702 logFolder = "/opt/onos/var/"
2703 logFiles = [ "stderr.log", "stdout.log" ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002704 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002705 dstDir = "~/packet_captures/"
2706 for f in logFiles:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002707 for node in nodes:
2708 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2709 ":" + logFolder + f + " " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002710 teststationUser + "@" +
2711 teststationIP + ":" +
2712 dstDir + str( testname ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002713 "-" + node.name + "-" + f )
Jon Hall58c76b72015-02-23 11:09:24 -08002714 main.ONOSbench.handle.expect( "\$" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002715 # sleep so scp can finish
2716 time.sleep( 10 )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002717
2718 main.step( "Stopping Mininet" )
Jon Hall390696c2015-05-05 17:13:41 -07002719 mnResult = main.Mininet1.stopNet()
2720 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2721 onpass="Mininet stopped",
2722 onfail="MN cleanup NOT successful" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002723
2724 main.step( "Checking ONOS Logs for errors" )
2725 for node in nodes:
2726 print colors[ 'purple' ] + "Checking logs for errors on " + \
2727 node.name + ":" + colors[ 'end' ]
Jon Hall40d2cbd2015-06-03 16:24:29 -07002728 print main.ONOSbench.checkLogs( node.ip_address, restart=True )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002729
Jon Hall6aec96b2015-01-19 14:49:31 -08002730 main.step( "Packing and rotating pcap archives" )
2731 os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002732
Jon Hallfeff3082015-05-19 10:23:26 -07002733 try:
2734 timerLog = open( main.logdir + "/Timers.csv", 'w')
Jon Hallc9eabec2015-06-10 14:33:14 -07002735 main.log.error( ", ".join( labels ) + "\n" + ", ".join( data ) )
2736 timerLog.write( ", ".join( labels ) + "\n" + ", ".join( data ) )
Jon Hallfeff3082015-05-19 10:23:26 -07002737 timerLog.close()
2738 except NameError, e:
2739 main.log.exception(e)
2740
Jon Hall6aec96b2015-01-19 14:49:31 -08002741 def CASE14( self, main ):
2742 """
Jon Hall669173b2014-12-17 11:36:30 -08002743 start election app on all onos nodes
Jon Hall6aec96b2015-01-19 14:49:31 -08002744 """
Jon Hall5cfd23c2015-03-19 11:40:57 -07002745 assert numControllers, "numControllers not defined"
2746 assert main, "main not defined"
2747 assert utilities.assert_equals, "utilities.assert_equals not defined"
2748 assert CLIs, "CLIs not defined"
2749 assert nodes, "nodes not defined"
2750
Jon Hall390696c2015-05-05 17:13:41 -07002751 main.case("Start Leadership Election app")
2752 main.step( "Install leadership election app" )
Jon Hallfeff3082015-05-19 10:23:26 -07002753 appResult = main.ONOScli1.activateApp( "org.onosproject.election" )
2754 utilities.assert_equals(
2755 expect=main.TRUE,
2756 actual=appResult,
2757 onpass="Election app installed",
2758 onfail="Something went wrong with installing Leadership election" )
2759
2760 main.step( "Run for election on each node" )
2761 leaderResult = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002762 leaders = []
2763 for cli in CLIs:
Jon Hall390696c2015-05-05 17:13:41 -07002764 cli.electionTestRun()
2765 for cli in CLIs:
Jon Halla9d26da2015-03-30 16:45:32 -07002766 leader = cli.electionTestLeader()
2767 if leader is None or leader == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002768 main.log.error( cli.name + ": Leader for the election app " +
Jon Halla9d26da2015-03-30 16:45:32 -07002769 "should be an ONOS node, instead got '" +
2770 str( leader ) + "'" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002771 leaderResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002772 leaders.append( leader )
Jon Hall6aec96b2015-01-19 14:49:31 -08002773 utilities.assert_equals(
2774 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002775 actual=leaderResult,
Jon Hallfeff3082015-05-19 10:23:26 -07002776 onpass="Successfully ran for leadership",
2777 onfail="Failed to run for leadership" )
2778
2779 main.step( "Check that each node shows the same leader" )
2780 sameLeader = main.TRUE
2781 if len( set( leaders ) ) != 1:
2782 sameLeader = main.FALSE
2783 main.log.error( "Results of electionTestLeader is order of CLIs:" +
2784 str( leaders ) )
2785 utilities.assert_equals(
2786 expect=main.TRUE,
2787 actual=sameLeader,
2788 onpass="Leadership is consistent for the election topic",
2789 onfail="Nodes have different leaders" )
Jon Hall669173b2014-12-17 11:36:30 -08002790
Jon Hall6aec96b2015-01-19 14:49:31 -08002791 def CASE15( self, main ):
2792 """
Jon Hall669173b2014-12-17 11:36:30 -08002793 Check that Leadership Election is still functional
Jon Hall6aec96b2015-01-19 14:49:31 -08002794 """
Jon Hall390696c2015-05-05 17:13:41 -07002795 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002796 assert numControllers, "numControllers not defined"
2797 assert main, "main not defined"
2798 assert utilities.assert_equals, "utilities.assert_equals not defined"
2799 assert CLIs, "CLIs not defined"
2800 assert nodes, "nodes not defined"
2801
Jon Hall8f89dda2015-01-22 16:03:33 -08002802 leaderResult = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08002803 description = "Check that Leadership Election is still functional"
Jon Hall6aec96b2015-01-19 14:49:31 -08002804 main.case( description )
Jon Hallfeff3082015-05-19 10:23:26 -07002805 # NOTE: Need to re-run since being a canidate is not persistant
2806 main.step( "Run for election on each node" )
2807 leaderResult = main.TRUE
2808 leaders = []
2809 for cli in CLIs:
2810 cli.electionTestRun()
2811 for cli in CLIs:
2812 leader = cli.electionTestLeader()
2813 if leader is None or leader == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002814 main.log.error( cli.name + ": Leader for the election app " +
Jon Hallfeff3082015-05-19 10:23:26 -07002815 "should be an ONOS node, instead got '" +
2816 str( leader ) + "'" )
2817 leaderResult = main.FALSE
2818 leaders.append( leader )
2819 utilities.assert_equals(
2820 expect=main.TRUE,
2821 actual=leaderResult,
2822 onpass="Successfully ran for leadership",
2823 onfail="Failed to run for leadership" )
2824
2825 main.step( "Check that each node shows the same leader" )
2826 sameLeader = main.TRUE
2827 if len( set( leaders ) ) != 1:
2828 sameLeader = main.FALSE
2829 main.log.error( "Results of electionTestLeader is order of CLIs:" +
2830 str( leaders ) )
2831 utilities.assert_equals(
2832 expect=main.TRUE,
2833 actual=sameLeader,
2834 onpass="Leadership is consistent for the election topic",
2835 onfail="Nodes have different leaders" )
2836
Jon Hall6aec96b2015-01-19 14:49:31 -08002837 main.step( "Find current leader and withdraw" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002838 leader = main.ONOScli1.electionTestLeader()
Jon Halla9d26da2015-03-30 16:45:32 -07002839 # do some sanity checking on leader before using it
Jon Hall8f89dda2015-01-22 16:03:33 -08002840 withdrawResult = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002841 if leader is None or leader == main.FALSE:
Jon Hallfeff3082015-05-19 10:23:26 -07002842 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -08002843 "Leader for the election app should be an ONOS node," +
Jon Hall58c76b72015-02-23 11:09:24 -08002844 "instead got '" + str( leader ) + "'" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002845 leaderResult = main.FALSE
Jon Hall63604932015-02-26 17:09:50 -08002846 oldLeader = None
Jon Hall5cfd23c2015-03-19 11:40:57 -07002847 for i in range( len( CLIs ) ):
2848 if leader == nodes[ i ].ip_address:
2849 oldLeader = CLIs[ i ]
2850 break
Jon Halla9d26da2015-03-30 16:45:32 -07002851 else: # FOR/ELSE statement
Jon Hall5cfd23c2015-03-19 11:40:57 -07002852 main.log.error( "Leader election, could not find current leader" )
Jon Hall63604932015-02-26 17:09:50 -08002853 if oldLeader:
2854 withdrawResult = oldLeader.electionTestWithdraw()
Jon Hall6aec96b2015-01-19 14:49:31 -08002855 utilities.assert_equals(
2856 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002857 actual=withdrawResult,
Jon Hallfeff3082015-05-19 10:23:26 -07002858 onpass="Node was withdrawn from election",
2859 onfail="Node was not withdrawn from election" )
Jon Hall669173b2014-12-17 11:36:30 -08002860
Jon Hall6aec96b2015-01-19 14:49:31 -08002861 main.step( "Make sure new leader is elected" )
Jon Halla9d26da2015-03-30 16:45:32 -07002862 # FIXME: use threads
Jon Hall8f89dda2015-01-22 16:03:33 -08002863 leaderList = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002864 for cli in CLIs:
2865 leaderN = cli.electionTestLeader()
2866 leaderList.append( leaderN )
Jon Hall669173b2014-12-17 11:36:30 -08002867 if leaderN == leader:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002868 main.log.error( cli.name + " still sees " + str( leader ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002869 " as leader after they withdrew" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002870 leaderResult = main.FALSE
Jon Hall669173b2014-12-17 11:36:30 -08002871 elif leaderN == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002872 # error in response
2873 # TODO: add check for "Command not found:" in the driver, this
Jon Hall5cfd23c2015-03-19 11:40:57 -07002874 # means the app isn't loaded
Jon Hall40d2cbd2015-06-03 16:24:29 -07002875 main.log.error( "Something is wrong with " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002876 "electionTestLeader function, " +
Jon Hall6aec96b2015-01-19 14:49:31 -08002877 "check the error logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002878 leaderResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002879 elif leaderN is None:
2880 # node may not have recieved the event yet
Jon Hall390696c2015-05-05 17:13:41 -07002881 time.sleep(7)
Jon Halla9d26da2015-03-30 16:45:32 -07002882 leaderN = cli.electionTestLeader()
2883 leaderList.pop()
2884 leaderList.append( leaderN )
Jon Hall8f89dda2015-01-22 16:03:33 -08002885 consistentLeader = main.FALSE
2886 if len( set( leaderList ) ) == 1:
Jon Hall6aec96b2015-01-19 14:49:31 -08002887 main.log.info( "Each Election-app sees '" +
Jon Hall8f89dda2015-01-22 16:03:33 -08002888 str( leaderList[ 0 ] ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002889 "' as the leader" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002890 consistentLeader = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08002891 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002892 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -08002893 "Inconsistent responses for leader of Election-app:" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002894 for n in range( len( leaderList ) ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07002895 main.log.error( "ONOS" + str( n + 1 ) + " response: " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002896 str( leaderList[ n ] ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002897 leaderResult = leaderResult and consistentLeader
Jon Hall6aec96b2015-01-19 14:49:31 -08002898 utilities.assert_equals(
2899 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002900 actual=leaderResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002901 onpass="Leadership election passed",
2902 onfail="Something went wrong with Leadership election" )
Jon Hall669173b2014-12-17 11:36:30 -08002903
Jon Hall58c76b72015-02-23 11:09:24 -08002904 main.step( "Run for election on old leader( just so everyone " +
2905 "is in the hat )" )
Jon Hall63604932015-02-26 17:09:50 -08002906 if oldLeader:
2907 runResult = oldLeader.electionTestRun()
2908 else:
2909 runResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002910 utilities.assert_equals(
2911 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002912 actual=runResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002913 onpass="App re-ran for election",
2914 onfail="App failed to run for election" )
Jon Hall390696c2015-05-05 17:13:41 -07002915
Jon Hallfeff3082015-05-19 10:23:26 -07002916 main.step( "Leader did not change when old leader re-ran" )
Jon Hall390696c2015-05-05 17:13:41 -07002917 afterRun = main.ONOScli1.electionTestLeader()
2918 # verify leader didn't just change
2919 if afterRun == leaderList[ 0 ]:
2920 afterResult = main.TRUE
2921 else:
2922 afterResult = main.FALSE
Jon Hall669173b2014-12-17 11:36:30 -08002923
Jon Hall6aec96b2015-01-19 14:49:31 -08002924 utilities.assert_equals(
2925 expect=main.TRUE,
Jon Hall390696c2015-05-05 17:13:41 -07002926 actual=afterResult,
2927 onpass="Old leader successfully re-ran for election",
Jon Hall6aec96b2015-01-19 14:49:31 -08002928 onfail="Something went wrong with Leadership election after " +
2929 "the old leader re-ran for election" )
Jon Hall390696c2015-05-05 17:13:41 -07002930
Jon Hall390696c2015-05-05 17:13:41 -07002931 def CASE16( self, main ):
2932 """
2933 Install Distributed Primitives app
2934 """
Jon Hall40d2cbd2015-06-03 16:24:29 -07002935 import time
Jon Hall390696c2015-05-05 17:13:41 -07002936 assert numControllers, "numControllers not defined"
2937 assert main, "main not defined"
2938 assert utilities.assert_equals, "utilities.assert_equals not defined"
2939 assert CLIs, "CLIs not defined"
2940 assert nodes, "nodes not defined"
2941
2942 # Variables for the distributed primitives tests
2943 global pCounterName
2944 global iCounterName
2945 global pCounterValue
2946 global iCounterValue
2947 global onosSet
2948 global onosSetName
2949 pCounterName = "TestON-Partitions"
2950 iCounterName = "TestON-inMemory"
2951 pCounterValue = 0
2952 iCounterValue = 0
2953 onosSet = set([])
2954 onosSetName = "TestON-set"
2955
2956 description = "Install Primitives app"
2957 main.case( description )
2958 main.step( "Install Primitives app" )
2959 appName = "org.onosproject.distributedprimitives"
2960 appResults = CLIs[0].activateApp( appName )
2961 utilities.assert_equals( expect=main.TRUE,
2962 actual=appResults,
2963 onpass="Primitives app activated",
2964 onfail="Primitives app not activated" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002965 time.sleep( 5 ) # To allow all nodes to activate
Jon Hall390696c2015-05-05 17:13:41 -07002966
2967 def CASE17( self, main ):
2968 """
2969 Check for basic functionality with distributed primitives
2970 """
Jon Hallc9eabec2015-06-10 14:33:14 -07002971 import json
Jon Hall390696c2015-05-05 17:13:41 -07002972 # Make sure variables are defined/set
2973 assert numControllers, "numControllers not defined"
2974 assert main, "main not defined"
2975 assert utilities.assert_equals, "utilities.assert_equals not defined"
2976 assert CLIs, "CLIs not defined"
2977 assert nodes, "nodes not defined"
2978 assert pCounterName, "pCounterName not defined"
2979 assert iCounterName, "iCounterName not defined"
2980 assert onosSetName, "onosSetName not defined"
2981 # NOTE: assert fails if value is 0/None/Empty/False
2982 try:
2983 pCounterValue
2984 except NameError:
2985 main.log.error( "pCounterValue not defined, setting to 0" )
2986 pCounterValue = 0
2987 try:
2988 iCounterValue
2989 except NameError:
2990 main.log.error( "iCounterValue not defined, setting to 0" )
2991 iCounterValue = 0
2992 try:
2993 onosSet
2994 except NameError:
2995 main.log.error( "onosSet not defined, setting to empty Set" )
2996 onosSet = set([])
2997 # Variables for the distributed primitives tests. These are local only
2998 addValue = "a"
2999 addAllValue = "a b c d e f"
3000 retainValue = "c d e f"
3001
3002 description = "Check for basic functionality with distributed " +\
3003 "primitives"
3004 main.case( description )
3005 main.caseExplaination = "Test the methods of the distributed primitives (counters and sets) throught the cli"
3006 # DISTRIBUTED ATOMIC COUNTERS
3007 main.step( "Increment and get a default counter on each node" )
3008 pCounters = []
3009 threads = []
Jon Hallfeff3082015-05-19 10:23:26 -07003010 addedPValues = []
Jon Hall390696c2015-05-05 17:13:41 -07003011 for i in range( numControllers ):
3012 t = main.Thread( target=CLIs[i].counterTestIncrement,
3013 name="counterIncrement-" + str( i ),
3014 args=[ pCounterName ] )
3015 pCounterValue += 1
Jon Hallfeff3082015-05-19 10:23:26 -07003016 addedPValues.append( pCounterValue )
Jon Hall390696c2015-05-05 17:13:41 -07003017 threads.append( t )
3018 t.start()
3019
3020 for t in threads:
3021 t.join()
3022 pCounters.append( t.result )
3023 # Check that counter incremented numController times
3024 pCounterResults = True
Jon Hallfeff3082015-05-19 10:23:26 -07003025 for i in addedPValues:
Jon Hall40d2cbd2015-06-03 16:24:29 -07003026 tmpResult = i in pCounters
Jon Hallfeff3082015-05-19 10:23:26 -07003027 pCounterResults = pCounterResults and tmpResult
3028 if not tmpResult:
3029 main.log.error( str( i ) + " is not in partitioned "
3030 "counter incremented results" )
Jon Hall390696c2015-05-05 17:13:41 -07003031 utilities.assert_equals( expect=True,
3032 actual=pCounterResults,
3033 onpass="Default counter incremented",
3034 onfail="Error incrementing default" +
3035 " counter" )
3036
3037 main.step( "Increment and get an in memory counter on each node" )
3038 iCounters = []
Jon Hallfeff3082015-05-19 10:23:26 -07003039 addedIValues = []
Jon Hall390696c2015-05-05 17:13:41 -07003040 threads = []
3041 for i in range( numControllers ):
3042 t = main.Thread( target=CLIs[i].counterTestIncrement,
3043 name="icounterIncrement-" + str( i ),
3044 args=[ iCounterName ],
3045 kwargs={ "inMemory": True } )
3046 iCounterValue += 1
Jon Hallfeff3082015-05-19 10:23:26 -07003047 addedIValues.append( iCounterValue )
Jon Hall390696c2015-05-05 17:13:41 -07003048 threads.append( t )
3049 t.start()
3050
3051 for t in threads:
3052 t.join()
3053 iCounters.append( t.result )
3054 # Check that counter incremented numController times
3055 iCounterResults = True
Jon Hallfeff3082015-05-19 10:23:26 -07003056 for i in addedIValues:
3057 tmpResult = i in iCounters
3058 iCounterResults = iCounterResults and tmpResult
3059 if not tmpResult:
3060 main.log.error( str( i ) + " is not in the in-memory "
3061 "counter incremented results" )
Jon Hall390696c2015-05-05 17:13:41 -07003062 utilities.assert_equals( expect=True,
3063 actual=iCounterResults,
3064 onpass="In memory counter incremented",
3065 onfail="Error incrementing in memory" +
3066 " counter" )
3067
3068 main.step( "Check counters are consistant across nodes" )
3069 onosCounters = []
3070 threads = []
3071 for i in range( numControllers ):
3072 t = main.Thread( target=CLIs[i].counters,
3073 name="counters-" + str( i ) )
3074 threads.append( t )
3075 t.start()
3076 for t in threads:
3077 t.join()
3078 onosCounters.append( t.result )
3079 tmp = [ i == onosCounters[ 0 ] for i in onosCounters ]
3080 if all( tmp ):
3081 main.log.info( "Counters are consistent across all nodes" )
3082 consistentCounterResults = main.TRUE
3083 else:
3084 main.log.error( "Counters are not consistent across all nodes" )
3085 consistentCounterResults = main.FALSE
3086 utilities.assert_equals( expect=main.TRUE,
3087 actual=consistentCounterResults,
3088 onpass="ONOS counters are consistent " +
3089 "across nodes",
3090 onfail="ONOS Counters are inconsistent " +
3091 "across nodes" )
3092
3093 main.step( "Counters we added have the correct values" )
3094 correctResults = main.TRUE
3095 for i in range( numControllers ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07003096 current = json.loads( onosCounters[i] )
3097 pValue = None
3098 iValue = None
Jon Hall390696c2015-05-05 17:13:41 -07003099 try:
Jon Hall40d2cbd2015-06-03 16:24:29 -07003100 for database in current:
3101 partitioned = database.get( 'partitionedDatabaseCounters' )
3102 if partitioned:
3103 for value in partitioned:
3104 if value.get( 'name' ) == pCounterName:
3105 pValue = value.get( 'value' )
3106 break
3107 inMemory = database.get( 'inMemoryDatabaseCounters' )
3108 if inMemory:
3109 for value in inMemory:
3110 if value.get( 'name' ) == iCounterName:
3111 iValue = value.get( 'value' )
3112 break
Jon Hall390696c2015-05-05 17:13:41 -07003113 except AttributeError, e:
3114 main.log.error( "ONOS" + str( i + 1 ) + " counters result " +
3115 "is not as expected" )
3116 correctResults = main.FALSE
Jon Hall40d2cbd2015-06-03 16:24:29 -07003117 if pValue == pCounterValue:
3118 main.log.info( "Partitioned counter value is correct" )
3119 else:
3120 main.log.error( "Partitioned counter value is incorrect," +
3121 " expected value: " + str( pCounterValue )
3122 + " current value: " + str( pValue ) )
3123 correctResults = main.FALSE
3124 if iValue == iCounterValue:
3125 main.log.info( "In memory counter value is correct" )
3126 else:
3127 main.log.error( "In memory counter value is incorrect, " +
3128 "expected value: " + str( iCounterValue ) +
3129 " current value: " + str( iValue ) )
3130 correctResults = main.FALSE
Jon Hall390696c2015-05-05 17:13:41 -07003131 utilities.assert_equals( expect=main.TRUE,
3132 actual=correctResults,
3133 onpass="Added counters are correct",
3134 onfail="Added counters are incorrect" )
3135 # DISTRIBUTED SETS
3136 main.step( "Distributed Set get" )
3137 size = len( onosSet )
3138 getResponses = []
3139 threads = []
3140 for i in range( numControllers ):
3141 t = main.Thread( target=CLIs[i].setTestGet,
3142 name="setTestGet-" + str( i ),
3143 args=[ onosSetName ] )
3144 threads.append( t )
3145 t.start()
3146 for t in threads:
3147 t.join()
3148 getResponses.append( t.result )
3149
3150 getResults = main.TRUE
3151 for i in range( numControllers ):
3152 if isinstance( getResponses[ i ], list):
3153 current = set( getResponses[ i ] )
3154 if len( current ) == len( getResponses[ i ] ):
3155 # no repeats
3156 if onosSet != current:
3157 main.log.error( "ONOS" + str( i + 1 ) +
3158 " has incorrect view" +
3159 " of set " + onosSetName + ":\n" +
3160 str( getResponses[ i ] ) )
3161 main.log.debug( "Expected: " + str( onosSet ) )
3162 main.log.debug( "Actual: " + str( current ) )
3163 getResults = main.FALSE
3164 else:
3165 # error, set is not a set
3166 main.log.error( "ONOS" + str( i + 1 ) +
3167 " has repeat elements in" +
3168 " set " + onosSetName + ":\n" +
3169 str( getResponses[ i ] ) )
3170 getResults = main.FALSE
3171 elif getResponses[ i ] == main.ERROR:
3172 getResults = main.FALSE
3173 utilities.assert_equals( expect=main.TRUE,
3174 actual=getResults,
3175 onpass="Set elements are correct",
3176 onfail="Set elements are incorrect" )
3177
3178 main.step( "Distributed Set size" )
3179 sizeResponses = []
3180 threads = []
3181 for i in range( numControllers ):
3182 t = main.Thread( target=CLIs[i].setTestSize,
3183 name="setTestSize-" + str( i ),
3184 args=[ onosSetName ] )
3185 threads.append( t )
3186 t.start()
3187 for t in threads:
3188 t.join()
3189 sizeResponses.append( t.result )
3190
3191 sizeResults = main.TRUE
3192 for i in range( numControllers ):
3193 if size != sizeResponses[ i ]:
3194 sizeResults = main.FALSE
3195 main.log.error( "ONOS" + str( i + 1 ) +
3196 " expected a size of " + str( size ) +
3197 " for set " + onosSetName +
3198 " but got " + str( sizeResponses[ i ] ) )
3199 utilities.assert_equals( expect=main.TRUE,
3200 actual=sizeResults,
3201 onpass="Set sizes are correct",
3202 onfail="Set sizes are incorrect" )
3203
3204 main.step( "Distributed Set add()" )
3205 onosSet.add( addValue )
3206 addResponses = []
3207 threads = []
3208 for i in range( numControllers ):
3209 t = main.Thread( target=CLIs[i].setTestAdd,
3210 name="setTestAdd-" + str( i ),
3211 args=[ onosSetName, addValue ] )
3212 threads.append( t )
3213 t.start()
3214 for t in threads:
3215 t.join()
3216 addResponses.append( t.result )
3217
3218 # main.TRUE = successfully changed the set
3219 # main.FALSE = action resulted in no change in set
3220 # main.ERROR - Some error in executing the function
3221 addResults = main.TRUE
3222 for i in range( numControllers ):
3223 if addResponses[ i ] == main.TRUE:
3224 # All is well
3225 pass
3226 elif addResponses[ i ] == main.FALSE:
3227 # Already in set, probably fine
3228 pass
3229 elif addResponses[ i ] == main.ERROR:
3230 # Error in execution
3231 addResults = main.FALSE
3232 else:
3233 # unexpected result
3234 addResults = main.FALSE
3235 if addResults != main.TRUE:
3236 main.log.error( "Error executing set add" )
3237
3238 # Check if set is still correct
3239 size = len( onosSet )
3240 getResponses = []
3241 threads = []
3242 for i in range( numControllers ):
3243 t = main.Thread( target=CLIs[i].setTestGet,
3244 name="setTestGet-" + str( i ),
3245 args=[ onosSetName ] )
3246 threads.append( t )
3247 t.start()
3248 for t in threads:
3249 t.join()
3250 getResponses.append( t.result )
3251 getResults = main.TRUE
3252 for i in range( numControllers ):
3253 if isinstance( getResponses[ i ], list):
3254 current = set( getResponses[ i ] )
3255 if len( current ) == len( getResponses[ i ] ):
3256 # no repeats
3257 if onosSet != current:
3258 main.log.error( "ONOS" + str( i + 1 ) +
3259 " has incorrect view" +
3260 " of set " + onosSetName + ":\n" +
3261 str( getResponses[ i ] ) )
3262 main.log.debug( "Expected: " + str( onosSet ) )
3263 main.log.debug( "Actual: " + str( current ) )
3264 getResults = main.FALSE
3265 else:
3266 # error, set is not a set
3267 main.log.error( "ONOS" + str( i + 1 ) +
3268 " has repeat elements in" +
3269 " set " + onosSetName + ":\n" +
3270 str( getResponses[ i ] ) )
3271 getResults = main.FALSE
3272 elif getResponses[ i ] == main.ERROR:
3273 getResults = main.FALSE
3274 sizeResponses = []
3275 threads = []
3276 for i in range( numControllers ):
3277 t = main.Thread( target=CLIs[i].setTestSize,
3278 name="setTestSize-" + str( i ),
3279 args=[ onosSetName ] )
3280 threads.append( t )
3281 t.start()
3282 for t in threads:
3283 t.join()
3284 sizeResponses.append( t.result )
3285 sizeResults = main.TRUE
3286 for i in range( numControllers ):
3287 if size != sizeResponses[ i ]:
3288 sizeResults = main.FALSE
3289 main.log.error( "ONOS" + str( i + 1 ) +
3290 " expected a size of " + str( size ) +
3291 " for set " + onosSetName +
3292 " but got " + str( sizeResponses[ i ] ) )
3293 addResults = addResults and getResults and sizeResults
3294 utilities.assert_equals( expect=main.TRUE,
3295 actual=addResults,
3296 onpass="Set add correct",
3297 onfail="Set add was incorrect" )
3298
3299 main.step( "Distributed Set addAll()" )
3300 onosSet.update( addAllValue.split() )
3301 addResponses = []
3302 threads = []
3303 for i in range( numControllers ):
3304 t = main.Thread( target=CLIs[i].setTestAdd,
3305 name="setTestAddAll-" + str( i ),
3306 args=[ onosSetName, addAllValue ] )
3307 threads.append( t )
3308 t.start()
3309 for t in threads:
3310 t.join()
3311 addResponses.append( t.result )
3312
3313 # main.TRUE = successfully changed the set
3314 # main.FALSE = action resulted in no change in set
3315 # main.ERROR - Some error in executing the function
3316 addAllResults = main.TRUE
3317 for i in range( numControllers ):
3318 if addResponses[ i ] == main.TRUE:
3319 # All is well
3320 pass
3321 elif addResponses[ i ] == main.FALSE:
3322 # Already in set, probably fine
3323 pass
3324 elif addResponses[ i ] == main.ERROR:
3325 # Error in execution
3326 addAllResults = main.FALSE
3327 else:
3328 # unexpected result
3329 addAllResults = main.FALSE
3330 if addAllResults != main.TRUE:
3331 main.log.error( "Error executing set addAll" )
3332
3333 # Check if set is still correct
3334 size = len( onosSet )
3335 getResponses = []
3336 threads = []
3337 for i in range( numControllers ):
3338 t = main.Thread( target=CLIs[i].setTestGet,
3339 name="setTestGet-" + str( i ),
3340 args=[ onosSetName ] )
3341 threads.append( t )
3342 t.start()
3343 for t in threads:
3344 t.join()
3345 getResponses.append( t.result )
3346 getResults = main.TRUE
3347 for i in range( numControllers ):
3348 if isinstance( getResponses[ i ], list):
3349 current = set( getResponses[ i ] )
3350 if len( current ) == len( getResponses[ i ] ):
3351 # no repeats
3352 if onosSet != current:
3353 main.log.error( "ONOS" + str( i + 1 ) +
3354 " has incorrect view" +
3355 " of set " + onosSetName + ":\n" +
3356 str( getResponses[ i ] ) )
3357 main.log.debug( "Expected: " + str( onosSet ) )
3358 main.log.debug( "Actual: " + str( current ) )
3359 getResults = main.FALSE
3360 else:
3361 # error, set is not a set
3362 main.log.error( "ONOS" + str( i + 1 ) +
3363 " has repeat elements in" +
3364 " set " + onosSetName + ":\n" +
3365 str( getResponses[ i ] ) )
3366 getResults = main.FALSE
3367 elif getResponses[ i ] == main.ERROR:
3368 getResults = main.FALSE
3369 sizeResponses = []
3370 threads = []
3371 for i in range( numControllers ):
3372 t = main.Thread( target=CLIs[i].setTestSize,
3373 name="setTestSize-" + str( i ),
3374 args=[ onosSetName ] )
3375 threads.append( t )
3376 t.start()
3377 for t in threads:
3378 t.join()
3379 sizeResponses.append( t.result )
3380 sizeResults = main.TRUE
3381 for i in range( numControllers ):
3382 if size != sizeResponses[ i ]:
3383 sizeResults = main.FALSE
3384 main.log.error( "ONOS" + str( i + 1 ) +
3385 " expected a size of " + str( size ) +
3386 " for set " + onosSetName +
3387 " but got " + str( sizeResponses[ i ] ) )
3388 addAllResults = addAllResults and getResults and sizeResults
3389 utilities.assert_equals( expect=main.TRUE,
3390 actual=addAllResults,
3391 onpass="Set addAll correct",
3392 onfail="Set addAll was incorrect" )
3393
3394 main.step( "Distributed Set contains()" )
3395 containsResponses = []
3396 threads = []
3397 for i in range( numControllers ):
3398 t = main.Thread( target=CLIs[i].setTestGet,
3399 name="setContains-" + str( i ),
3400 args=[ onosSetName ],
3401 kwargs={ "values": addValue } )
3402 threads.append( t )
3403 t.start()
3404 for t in threads:
3405 t.join()
3406 # NOTE: This is the tuple
3407 containsResponses.append( t.result )
3408
3409 containsResults = main.TRUE
3410 for i in range( numControllers ):
3411 if containsResponses[ i ] == main.ERROR:
3412 containsResults = main.FALSE
3413 else:
3414 containsResults = containsResults and\
3415 containsResponses[ i ][ 1 ]
3416 utilities.assert_equals( expect=main.TRUE,
3417 actual=containsResults,
3418 onpass="Set contains is functional",
3419 onfail="Set contains failed" )
3420
3421 main.step( "Distributed Set containsAll()" )
3422 containsAllResponses = []
3423 threads = []
3424 for i in range( numControllers ):
3425 t = main.Thread( target=CLIs[i].setTestGet,
3426 name="setContainsAll-" + str( i ),
3427 args=[ onosSetName ],
3428 kwargs={ "values": addAllValue } )
3429 threads.append( t )
3430 t.start()
3431 for t in threads:
3432 t.join()
3433 # NOTE: This is the tuple
3434 containsAllResponses.append( t.result )
3435
3436 containsAllResults = main.TRUE
3437 for i in range( numControllers ):
3438 if containsResponses[ i ] == main.ERROR:
3439 containsResults = main.FALSE
3440 else:
3441 containsResults = containsResults and\
3442 containsResponses[ i ][ 1 ]
3443 utilities.assert_equals( expect=main.TRUE,
3444 actual=containsAllResults,
3445 onpass="Set containsAll is functional",
3446 onfail="Set containsAll failed" )
3447
3448 main.step( "Distributed Set remove()" )
3449 onosSet.remove( addValue )
3450 removeResponses = []
3451 threads = []
3452 for i in range( numControllers ):
3453 t = main.Thread( target=CLIs[i].setTestRemove,
3454 name="setTestRemove-" + str( i ),
3455 args=[ onosSetName, addValue ] )
3456 threads.append( t )
3457 t.start()
3458 for t in threads:
3459 t.join()
3460 removeResponses.append( t.result )
3461
3462 # main.TRUE = successfully changed the set
3463 # main.FALSE = action resulted in no change in set
3464 # main.ERROR - Some error in executing the function
3465 removeResults = main.TRUE
3466 for i in range( numControllers ):
3467 if removeResponses[ i ] == main.TRUE:
3468 # All is well
3469 pass
3470 elif removeResponses[ i ] == main.FALSE:
3471 # not in set, probably fine
3472 pass
3473 elif removeResponses[ i ] == main.ERROR:
3474 # Error in execution
3475 removeResults = main.FALSE
3476 else:
3477 # unexpected result
3478 removeResults = main.FALSE
3479 if removeResults != main.TRUE:
3480 main.log.error( "Error executing set remove" )
3481
3482 # Check if set is still correct
3483 size = len( onosSet )
3484 getResponses = []
3485 threads = []
3486 for i in range( numControllers ):
3487 t = main.Thread( target=CLIs[i].setTestGet,
3488 name="setTestGet-" + str( i ),
3489 args=[ onosSetName ] )
3490 threads.append( t )
3491 t.start()
3492 for t in threads:
3493 t.join()
3494 getResponses.append( t.result )
3495 getResults = main.TRUE
3496 for i in range( numControllers ):
3497 if isinstance( getResponses[ i ], list):
3498 current = set( getResponses[ i ] )
3499 if len( current ) == len( getResponses[ i ] ):
3500 # no repeats
3501 if onosSet != current:
3502 main.log.error( "ONOS" + str( i + 1 ) +
3503 " has incorrect view" +
3504 " of set " + onosSetName + ":\n" +
3505 str( getResponses[ i ] ) )
3506 main.log.debug( "Expected: " + str( onosSet ) )
3507 main.log.debug( "Actual: " + str( current ) )
3508 getResults = main.FALSE
3509 else:
3510 # error, set is not a set
3511 main.log.error( "ONOS" + str( i + 1 ) +
3512 " has repeat elements in" +
3513 " set " + onosSetName + ":\n" +
3514 str( getResponses[ i ] ) )
3515 getResults = main.FALSE
3516 elif getResponses[ i ] == main.ERROR:
3517 getResults = main.FALSE
3518 sizeResponses = []
3519 threads = []
3520 for i in range( numControllers ):
3521 t = main.Thread( target=CLIs[i].setTestSize,
3522 name="setTestSize-" + str( i ),
3523 args=[ onosSetName ] )
3524 threads.append( t )
3525 t.start()
3526 for t in threads:
3527 t.join()
3528 sizeResponses.append( t.result )
3529 sizeResults = main.TRUE
3530 for i in range( numControllers ):
3531 if size != sizeResponses[ i ]:
3532 sizeResults = main.FALSE
3533 main.log.error( "ONOS" + str( i + 1 ) +
3534 " expected a size of " + str( size ) +
3535 " for set " + onosSetName +
3536 " but got " + str( sizeResponses[ i ] ) )
3537 removeResults = removeResults and getResults and sizeResults
3538 utilities.assert_equals( expect=main.TRUE,
3539 actual=removeResults,
3540 onpass="Set remove correct",
3541 onfail="Set remove was incorrect" )
3542
3543 main.step( "Distributed Set removeAll()" )
3544 onosSet.difference_update( addAllValue.split() )
3545 removeAllResponses = []
3546 threads = []
3547 try:
3548 for i in range( numControllers ):
3549 t = main.Thread( target=CLIs[i].setTestRemove,
3550 name="setTestRemoveAll-" + str( i ),
3551 args=[ onosSetName, addAllValue ] )
3552 threads.append( t )
3553 t.start()
3554 for t in threads:
3555 t.join()
3556 removeAllResponses.append( t.result )
3557 except Exception, e:
3558 main.log.exception(e)
3559
3560 # main.TRUE = successfully changed the set
3561 # main.FALSE = action resulted in no change in set
3562 # main.ERROR - Some error in executing the function
3563 removeAllResults = main.TRUE
3564 for i in range( numControllers ):
3565 if removeAllResponses[ i ] == main.TRUE:
3566 # All is well
3567 pass
3568 elif removeAllResponses[ i ] == main.FALSE:
3569 # not in set, probably fine
3570 pass
3571 elif removeAllResponses[ i ] == main.ERROR:
3572 # Error in execution
3573 removeAllResults = main.FALSE
3574 else:
3575 # unexpected result
3576 removeAllResults = main.FALSE
3577 if removeAllResults != main.TRUE:
3578 main.log.error( "Error executing set removeAll" )
3579
3580 # Check if set is still correct
3581 size = len( onosSet )
3582 getResponses = []
3583 threads = []
3584 for i in range( numControllers ):
3585 t = main.Thread( target=CLIs[i].setTestGet,
3586 name="setTestGet-" + str( i ),
3587 args=[ onosSetName ] )
3588 threads.append( t )
3589 t.start()
3590 for t in threads:
3591 t.join()
3592 getResponses.append( t.result )
3593 getResults = main.TRUE
3594 for i in range( numControllers ):
3595 if isinstance( getResponses[ i ], list):
3596 current = set( getResponses[ i ] )
3597 if len( current ) == len( getResponses[ i ] ):
3598 # no repeats
3599 if onosSet != current:
3600 main.log.error( "ONOS" + str( i + 1 ) +
3601 " has incorrect view" +
3602 " of set " + onosSetName + ":\n" +
3603 str( getResponses[ i ] ) )
3604 main.log.debug( "Expected: " + str( onosSet ) )
3605 main.log.debug( "Actual: " + str( current ) )
3606 getResults = main.FALSE
3607 else:
3608 # error, set is not a set
3609 main.log.error( "ONOS" + str( i + 1 ) +
3610 " has repeat elements in" +
3611 " set " + onosSetName + ":\n" +
3612 str( getResponses[ i ] ) )
3613 getResults = main.FALSE
3614 elif getResponses[ i ] == main.ERROR:
3615 getResults = main.FALSE
3616 sizeResponses = []
3617 threads = []
3618 for i in range( numControllers ):
3619 t = main.Thread( target=CLIs[i].setTestSize,
3620 name="setTestSize-" + str( i ),
3621 args=[ onosSetName ] )
3622 threads.append( t )
3623 t.start()
3624 for t in threads:
3625 t.join()
3626 sizeResponses.append( t.result )
3627 sizeResults = main.TRUE
3628 for i in range( numControllers ):
3629 if size != sizeResponses[ i ]:
3630 sizeResults = main.FALSE
3631 main.log.error( "ONOS" + str( i + 1 ) +
3632 " expected a size of " + str( size ) +
3633 " for set " + onosSetName +
3634 " but got " + str( sizeResponses[ i ] ) )
3635 removeAllResults = removeAllResults and getResults and sizeResults
3636 utilities.assert_equals( expect=main.TRUE,
3637 actual=removeAllResults,
3638 onpass="Set removeAll correct",
3639 onfail="Set removeAll was incorrect" )
3640
3641 main.step( "Distributed Set addAll()" )
3642 onosSet.update( addAllValue.split() )
3643 addResponses = []
3644 threads = []
3645 for i in range( numControllers ):
3646 t = main.Thread( target=CLIs[i].setTestAdd,
3647 name="setTestAddAll-" + str( i ),
3648 args=[ onosSetName, addAllValue ] )
3649 threads.append( t )
3650 t.start()
3651 for t in threads:
3652 t.join()
3653 addResponses.append( t.result )
3654
3655 # main.TRUE = successfully changed the set
3656 # main.FALSE = action resulted in no change in set
3657 # main.ERROR - Some error in executing the function
3658 addAllResults = main.TRUE
3659 for i in range( numControllers ):
3660 if addResponses[ i ] == main.TRUE:
3661 # All is well
3662 pass
3663 elif addResponses[ i ] == main.FALSE:
3664 # Already in set, probably fine
3665 pass
3666 elif addResponses[ i ] == main.ERROR:
3667 # Error in execution
3668 addAllResults = main.FALSE
3669 else:
3670 # unexpected result
3671 addAllResults = main.FALSE
3672 if addAllResults != main.TRUE:
3673 main.log.error( "Error executing set addAll" )
3674
3675 # Check if set is still correct
3676 size = len( onosSet )
3677 getResponses = []
3678 threads = []
3679 for i in range( numControllers ):
3680 t = main.Thread( target=CLIs[i].setTestGet,
3681 name="setTestGet-" + str( i ),
3682 args=[ onosSetName ] )
3683 threads.append( t )
3684 t.start()
3685 for t in threads:
3686 t.join()
3687 getResponses.append( t.result )
3688 getResults = main.TRUE
3689 for i in range( numControllers ):
3690 if isinstance( getResponses[ i ], list):
3691 current = set( getResponses[ i ] )
3692 if len( current ) == len( getResponses[ i ] ):
3693 # no repeats
3694 if onosSet != current:
3695 main.log.error( "ONOS" + str( i + 1 ) +
3696 " has incorrect view" +
3697 " of set " + onosSetName + ":\n" +
3698 str( getResponses[ i ] ) )
3699 main.log.debug( "Expected: " + str( onosSet ) )
3700 main.log.debug( "Actual: " + str( current ) )
3701 getResults = main.FALSE
3702 else:
3703 # error, set is not a set
3704 main.log.error( "ONOS" + str( i + 1 ) +
3705 " has repeat elements in" +
3706 " set " + onosSetName + ":\n" +
3707 str( getResponses[ i ] ) )
3708 getResults = main.FALSE
3709 elif getResponses[ i ] == main.ERROR:
3710 getResults = main.FALSE
3711 sizeResponses = []
3712 threads = []
3713 for i in range( numControllers ):
3714 t = main.Thread( target=CLIs[i].setTestSize,
3715 name="setTestSize-" + str( i ),
3716 args=[ onosSetName ] )
3717 threads.append( t )
3718 t.start()
3719 for t in threads:
3720 t.join()
3721 sizeResponses.append( t.result )
3722 sizeResults = main.TRUE
3723 for i in range( numControllers ):
3724 if size != sizeResponses[ i ]:
3725 sizeResults = main.FALSE
3726 main.log.error( "ONOS" + str( i + 1 ) +
3727 " expected a size of " + str( size ) +
3728 " for set " + onosSetName +
3729 " but got " + str( sizeResponses[ i ] ) )
3730 addAllResults = addAllResults and getResults and sizeResults
3731 utilities.assert_equals( expect=main.TRUE,
3732 actual=addAllResults,
3733 onpass="Set addAll correct",
3734 onfail="Set addAll was incorrect" )
3735
3736 main.step( "Distributed Set clear()" )
3737 onosSet.clear()
3738 clearResponses = []
3739 threads = []
3740 for i in range( numControllers ):
3741 t = main.Thread( target=CLIs[i].setTestRemove,
3742 name="setTestClear-" + str( i ),
3743 args=[ onosSetName, " "], # Values doesn't matter
3744 kwargs={ "clear": True } )
3745 threads.append( t )
3746 t.start()
3747 for t in threads:
3748 t.join()
3749 clearResponses.append( t.result )
3750
3751 # main.TRUE = successfully changed the set
3752 # main.FALSE = action resulted in no change in set
3753 # main.ERROR - Some error in executing the function
3754 clearResults = main.TRUE
3755 for i in range( numControllers ):
3756 if clearResponses[ i ] == main.TRUE:
3757 # All is well
3758 pass
3759 elif clearResponses[ i ] == main.FALSE:
3760 # Nothing set, probably fine
3761 pass
3762 elif clearResponses[ i ] == main.ERROR:
3763 # Error in execution
3764 clearResults = main.FALSE
3765 else:
3766 # unexpected result
3767 clearResults = main.FALSE
3768 if clearResults != main.TRUE:
3769 main.log.error( "Error executing set clear" )
3770
3771 # Check if set is still correct
3772 size = len( onosSet )
3773 getResponses = []
3774 threads = []
3775 for i in range( numControllers ):
3776 t = main.Thread( target=CLIs[i].setTestGet,
3777 name="setTestGet-" + str( i ),
3778 args=[ onosSetName ] )
3779 threads.append( t )
3780 t.start()
3781 for t in threads:
3782 t.join()
3783 getResponses.append( t.result )
3784 getResults = main.TRUE
3785 for i in range( numControllers ):
3786 if isinstance( getResponses[ i ], list):
3787 current = set( getResponses[ i ] )
3788 if len( current ) == len( getResponses[ i ] ):
3789 # no repeats
3790 if onosSet != current:
3791 main.log.error( "ONOS" + str( i + 1 ) +
3792 " has incorrect view" +
3793 " of set " + onosSetName + ":\n" +
3794 str( getResponses[ i ] ) )
3795 main.log.debug( "Expected: " + str( onosSet ) )
3796 main.log.debug( "Actual: " + str( current ) )
3797 getResults = main.FALSE
3798 else:
3799 # error, set is not a set
3800 main.log.error( "ONOS" + str( i + 1 ) +
3801 " has repeat elements in" +
3802 " set " + onosSetName + ":\n" +
3803 str( getResponses[ i ] ) )
3804 getResults = main.FALSE
3805 elif getResponses[ i ] == main.ERROR:
3806 getResults = main.FALSE
3807 sizeResponses = []
3808 threads = []
3809 for i in range( numControllers ):
3810 t = main.Thread( target=CLIs[i].setTestSize,
3811 name="setTestSize-" + str( i ),
3812 args=[ onosSetName ] )
3813 threads.append( t )
3814 t.start()
3815 for t in threads:
3816 t.join()
3817 sizeResponses.append( t.result )
3818 sizeResults = main.TRUE
3819 for i in range( numControllers ):
3820 if size != sizeResponses[ i ]:
3821 sizeResults = main.FALSE
3822 main.log.error( "ONOS" + str( i + 1 ) +
3823 " expected a size of " + str( size ) +
3824 " for set " + onosSetName +
3825 " but got " + str( sizeResponses[ i ] ) )
3826 clearResults = clearResults and getResults and sizeResults
3827 utilities.assert_equals( expect=main.TRUE,
3828 actual=clearResults,
3829 onpass="Set clear correct",
3830 onfail="Set clear was incorrect" )
3831
3832 main.step( "Distributed Set addAll()" )
3833 onosSet.update( addAllValue.split() )
3834 addResponses = []
3835 threads = []
3836 for i in range( numControllers ):
3837 t = main.Thread( target=CLIs[i].setTestAdd,
3838 name="setTestAddAll-" + str( i ),
3839 args=[ onosSetName, addAllValue ] )
3840 threads.append( t )
3841 t.start()
3842 for t in threads:
3843 t.join()
3844 addResponses.append( t.result )
3845
3846 # main.TRUE = successfully changed the set
3847 # main.FALSE = action resulted in no change in set
3848 # main.ERROR - Some error in executing the function
3849 addAllResults = main.TRUE
3850 for i in range( numControllers ):
3851 if addResponses[ i ] == main.TRUE:
3852 # All is well
3853 pass
3854 elif addResponses[ i ] == main.FALSE:
3855 # Already in set, probably fine
3856 pass
3857 elif addResponses[ i ] == main.ERROR:
3858 # Error in execution
3859 addAllResults = main.FALSE
3860 else:
3861 # unexpected result
3862 addAllResults = main.FALSE
3863 if addAllResults != main.TRUE:
3864 main.log.error( "Error executing set addAll" )
3865
3866 # Check if set is still correct
3867 size = len( onosSet )
3868 getResponses = []
3869 threads = []
3870 for i in range( numControllers ):
3871 t = main.Thread( target=CLIs[i].setTestGet,
3872 name="setTestGet-" + str( i ),
3873 args=[ onosSetName ] )
3874 threads.append( t )
3875 t.start()
3876 for t in threads:
3877 t.join()
3878 getResponses.append( t.result )
3879 getResults = main.TRUE
3880 for i in range( numControllers ):
3881 if isinstance( getResponses[ i ], list):
3882 current = set( getResponses[ i ] )
3883 if len( current ) == len( getResponses[ i ] ):
3884 # no repeats
3885 if onosSet != current:
3886 main.log.error( "ONOS" + str( i + 1 ) +
3887 " has incorrect view" +
3888 " of set " + onosSetName + ":\n" +
3889 str( getResponses[ i ] ) )
3890 main.log.debug( "Expected: " + str( onosSet ) )
3891 main.log.debug( "Actual: " + str( current ) )
3892 getResults = main.FALSE
3893 else:
3894 # error, set is not a set
3895 main.log.error( "ONOS" + str( i + 1 ) +
3896 " has repeat elements in" +
3897 " set " + onosSetName + ":\n" +
3898 str( getResponses[ i ] ) )
3899 getResults = main.FALSE
3900 elif getResponses[ i ] == main.ERROR:
3901 getResults = main.FALSE
3902 sizeResponses = []
3903 threads = []
3904 for i in range( numControllers ):
3905 t = main.Thread( target=CLIs[i].setTestSize,
3906 name="setTestSize-" + str( i ),
3907 args=[ onosSetName ] )
3908 threads.append( t )
3909 t.start()
3910 for t in threads:
3911 t.join()
3912 sizeResponses.append( t.result )
3913 sizeResults = main.TRUE
3914 for i in range( numControllers ):
3915 if size != sizeResponses[ i ]:
3916 sizeResults = main.FALSE
3917 main.log.error( "ONOS" + str( i + 1 ) +
3918 " expected a size of " + str( size ) +
3919 " for set " + onosSetName +
3920 " but got " + str( sizeResponses[ i ] ) )
3921 addAllResults = addAllResults and getResults and sizeResults
3922 utilities.assert_equals( expect=main.TRUE,
3923 actual=addAllResults,
3924 onpass="Set addAll correct",
3925 onfail="Set addAll was incorrect" )
3926
3927 main.step( "Distributed Set retain()" )
3928 onosSet.intersection_update( retainValue.split() )
3929 retainResponses = []
3930 threads = []
3931 for i in range( numControllers ):
3932 t = main.Thread( target=CLIs[i].setTestRemove,
3933 name="setTestRetain-" + str( i ),
3934 args=[ onosSetName, retainValue ],
3935 kwargs={ "retain": True } )
3936 threads.append( t )
3937 t.start()
3938 for t in threads:
3939 t.join()
3940 retainResponses.append( t.result )
3941
3942 # main.TRUE = successfully changed the set
3943 # main.FALSE = action resulted in no change in set
3944 # main.ERROR - Some error in executing the function
3945 retainResults = main.TRUE
3946 for i in range( numControllers ):
3947 if retainResponses[ i ] == main.TRUE:
3948 # All is well
3949 pass
3950 elif retainResponses[ i ] == main.FALSE:
3951 # Already in set, probably fine
3952 pass
3953 elif retainResponses[ i ] == main.ERROR:
3954 # Error in execution
3955 retainResults = main.FALSE
3956 else:
3957 # unexpected result
3958 retainResults = main.FALSE
3959 if retainResults != main.TRUE:
3960 main.log.error( "Error executing set retain" )
3961
3962 # Check if set is still correct
3963 size = len( onosSet )
3964 getResponses = []
3965 threads = []
3966 for i in range( numControllers ):
3967 t = main.Thread( target=CLIs[i].setTestGet,
3968 name="setTestGet-" + str( i ),
3969 args=[ onosSetName ] )
3970 threads.append( t )
3971 t.start()
3972 for t in threads:
3973 t.join()
3974 getResponses.append( t.result )
3975 getResults = main.TRUE
3976 for i in range( numControllers ):
3977 if isinstance( getResponses[ i ], list):
3978 current = set( getResponses[ i ] )
3979 if len( current ) == len( getResponses[ i ] ):
3980 # no repeats
3981 if onosSet != current:
3982 main.log.error( "ONOS" + str( i + 1 ) +
3983 " has incorrect view" +
3984 " of set " + onosSetName + ":\n" +
3985 str( getResponses[ i ] ) )
3986 main.log.debug( "Expected: " + str( onosSet ) )
3987 main.log.debug( "Actual: " + str( current ) )
3988 getResults = main.FALSE
3989 else:
3990 # error, set is not a set
3991 main.log.error( "ONOS" + str( i + 1 ) +
3992 " has repeat elements in" +
3993 " set " + onosSetName + ":\n" +
3994 str( getResponses[ i ] ) )
3995 getResults = main.FALSE
3996 elif getResponses[ i ] == main.ERROR:
3997 getResults = main.FALSE
3998 sizeResponses = []
3999 threads = []
4000 for i in range( numControllers ):
4001 t = main.Thread( target=CLIs[i].setTestSize,
4002 name="setTestSize-" + str( i ),
4003 args=[ onosSetName ] )
4004 threads.append( t )
4005 t.start()
4006 for t in threads:
4007 t.join()
4008 sizeResponses.append( t.result )
4009 sizeResults = main.TRUE
4010 for i in range( numControllers ):
4011 if size != sizeResponses[ i ]:
4012 sizeResults = main.FALSE
4013 main.log.error( "ONOS" + str( i + 1 ) +
4014 " expected a size of " +
4015 str( size ) + " for set " + onosSetName +
4016 " but got " + str( sizeResponses[ i ] ) )
4017 retainResults = retainResults and getResults and sizeResults
4018 utilities.assert_equals( expect=main.TRUE,
4019 actual=retainResults,
4020 onpass="Set retain correct",
4021 onfail="Set retain was incorrect" )
4022