blob: 3bb5e87bcc70aa3622605d828d7f4aee9c0f4992 [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 Hall5cfd23c2015-03-19 11:40:57 -0700273 # TODO: rewrite this function to take lists of ips and ports?
274 # or list of tuples?
Jon Hall6aec96b2015-01-19 14:49:31 -0800275 for i in range( 1, 29 ):
Jon Hall8f89dda2015-01-22 16:03:33 -0800276 main.Mininet1.assignSwController(
Jon Hall6aec96b2015-01-19 14:49:31 -0800277 sw=str( i ),
Jon Hall8f89dda2015-01-22 16:03:33 -0800278 count=numControllers,
Jon Hall5cfd23c2015-03-19 11:40:57 -0700279 ip1=nodes[ 0 ].ip_address, port1=ONOS1Port,
280 ip2=nodes[ 1 ].ip_address, port2=ONOS2Port,
281 ip3=nodes[ 2 ].ip_address, port3=ONOS3Port,
282 ip4=nodes[ 3 ].ip_address, port4=ONOS4Port,
283 ip5=nodes[ 4 ].ip_address, port5=ONOS5Port,
284 ip6=nodes[ 5 ].ip_address, port6=ONOS6Port,
285 ip7=nodes[ 6 ].ip_address, port7=ONOS7Port )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800286
Jon Hall8f89dda2015-01-22 16:03:33 -0800287 mastershipCheck = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -0800288 for i in range( 1, 29 ):
Jon Hall8f89dda2015-01-22 16:03:33 -0800289 response = main.Mininet1.getSwController( "s" + str( i ) )
Jon Hallffb386d2014-11-21 13:43:38 -0800290 try:
Jon Hall6aec96b2015-01-19 14:49:31 -0800291 main.log.info( str( response ) )
Jon Hallfebb1c72015-03-05 13:30:09 -0800292 except Exception:
Jon Hall6aec96b2015-01-19 14:49:31 -0800293 main.log.info( repr( response ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700294 for node in nodes:
295 if re.search( "tcp:" + node.ip_address, response ):
296 mastershipCheck = mastershipCheck and main.TRUE
297 else:
Jon Halla9d26da2015-03-30 16:45:32 -0700298 main.log.error( "Error, node " + node.ip_address + " is " +
299 "not in the list of controllers s" +
300 str( i ) + " is connecting to." )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700301 mastershipCheck = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -0800302 utilities.assert_equals(
303 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800304 actual=mastershipCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -0800305 onpass="Switch mastership assigned correctly",
306 onfail="Switches not assigned correctly to controllers" )
Jon Hall390696c2015-05-05 17:13:41 -0700307
Jon Hallc9eabec2015-06-10 14:33:14 -0700308 def CASE21( self, main ):
309 """
310 Assign mastership to controllers
311 """
312 import re
313 import time
314 assert numControllers, "numControllers not defined"
315 assert main, "main not defined"
316 assert utilities.assert_equals, "utilities.assert_equals not defined"
317 assert CLIs, "CLIs not defined"
318 assert nodes, "nodes not defined"
319 assert ONOS1Port, "ONOS1Port not defined"
320 assert ONOS2Port, "ONOS2Port not defined"
321 assert ONOS3Port, "ONOS3Port not defined"
322 assert ONOS4Port, "ONOS4Port not defined"
323 assert ONOS5Port, "ONOS5Port not defined"
324 assert ONOS6Port, "ONOS6Port not defined"
325 assert ONOS7Port, "ONOS7Port not defined"
326
327 main.case( "Assigning Controller roles for switches" )
328 main.caseExplaination = "Check that ONOS is connected to each " +\
329 "device. Then manually assign" +\
330 " mastership to specific ONOS nodes using" +\
331 " 'device-role'"
Jon Hall390696c2015-05-05 17:13:41 -0700332 main.step( "Assign mastership of switches to specific controllers" )
Jon Hall6aec96b2015-01-19 14:49:31 -0800333 # Manually assign mastership to the controller we want
Jon Hall8f89dda2015-01-22 16:03:33 -0800334 roleCall = main.TRUE
Jon Hall390696c2015-05-05 17:13:41 -0700335
336 ipList = [ ]
337 deviceList = []
Jon Hall58c76b72015-02-23 11:09:24 -0800338 try:
Jon Halla9d26da2015-03-30 16:45:32 -0700339 for i in range( 1, 29 ): # switches 1 through 28
340 # set up correct variables:
341 if i == 1:
342 ip = nodes[ 0 ].ip_address # ONOS1
343 deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
344 elif i == 2:
345 ip = nodes[ 1 ].ip_address # ONOS2
346 deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
347 elif i == 3:
348 ip = nodes[ 1 ].ip_address # ONOS2
349 deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
350 elif i == 4:
351 ip = nodes[ 3 ].ip_address # ONOS4
352 deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
353 elif i == 5:
354 ip = nodes[ 2 ].ip_address # ONOS3
355 deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
356 elif i == 6:
357 ip = nodes[ 2 ].ip_address # ONOS3
358 deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
359 elif i == 7:
360 ip = nodes[ 5 ].ip_address # ONOS6
361 deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
362 elif i >= 8 and i <= 17:
363 ip = nodes[ 4 ].ip_address # ONOS5
364 dpid = '3' + str( i ).zfill( 3 )
365 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
366 elif i >= 18 and i <= 27:
367 ip = nodes[ 6 ].ip_address # ONOS7
368 dpid = '6' + str( i ).zfill( 3 )
369 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
370 elif i == 28:
371 ip = nodes[ 0 ].ip_address # ONOS1
372 deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
373 else:
374 main.log.error( "You didn't write an else statement for " +
375 "switch s" + str( i ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700376 roleCall = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -0700377 # Assign switch
378 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
379 # TODO: make this controller dynamic
380 roleCall = roleCall and main.ONOScli1.deviceRole( deviceId,
381 ip )
Jon Hall390696c2015-05-05 17:13:41 -0700382 ipList.append( ip )
383 deviceList.append( deviceId )
Jon Hall58c76b72015-02-23 11:09:24 -0800384 except ( AttributeError, AssertionError ):
385 main.log.exception( "Something is wrong with ONOS device view" )
386 main.log.info( main.ONOScli1.devices() )
Jon Hall6aec96b2015-01-19 14:49:31 -0800387 utilities.assert_equals(
388 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800389 actual=roleCall,
Jon Hall6aec96b2015-01-19 14:49:31 -0800390 onpass="Re-assigned switch mastership to designated controller",
Jon Hall8f89dda2015-01-22 16:03:33 -0800391 onfail="Something wrong with deviceRole calls" )
Jon Hall94fd0472014-12-08 11:52:42 -0800392
Jon Hall390696c2015-05-05 17:13:41 -0700393 main.step( "Check mastership was correctly assigned" )
394 roleCheck = main.TRUE
395 # NOTE: This is due to the fact that device mastership change is not
396 # atomic and is actually a multi step process
397 time.sleep( 5 )
398 for i in range( len( ipList ) ):
399 ip = ipList[i]
400 deviceId = deviceList[i]
401 # Check assignment
402 master = main.ONOScli1.getRole( deviceId ).get( 'master' )
403 if ip in master:
404 roleCheck = roleCheck and main.TRUE
405 else:
406 roleCheck = roleCheck and main.FALSE
407 main.log.error( "Error, controller " + ip + " is not" +
408 " master " + "of device " +
409 str( deviceId ) + ". Master is " +
410 repr( master ) + "." )
Jon Hall6aec96b2015-01-19 14:49:31 -0800411 utilities.assert_equals(
412 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800413 actual=roleCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -0800414 onpass="Switches were successfully reassigned to designated " +
415 "controller",
416 onfail="Switches were not successfully reassigned" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800417
Jon Hall6aec96b2015-01-19 14:49:31 -0800418 def CASE3( self, main ):
Jon Hall73cf9cc2014-11-20 22:28:38 -0800419 """
420 Assign intents
Jon Hall73cf9cc2014-11-20 22:28:38 -0800421 """
422 import time
Jon Hall58c76b72015-02-23 11:09:24 -0800423 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -0700424 assert numControllers, "numControllers not defined"
425 assert main, "main not defined"
426 assert utilities.assert_equals, "utilities.assert_equals not defined"
427 assert CLIs, "CLIs not defined"
428 assert nodes, "nodes not defined"
Jon Hallc9eabec2015-06-10 14:33:14 -0700429 try:
430 labels
431 except NameError:
432 main.log.error( "labels not defined, setting to []" )
433 labels = []
434 try:
435 data
436 except NameError:
437 main.log.error( "data not defined, setting to []" )
438 data = []
Jon Hallfeff3082015-05-19 10:23:26 -0700439 # NOTE: we must reinstall intents until we have a persistant intent
440 # datastore!
Jon Hall6aec96b2015-01-19 14:49:31 -0800441 main.case( "Adding host Intents" )
Jon Hallfeff3082015-05-19 10:23:26 -0700442 main.caseExplaination = "Discover hosts by using pingall then " +\
443 "assign predetermined host-to-host intents." +\
444 " After installation, check that the intent" +\
445 " is distributed to all nodes and the state" +\
446 " is INSTALLED"
Jon Hall73cf9cc2014-11-20 22:28:38 -0800447
Jon Hall6aec96b2015-01-19 14:49:31 -0800448 # install onos-app-fwd
Jon Hall390696c2015-05-05 17:13:41 -0700449 main.step( "Install reactive forwarding app" )
450 installResults = CLIs[0].activateApp( "org.onosproject.fwd" )
451 utilities.assert_equals( expect=main.TRUE, actual=installResults,
452 onpass="Install fwd successful",
453 onfail="Install fwd failed" )
Jon Halla9d26da2015-03-30 16:45:32 -0700454
Jon Hallfeff3082015-05-19 10:23:26 -0700455 main.step( "Check app ids" )
Jon Halla9d26da2015-03-30 16:45:32 -0700456 appCheck = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -0700457 threads = []
458 for i in range( numControllers ):
Jon Halla9d26da2015-03-30 16:45:32 -0700459 t = main.Thread( target=CLIs[i].appToIDCheck,
460 name="appToIDCheck-" + str( i ),
461 args=[] )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700462 threads.append( t )
463 t.start()
464
465 for t in threads:
466 t.join()
Jon Halla9d26da2015-03-30 16:45:32 -0700467 appCheck = appCheck and t.result
Jon Halla9d26da2015-03-30 16:45:32 -0700468 if appCheck != main.TRUE:
469 main.log.warn( CLIs[0].apps() )
470 main.log.warn( CLIs[0].appIDs() )
Jon Hall390696c2015-05-05 17:13:41 -0700471 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
472 onpass="App Ids seem to be correct",
473 onfail="Something is wrong with app Ids" )
Jon Hall94fd0472014-12-08 11:52:42 -0800474
Jon Hallfeff3082015-05-19 10:23:26 -0700475 main.step( "Discovering Hosts( Via pingall for now )" )
476 # FIXME: Once we have a host discovery mechanism, use that instead
Jon Hall6aec96b2015-01-19 14:49:31 -0800477 # REACTIVE FWD test
Jon Hall8f89dda2015-01-22 16:03:33 -0800478 pingResult = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -0700479 for i in range(2): # Retry if pingall fails first time
480 time1 = time.time()
481 pingResult = main.Mininet1.pingall()
482 utilities.assert_equals(
483 expect=main.TRUE,
484 actual=pingResult,
485 onpass="Reactive Pingall test passed",
Jon Hall390696c2015-05-05 17:13:41 -0700486 onfail="Reactive Pingall failed, " +
487 "one or more ping pairs failed" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700488 time2 = time.time()
Jon Hall390696c2015-05-05 17:13:41 -0700489 main.log.info( "Time for pingall: %2f seconds" %
490 ( time2 - time1 ) )
491 # timeout for fwd flows
492 time.sleep( 11 )
Jon Hall6aec96b2015-01-19 14:49:31 -0800493 # uninstall onos-app-fwd
Jon Hall390696c2015-05-05 17:13:41 -0700494 main.step( "Uninstall reactive forwarding app" )
495 uninstallResult = CLIs[0].deactivateApp( "org.onosproject.fwd" )
496 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
497 onpass="Uninstall fwd successful",
498 onfail="Uninstall fwd failed" )
Jon Hallfeff3082015-05-19 10:23:26 -0700499
500 main.step( "Check app ids" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700501 threads = []
Jon Hallfeff3082015-05-19 10:23:26 -0700502 appCheck2 = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -0700503 for i in range( numControllers ):
Jon Halla9d26da2015-03-30 16:45:32 -0700504 t = main.Thread( target=CLIs[i].appToIDCheck,
505 name="appToIDCheck-" + str( i ),
506 args=[] )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700507 threads.append( t )
508 t.start()
Jon Hall73cf9cc2014-11-20 22:28:38 -0800509
Jon Hall5cfd23c2015-03-19 11:40:57 -0700510 for t in threads:
511 t.join()
Jon Hallfeff3082015-05-19 10:23:26 -0700512 appCheck2 = appCheck2 and t.result
513 if appCheck2 != main.TRUE:
Jon Halla9d26da2015-03-30 16:45:32 -0700514 main.log.warn( CLIs[0].apps() )
515 main.log.warn( CLIs[0].appIDs() )
Jon Hallfeff3082015-05-19 10:23:26 -0700516 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
Jon Hall390696c2015-05-05 17:13:41 -0700517 onpass="App Ids seem to be correct",
518 onfail="Something is wrong with app Ids" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700519
Jon Hallfeff3082015-05-19 10:23:26 -0700520 main.step( "Add host intents via cli" )
Jon Hall58c76b72015-02-23 11:09:24 -0800521 intentIds = []
Jon Hall6aec96b2015-01-19 14:49:31 -0800522 # TODO: move the host numbers to params
Jon Hall58c76b72015-02-23 11:09:24 -0800523 # Maybe look at all the paths we ping?
Jon Hall8f89dda2015-01-22 16:03:33 -0800524 intentAddResult = True
Jon Hall58c76b72015-02-23 11:09:24 -0800525 hostResult = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -0800526 for i in range( 8, 18 ):
527 main.log.info( "Adding host intent between h" + str( i ) +
528 " and h" + str( i + 10 ) )
529 host1 = "00:00:00:00:00:" + \
530 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
531 host2 = "00:00:00:00:00:" + \
532 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
Jon Hall1b8f54a2015-02-04 13:24:20 -0800533 # NOTE: getHost can return None
534 host1Dict = main.ONOScli1.getHost( host1 )
535 host2Dict = main.ONOScli1.getHost( host2 )
536 host1Id = None
537 host2Id = None
538 if host1Dict and host2Dict:
539 host1Id = host1Dict.get( 'id', None )
540 host2Id = host2Dict.get( 'id', None )
Jon Hall8f89dda2015-01-22 16:03:33 -0800541 if host1Id and host2Id:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700542 nodeNum = ( i % 7 )
543 tmpId = CLIs[ nodeNum ].addHostIntent( host1Id, host2Id )
Jon Hall63604932015-02-26 17:09:50 -0800544 if tmpId:
545 main.log.info( "Added intent with id: " + tmpId )
546 intentIds.append( tmpId )
547 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700548 main.log.error( "addHostIntent returned: " +
549 repr( tmpId ) )
Jon Hall669173b2014-12-17 11:36:30 -0800550 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700551 main.log.error( "Error, getHost() failed for h" + str( i ) +
552 " and/or h" + str( i + 10 ) )
553 hosts = CLIs[ 0 ].hosts()
554 main.log.warn( "Hosts output: " )
555 try:
556 main.log.warn( json.dumps( json.loads( hosts ),
557 sort_keys=True,
558 indent=4,
559 separators=( ',', ': ' ) ) )
560 except ( ValueError, TypeError ):
561 main.log.warn( repr( hosts ) )
Jon Hall58c76b72015-02-23 11:09:24 -0800562 hostResult = main.FALSE
Jon Hallfeff3082015-05-19 10:23:26 -0700563 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
564 onpass="Found a host id for each host",
565 onfail="Error looking up host ids" )
566
Jon Halla9d26da2015-03-30 16:45:32 -0700567 intentStart = time.time()
Jon Hall58c76b72015-02-23 11:09:24 -0800568 onosIds = main.ONOScli1.getAllIntentsId()
569 main.log.info( "Submitted intents: " + str( intentIds ) )
570 main.log.info( "Intents in ONOS: " + str( onosIds ) )
571 for intent in intentIds:
572 if intent in onosIds:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700573 pass # intent submitted is in onos
Jon Hall58c76b72015-02-23 11:09:24 -0800574 else:
575 intentAddResult = False
Jon Halla9d26da2015-03-30 16:45:32 -0700576 if intentAddResult:
577 intentStop = time.time()
578 else:
579 intentStop = None
Jon Hall1b8f54a2015-02-04 13:24:20 -0800580 # Print the intent states
Jon Hall58c76b72015-02-23 11:09:24 -0800581 intents = main.ONOScli1.intents()
Jon Hall1b8f54a2015-02-04 13:24:20 -0800582 intentStates = []
Jon Hall63604932015-02-26 17:09:50 -0800583 installedCheck = True
Jon Hall58c76b72015-02-23 11:09:24 -0800584 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
585 count = 0
Jon Hall5cfd23c2015-03-19 11:40:57 -0700586 try:
587 for intent in json.loads( intents ):
588 state = intent.get( 'state', None )
589 if "INSTALLED" not in state:
590 installedCheck = False
591 intentId = intent.get( 'id', None )
592 intentStates.append( ( intentId, state ) )
593 except ( ValueError, TypeError ):
594 main.log.exception( "Error parsing intents" )
Jon Hall58c76b72015-02-23 11:09:24 -0800595 # add submitted intents not in the store
596 tmplist = [ i for i, s in intentStates ]
597 missingIntents = False
598 for i in intentIds:
599 if i not in tmplist:
600 intentStates.append( ( i, " - " ) )
601 missingIntents = True
602 intentStates.sort()
603 for i, s in intentStates:
604 count += 1
605 main.log.info( "%-6s%-15s%-15s" %
606 ( str( count ), str( i ), str( s ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700607 leaders = main.ONOScli1.leaders()
608 try:
Jon Hallc9eabec2015-06-10 14:33:14 -0700609 missing = False
Jon Hall5cfd23c2015-03-19 11:40:57 -0700610 if leaders:
611 parsedLeaders = json.loads( leaders )
612 main.log.warn( json.dumps( parsedLeaders,
613 sort_keys=True,
614 indent=4,
615 separators=( ',', ': ' ) ) )
616 # check for all intent partitions
Jon Hall5cfd23c2015-03-19 11:40:57 -0700617 topics = []
618 for i in range( 14 ):
619 topics.append( "intent-partition-" + str( i ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700620 main.log.debug( topics )
621 ONOStopics = [ j['topic'] for j in parsedLeaders ]
622 for topic in topics:
623 if topic not in ONOStopics:
624 main.log.error( "Error: " + topic +
625 " not in leaders" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700626 missing = True
Jon Hall5cfd23c2015-03-19 11:40:57 -0700627 else:
628 main.log.error( "leaders() returned None" )
629 except ( ValueError, TypeError ):
630 main.log.exception( "Error parsing leaders" )
631 main.log.error( repr( leaders ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700632 # Check all nodes
633 if missing:
634 for node in CLIs:
635 response = node.leaders( jsonFormat=False)
636 main.log.warn( str( node.name ) + " leaders output: \n" +
637 str( response ) )
638
Jon Hall5cfd23c2015-03-19 11:40:57 -0700639 partitions = main.ONOScli1.partitions()
640 try:
641 if partitions :
642 parsedPartitions = json.loads( partitions )
643 main.log.warn( json.dumps( parsedPartitions,
644 sort_keys=True,
645 indent=4,
646 separators=( ',', ': ' ) ) )
647 # TODO check for a leader in all paritions
648 # TODO check for consistency among nodes
649 else:
650 main.log.error( "partitions() returned None" )
651 except ( ValueError, TypeError ):
652 main.log.exception( "Error parsing partitions" )
653 main.log.error( repr( partitions ) )
Jon Hall63604932015-02-26 17:09:50 -0800654 pendingMap = main.ONOScli1.pendingMap()
Jon Hall5cfd23c2015-03-19 11:40:57 -0700655 try:
656 if pendingMap :
657 parsedPending = json.loads( pendingMap )
658 main.log.warn( json.dumps( parsedPending,
659 sort_keys=True,
660 indent=4,
661 separators=( ',', ': ' ) ) )
662 # TODO check something here?
663 else:
664 main.log.error( "pendingMap() returned None" )
665 except ( ValueError, TypeError ):
666 main.log.exception( "Error parsing pending map" )
667 main.log.error( repr( pendingMap ) )
668
Jon Hallfeff3082015-05-19 10:23:26 -0700669 intentAddResult = bool( intentAddResult and not missingIntents and
670 installedCheck )
671 if not intentAddResult:
672 main.log.error( "Error in pushing host intents to ONOS" )
673
Jon Hall390696c2015-05-05 17:13:41 -0700674 main.step( "Intent Anti-Entropy dispersion" )
Jon Halla9d26da2015-03-30 16:45:32 -0700675 for i in range(100):
Jon Hall390696c2015-05-05 17:13:41 -0700676 correct = True
Jon Halla9d26da2015-03-30 16:45:32 -0700677 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Hall390696c2015-05-05 17:13:41 -0700678 for cli in CLIs:
679 onosIds = []
680 ids = cli.getAllIntentsId()
681 onosIds.append( ids )
682 main.log.debug( "Intents in " + cli.name + ": " +
683 str( sorted( onosIds ) ) )
684 if sorted( ids ) != sorted( intentIds ):
Jon Hallb6a54872015-06-12 14:02:42 -0700685 main.log.warn( "Set of intent IDs doesn't match" )
Jon Hall390696c2015-05-05 17:13:41 -0700686 correct = False
Jon Hall40d2cbd2015-06-03 16:24:29 -0700687 break
688 else:
689 intents = json.loads( cli.intents() )
690 for intent in intents:
691 if intent[ 'state' ] != "INSTALLED":
Jon Hallc9eabec2015-06-10 14:33:14 -0700692 main.log.warn( "Intent " + intent[ 'id' ] +
693 " is " + intent[ 'state' ] )
Jon Hall40d2cbd2015-06-03 16:24:29 -0700694 correct = False
695 break
Jon Hall390696c2015-05-05 17:13:41 -0700696 if correct:
Jon Halla9d26da2015-03-30 16:45:32 -0700697 break
698 else:
699 time.sleep(1)
Jon Halla9d26da2015-03-30 16:45:32 -0700700 if not intentStop:
701 intentStop = time.time()
Jon Hall390696c2015-05-05 17:13:41 -0700702 global gossipTime
Jon Halla9d26da2015-03-30 16:45:32 -0700703 gossipTime = intentStop - intentStart
704 main.log.info( "It took about " + str( gossipTime ) +
Jon Hall390696c2015-05-05 17:13:41 -0700705 " seconds for all intents to appear in each node" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700706 append = False
707 title = "Gossip Intents"
708 count = 1
709 while append is False:
710 curTitle = title + str( count )
711 if curTitle not in labels:
712 labels.append( curTitle )
713 data.append( str( gossipTime ) )
714 append = True
715 else:
716 count += 1
Jon Halla9d26da2015-03-30 16:45:32 -0700717 # FIXME: make this time configurable/calculate based off of number of
718 # nodes and gossip rounds
719 utilities.assert_greater_equals(
Jon Hall390696c2015-05-05 17:13:41 -0700720 expect=40, actual=gossipTime,
Jon Halla9d26da2015-03-30 16:45:32 -0700721 onpass="ECM anti-entropy for intents worked within " +
722 "expected time",
723 onfail="Intent ECM anti-entropy took too long" )
Jon Hall390696c2015-05-05 17:13:41 -0700724 if gossipTime <= 40:
Jon Hall678f4512015-03-31 09:48:31 -0700725 intentAddResult = True
Jon Hall58c76b72015-02-23 11:09:24 -0800726
Jon Hall63604932015-02-26 17:09:50 -0800727 if not intentAddResult or "key" in pendingMap:
Jon Hall58c76b72015-02-23 11:09:24 -0800728 import time
Jon Hall63604932015-02-26 17:09:50 -0800729 installedCheck = True
Jon Hall58c76b72015-02-23 11:09:24 -0800730 main.log.info( "Sleeping 60 seconds to see if intents are found" )
731 time.sleep( 60 )
732 onosIds = main.ONOScli1.getAllIntentsId()
733 main.log.info( "Submitted intents: " + str( intentIds ) )
734 main.log.info( "Intents in ONOS: " + str( onosIds ) )
735 # Print the intent states
736 intents = main.ONOScli1.intents()
737 intentStates = []
738 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
739 count = 0
Jon Hall5cfd23c2015-03-19 11:40:57 -0700740 try:
741 for intent in json.loads( intents ):
742 # Iter through intents of a node
743 state = intent.get( 'state', None )
744 if "INSTALLED" not in state:
745 installedCheck = False
746 intentId = intent.get( 'id', None )
747 intentStates.append( ( intentId, state ) )
748 except ( ValueError, TypeError ):
749 main.log.exception( "Error parsing intents" )
Jon Hall58c76b72015-02-23 11:09:24 -0800750 # add submitted intents not in the store
751 tmplist = [ i for i, s in intentStates ]
752 for i in intentIds:
753 if i not in tmplist:
754 intentStates.append( ( i, " - " ) )
755 intentStates.sort()
756 for i, s in intentStates:
757 count += 1
758 main.log.info( "%-6s%-15s%-15s" %
759 ( str( count ), str( i ), str( s ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700760 leaders = main.ONOScli1.leaders()
761 try:
Jon Hallc9eabec2015-06-10 14:33:14 -0700762 missing = False
Jon Hall5cfd23c2015-03-19 11:40:57 -0700763 if leaders:
764 parsedLeaders = json.loads( leaders )
765 main.log.warn( json.dumps( parsedLeaders,
766 sort_keys=True,
767 indent=4,
768 separators=( ',', ': ' ) ) )
769 # check for all intent partitions
770 # check for election
771 topics = []
772 for i in range( 14 ):
773 topics.append( "intent-partition-" + str( i ) )
774 # FIXME: this should only be after we start the app
775 topics.append( "org.onosproject.election" )
776 main.log.debug( topics )
777 ONOStopics = [ j['topic'] for j in parsedLeaders ]
778 for topic in topics:
779 if topic not in ONOStopics:
780 main.log.error( "Error: " + topic +
781 " not in leaders" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700782 missing = True
Jon Hall5cfd23c2015-03-19 11:40:57 -0700783 else:
784 main.log.error( "leaders() returned None" )
785 except ( ValueError, TypeError ):
786 main.log.exception( "Error parsing leaders" )
787 main.log.error( repr( leaders ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700788 # Check all nodes
789 if missing:
790 for node in CLIs:
791 response = node.leaders( jsonFormat=False)
792 main.log.warn( str( node.name ) + " leaders output: \n" +
793 str( response ) )
794
Jon Hall5cfd23c2015-03-19 11:40:57 -0700795 partitions = main.ONOScli1.partitions()
796 try:
797 if partitions :
798 parsedPartitions = json.loads( partitions )
799 main.log.warn( json.dumps( parsedPartitions,
800 sort_keys=True,
801 indent=4,
802 separators=( ',', ': ' ) ) )
803 # TODO check for a leader in all paritions
804 # TODO check for consistency among nodes
805 else:
806 main.log.error( "partitions() returned None" )
807 except ( ValueError, TypeError ):
808 main.log.exception( "Error parsing partitions" )
809 main.log.error( repr( partitions ) )
810 pendingMap = main.ONOScli1.pendingMap()
811 try:
812 if pendingMap :
813 parsedPending = json.loads( pendingMap )
814 main.log.warn( json.dumps( parsedPending,
815 sort_keys=True,
816 indent=4,
817 separators=( ',', ': ' ) ) )
818 # TODO check something here?
819 else:
820 main.log.error( "pendingMap() returned None" )
821 except ( ValueError, TypeError ):
822 main.log.exception( "Error parsing pending map" )
823 main.log.error( repr( pendingMap ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800824
Jon Hall6aec96b2015-01-19 14:49:31 -0800825 def CASE4( self, main ):
Jon Hall73cf9cc2014-11-20 22:28:38 -0800826 """
827 Ping across added host intents
828 """
Jon Hall58c76b72015-02-23 11:09:24 -0800829 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -0700830 import time
831 assert numControllers, "numControllers not defined"
832 assert main, "main not defined"
833 assert utilities.assert_equals, "utilities.assert_equals not defined"
834 assert CLIs, "CLIs not defined"
835 assert nodes, "nodes not defined"
Jon Hallfeff3082015-05-19 10:23:26 -0700836 main.case( "Verify connectivity by sendind traffic across Intents" )
837 main.caseExplaination = "Ping across added host intents to check " +\
838 "functionality and check the state of " +\
839 "the intent"
840 main.step( "Ping across added host intents" )
Jon Hall8f89dda2015-01-22 16:03:33 -0800841 PingResult = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -0800842 for i in range( 8, 18 ):
Jon Hall58c76b72015-02-23 11:09:24 -0800843 ping = main.Mininet1.pingHost( src="h" + str( i ),
844 target="h" + str( i + 10 ) )
Jon Hall8f89dda2015-01-22 16:03:33 -0800845 PingResult = PingResult and ping
Jon Hall6aec96b2015-01-19 14:49:31 -0800846 if ping == main.FALSE:
847 main.log.warn( "Ping failed between h" + str( i ) +
848 " and h" + str( i + 10 ) )
849 elif ping == main.TRUE:
850 main.log.info( "Ping test passed!" )
Jon Hall21270ac2015-02-16 17:59:55 -0800851 # Don't set PingResult or you'd override failures
Jon Hall8f89dda2015-01-22 16:03:33 -0800852 if PingResult == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -0700853 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -0800854 "Intents have not been installed correctly, pings failed." )
Jon Hall58c76b72015-02-23 11:09:24 -0800855 # TODO: pretty print
Jon Hall5cfd23c2015-03-19 11:40:57 -0700856 main.log.warn( "ONOS1 intents: " )
857 try:
858 tmpIntents = main.ONOScli1.intents()
859 main.log.warn( json.dumps( json.loads( tmpIntents ),
860 sort_keys=True,
861 indent=4,
862 separators=( ',', ': ' ) ) )
863 except ( ValueError, TypeError ):
864 main.log.warn( repr( tmpIntents ) )
Jon Hall6aec96b2015-01-19 14:49:31 -0800865 utilities.assert_equals(
866 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800867 actual=PingResult,
Jon Hall6aec96b2015-01-19 14:49:31 -0800868 onpass="Intents have been installed correctly and pings work",
869 onfail="Intents have not been installed correctly, pings failed." )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800870
Jon Hallfeff3082015-05-19 10:23:26 -0700871 main.step( "Check Intent state" )
Jon Hall40d2cbd2015-06-03 16:24:29 -0700872 installedCheck = False
Jon Hallc9eabec2015-06-10 14:33:14 -0700873 loopCount = 0
874 while not installedCheck and loopCount < 40:
Jon Hall40d2cbd2015-06-03 16:24:29 -0700875 installedCheck = True
876 # Print the intent states
877 intents = main.ONOScli1.intents()
878 intentStates = []
879 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
Jon Hall40d2cbd2015-06-03 16:24:29 -0700880 # Iter through intents of a node
881 try:
882 for intent in json.loads( intents ):
883 state = intent.get( 'state', None )
884 if "INSTALLED" not in state:
885 installedCheck = False
886 intentId = intent.get( 'id', None )
887 intentStates.append( ( intentId, state ) )
888 except ( ValueError, TypeError ):
889 main.log.exception( "Error parsing intents." )
890 # Print states
891 intentStates.sort()
892 for i, s in intentStates:
893 count += 1
894 main.log.info( "%-6s%-15s%-15s" %
895 ( str( count ), str( i ), str( s ) ) )
896 if not installedCheck:
897 time.sleep( 1 )
Jon Hallc9eabec2015-06-10 14:33:14 -0700898 loopCount += 1
Jon Hallfeff3082015-05-19 10:23:26 -0700899 utilities.assert_equals( expect=True, actual=installedCheck,
900 onpass="Intents are all INSTALLED",
Jon Hall40d2cbd2015-06-03 16:24:29 -0700901 onfail="Intents are not all in " +
Jon Hallfeff3082015-05-19 10:23:26 -0700902 "INSTALLED state" )
903
904 main.step( "Check leadership of topics" )
905 leaders = main.ONOScli1.leaders()
906 topicCheck = main.TRUE
907 try:
908 if leaders:
909 parsedLeaders = json.loads( leaders )
910 main.log.warn( json.dumps( parsedLeaders,
911 sort_keys=True,
912 indent=4,
913 separators=( ',', ': ' ) ) )
914 # check for all intent partitions
915 # check for election
916 # TODO: Look at Devices as topics now that it uses this system
917 topics = []
918 for i in range( 14 ):
919 topics.append( "intent-partition-" + str( i ) )
920 # FIXME: this should only be after we start the app
921 # FIXME: topics.append( "org.onosproject.election" )
922 # Print leaders output
923 main.log.debug( topics )
924 ONOStopics = [ j['topic'] for j in parsedLeaders ]
925 for topic in topics:
926 if topic not in ONOStopics:
927 main.log.error( "Error: " + topic +
928 " not in leaders" )
929 topicCheck = main.FALSE
930 else:
931 main.log.error( "leaders() returned None" )
932 topicCheck = main.FALSE
933 except ( ValueError, TypeError ):
934 topicCheck = main.FALSE
935 main.log.exception( "Error parsing leaders" )
936 main.log.error( repr( leaders ) )
937 # TODO: Check for a leader of these topics
Jon Hallc9eabec2015-06-10 14:33:14 -0700938 # Check all nodes
939 if topicCheck:
940 for node in CLIs:
941 response = node.leaders( jsonFormat=False)
942 main.log.warn( str( node.name ) + " leaders output: \n" +
943 str( response ) )
944
Jon Hallfeff3082015-05-19 10:23:26 -0700945 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
946 onpass="intent Partitions is in leaders",
947 onfail="Some topics were lost " )
948 # Print partitions
949 partitions = main.ONOScli1.partitions()
950 try:
951 if partitions :
952 parsedPartitions = json.loads( partitions )
953 main.log.warn( json.dumps( parsedPartitions,
954 sort_keys=True,
955 indent=4,
956 separators=( ',', ': ' ) ) )
957 # TODO check for a leader in all paritions
958 # TODO check for consistency among nodes
959 else:
960 main.log.error( "partitions() returned None" )
961 except ( ValueError, TypeError ):
962 main.log.exception( "Error parsing partitions" )
963 main.log.error( repr( partitions ) )
964 # Print Pending Map
965 pendingMap = main.ONOScli1.pendingMap()
966 try:
967 if pendingMap :
968 parsedPending = json.loads( pendingMap )
969 main.log.warn( json.dumps( parsedPending,
970 sort_keys=True,
971 indent=4,
972 separators=( ',', ': ' ) ) )
973 # TODO check something here?
974 else:
975 main.log.error( "pendingMap() returned None" )
976 except ( ValueError, TypeError ):
977 main.log.exception( "Error parsing pending map" )
978 main.log.error( repr( pendingMap ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700979
Jon Hall63604932015-02-26 17:09:50 -0800980 if not installedCheck:
Jon Hallc9eabec2015-06-10 14:33:14 -0700981 main.log.info( "Waiting 60 seconds to see if the state of " +
982 "intents change" )
983 time.sleep( 60 )
Jon Hall63604932015-02-26 17:09:50 -0800984 # Print the intent states
985 intents = main.ONOScli1.intents()
986 intentStates = []
987 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
988 count = 0
989 # Iter through intents of a node
Jon Hall5cfd23c2015-03-19 11:40:57 -0700990 try:
991 for intent in json.loads( intents ):
992 state = intent.get( 'state', None )
993 if "INSTALLED" not in state:
994 installedCheck = False
995 intentId = intent.get( 'id', None )
996 intentStates.append( ( intentId, state ) )
997 except ( ValueError, TypeError ):
998 main.log.exception( "Error parsing intents." )
Jon Hall63604932015-02-26 17:09:50 -0800999 intentStates.sort()
1000 for i, s in intentStates:
1001 count += 1
1002 main.log.info( "%-6s%-15s%-15s" %
1003 ( str( count ), str( i ), str( s ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001004 leaders = main.ONOScli1.leaders()
1005 try:
Jon Hallc9eabec2015-06-10 14:33:14 -07001006 missing = False
Jon Hall5cfd23c2015-03-19 11:40:57 -07001007 if leaders:
1008 parsedLeaders = json.loads( leaders )
1009 main.log.warn( json.dumps( parsedLeaders,
1010 sort_keys=True,
1011 indent=4,
1012 separators=( ',', ': ' ) ) )
1013 # check for all intent partitions
1014 # check for election
1015 topics = []
1016 for i in range( 14 ):
1017 topics.append( "intent-partition-" + str( i ) )
1018 # FIXME: this should only be after we start the app
1019 topics.append( "org.onosproject.election" )
1020 main.log.debug( topics )
1021 ONOStopics = [ j['topic'] for j in parsedLeaders ]
1022 for topic in topics:
1023 if topic not in ONOStopics:
1024 main.log.error( "Error: " + topic +
1025 " not in leaders" )
Jon Hallc9eabec2015-06-10 14:33:14 -07001026 missing = True
Jon Hall5cfd23c2015-03-19 11:40:57 -07001027 else:
1028 main.log.error( "leaders() returned None" )
1029 except ( ValueError, TypeError ):
1030 main.log.exception( "Error parsing leaders" )
1031 main.log.error( repr( leaders ) )
Jon Hallc9eabec2015-06-10 14:33:14 -07001032 if missing:
1033 for node in CLIs:
1034 response = node.leaders( jsonFormat=False)
1035 main.log.warn( str( node.name ) + " leaders output: \n" +
1036 str( response ) )
1037
Jon Hall5cfd23c2015-03-19 11:40:57 -07001038 partitions = main.ONOScli1.partitions()
1039 try:
1040 if partitions :
1041 parsedPartitions = json.loads( partitions )
1042 main.log.warn( json.dumps( parsedPartitions,
1043 sort_keys=True,
1044 indent=4,
1045 separators=( ',', ': ' ) ) )
1046 # TODO check for a leader in all paritions
1047 # TODO check for consistency among nodes
1048 else:
1049 main.log.error( "partitions() returned None" )
1050 except ( ValueError, TypeError ):
1051 main.log.exception( "Error parsing partitions" )
1052 main.log.error( repr( partitions ) )
1053 pendingMap = main.ONOScli1.pendingMap()
1054 try:
1055 if pendingMap :
1056 parsedPending = json.loads( pendingMap )
1057 main.log.warn( json.dumps( parsedPending,
1058 sort_keys=True,
1059 indent=4,
1060 separators=( ',', ': ' ) ) )
1061 # TODO check something here?
1062 else:
1063 main.log.error( "pendingMap() returned None" )
1064 except ( ValueError, TypeError ):
1065 main.log.exception( "Error parsing pending map" )
1066 main.log.error( repr( pendingMap ) )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001067 # Print flowrules
1068 main.log.debug( CLIs[0].flows( jsonFormat=False ) )
Jon Hallfeff3082015-05-19 10:23:26 -07001069 main.step( "Wait a minute then ping again" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001070 # the wait is above
Jon Hallfeff3082015-05-19 10:23:26 -07001071 PingResult = main.TRUE
1072 for i in range( 8, 18 ):
1073 ping = main.Mininet1.pingHost( src="h" + str( i ),
1074 target="h" + str( i + 10 ) )
1075 PingResult = PingResult and ping
1076 if ping == main.FALSE:
1077 main.log.warn( "Ping failed between h" + str( i ) +
1078 " and h" + str( i + 10 ) )
1079 elif ping == main.TRUE:
1080 main.log.info( "Ping test passed!" )
1081 # Don't set PingResult or you'd override failures
1082 if PingResult == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001083 main.log.error(
Jon Hallfeff3082015-05-19 10:23:26 -07001084 "Intents have not been installed correctly, pings failed." )
1085 # TODO: pretty print
1086 main.log.warn( "ONOS1 intents: " )
1087 try:
1088 tmpIntents = main.ONOScli1.intents()
1089 main.log.warn( json.dumps( json.loads( tmpIntents ),
1090 sort_keys=True,
1091 indent=4,
1092 separators=( ',', ': ' ) ) )
1093 except ( ValueError, TypeError ):
1094 main.log.warn( repr( tmpIntents ) )
1095 utilities.assert_equals(
1096 expect=main.TRUE,
1097 actual=PingResult,
1098 onpass="Intents have been installed correctly and pings work",
1099 onfail="Intents have not been installed correctly, pings failed." )
1100
Jon Hall6aec96b2015-01-19 14:49:31 -08001101 def CASE5( self, main ):
1102 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001103 Reading state of ONOS
Jon Hall6aec96b2015-01-19 14:49:31 -08001104 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001105 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -07001106 import time
1107 assert numControllers, "numControllers not defined"
1108 assert main, "main not defined"
1109 assert utilities.assert_equals, "utilities.assert_equals not defined"
1110 assert CLIs, "CLIs not defined"
1111 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08001112 # assumes that sts is already in you PYTHONPATH
1113 from sts.topology.teston_topology import TestONTopology
Jon Hall73cf9cc2014-11-20 22:28:38 -08001114
Jon Hall6aec96b2015-01-19 14:49:31 -08001115 main.case( "Setting up and gathering data for current state" )
1116 # The general idea for this test case is to pull the state of
1117 # ( intents,flows, topology,... ) from each ONOS node
Jon Hall5cfd23c2015-03-19 11:40:57 -07001118 # We can then compare them with each other and also with past states
Jon Hall73cf9cc2014-11-20 22:28:38 -08001119
Jon Hall5cfd23c2015-03-19 11:40:57 -07001120 main.step( "Check that each switch has a master" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001121 global mastershipState
Jon Hall5cfd23c2015-03-19 11:40:57 -07001122 mastershipState = '[]'
Jon Hall94fd0472014-12-08 11:52:42 -08001123
Jon Hall6aec96b2015-01-19 14:49:31 -08001124 # Assert that each device has a master
Jon Hall5cfd23c2015-03-19 11:40:57 -07001125 rolesNotNull = main.TRUE
1126 threads = []
1127 for i in range( numControllers ):
1128 t = main.Thread( target=CLIs[i].rolesNotNull,
1129 name="rolesNotNull-" + str( i ),
1130 args=[] )
1131 threads.append( t )
1132 t.start()
1133
1134 for t in threads:
1135 t.join()
1136 rolesNotNull = rolesNotNull and t.result
Jon Hall6aec96b2015-01-19 14:49:31 -08001137 utilities.assert_equals(
1138 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001139 actual=rolesNotNull,
Jon Hall6aec96b2015-01-19 14:49:31 -08001140 onpass="Each device has a master",
1141 onfail="Some devices don't have a master assigned" )
Jon Hall94fd0472014-12-08 11:52:42 -08001142
Jon Hall5cfd23c2015-03-19 11:40:57 -07001143 main.step( "Get the Mastership of each switch from each controller" )
1144 ONOSMastership = []
1145 mastershipCheck = main.FALSE
1146 consistentMastership = True
1147 rolesResults = True
1148 threads = []
1149 for i in range( numControllers ):
1150 t = main.Thread( target=CLIs[i].roles,
1151 name="roles-" + str( i ),
1152 args=[] )
1153 threads.append( t )
1154 t.start()
1155
1156 for t in threads:
1157 t.join()
1158 ONOSMastership.append( t.result )
1159
1160 for i in range( numControllers ):
1161 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001162 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001163 " roles" )
1164 main.log.warn(
1165 "ONOS" + str( i + 1 ) + " mastership response: " +
1166 repr( ONOSMastership[i] ) )
1167 rolesResults = False
1168 utilities.assert_equals(
1169 expect=True,
1170 actual=rolesResults,
1171 onpass="No error in reading roles output",
1172 onfail="Error in reading roles from ONOS" )
1173
1174 main.step( "Check for consistency in roles from each controller" )
1175 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001176 main.log.info(
Jon Hall6aec96b2015-01-19 14:49:31 -08001177 "Switch roles are consistent across all ONOS nodes" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001178 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001179 consistentMastership = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001180 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001181 expect=True,
Jon Hall8f89dda2015-01-22 16:03:33 -08001182 actual=consistentMastership,
Jon Hall6aec96b2015-01-19 14:49:31 -08001183 onpass="Switch roles are consistent across all ONOS nodes",
1184 onfail="ONOS nodes have different views of switch roles" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001185
Jon Hall5cfd23c2015-03-19 11:40:57 -07001186 if rolesResults and not consistentMastership:
1187 for i in range( numControllers ):
1188 try:
1189 main.log.warn(
1190 "ONOS" + str( i + 1 ) + " roles: ",
1191 json.dumps(
1192 json.loads( ONOSMastership[ i ] ),
1193 sort_keys=True,
1194 indent=4,
1195 separators=( ',', ': ' ) ) )
1196 except ( ValueError, TypeError ):
1197 main.log.warn( repr( ONOSMastership[ i ] ) )
1198 elif rolesResults and consistentMastership:
1199 mastershipCheck = main.TRUE
1200 mastershipState = ONOSMastership[ 0 ]
1201
Jon Hall6aec96b2015-01-19 14:49:31 -08001202 main.step( "Get the intents from each controller" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001203 global intentState
1204 intentState = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001205 ONOSIntents = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001206 intentCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001207 consistentIntents = True
1208 intentsResults = True
1209 threads = []
1210 for i in range( numControllers ):
1211 t = main.Thread( target=CLIs[i].intents,
1212 name="intents-" + str( i ),
1213 args=[],
1214 kwargs={ 'jsonFormat': True } )
1215 threads.append( t )
1216 t.start()
1217
1218 for t in threads:
1219 t.join()
1220 ONOSIntents.append( t.result )
1221
1222 for i in range( numControllers ):
1223 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001224 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001225 " intents" )
1226 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1227 repr( ONOSIntents[ i ] ) )
1228 intentsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001229 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001230 expect=True,
1231 actual=intentsResults,
1232 onpass="No error in reading intents output",
1233 onfail="Error in reading intents from ONOS" )
1234
1235 main.step( "Check for consistency in Intents from each controller" )
1236 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001237 main.log.info( "Intents are consistent across all ONOS " +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001238 "nodes" )
1239 else:
1240 consistentIntents = False
Jon Hall40d2cbd2015-06-03 16:24:29 -07001241 main.log.error( "Intents not consistent" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001242 utilities.assert_equals(
1243 expect=True,
1244 actual=consistentIntents,
Jon Hall6aec96b2015-01-19 14:49:31 -08001245 onpass="Intents are consistent across all ONOS nodes",
1246 onfail="ONOS nodes have different views of intents" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001247
Jon Hall390696c2015-05-05 17:13:41 -07001248 if intentsResults:
1249 # Try to make it easy to figure out what is happening
1250 #
1251 # Intent ONOS1 ONOS2 ...
1252 # 0x01 INSTALLED INSTALLING
1253 # ... ... ...
1254 # ... ... ...
1255 title = " Id"
1256 for n in range( numControllers ):
1257 title += " " * 10 + "ONOS" + str( n + 1 )
1258 main.log.warn( title )
1259 # get all intent keys in the cluster
1260 keys = []
1261 for nodeStr in ONOSIntents:
1262 node = json.loads( nodeStr )
1263 for intent in node:
1264 keys.append( intent.get( 'id' ) )
1265 keys = set( keys )
1266 for key in keys:
1267 row = "%-13s" % key
1268 for nodeStr in ONOSIntents:
1269 node = json.loads( nodeStr )
1270 for intent in node:
1271 if intent.get( 'id', "Error" ) == key:
1272 row += "%-15s" % intent.get( 'state' )
1273 main.log.warn( row )
1274 # End table view
1275
Jon Hall5cfd23c2015-03-19 11:40:57 -07001276 if intentsResults and not consistentIntents:
Jon Hall390696c2015-05-05 17:13:41 -07001277 # print the json objects
Jon Hall5cfd23c2015-03-19 11:40:57 -07001278 n = len(ONOSIntents)
Jon Hall390696c2015-05-05 17:13:41 -07001279 main.log.debug( "ONOS" + str( n ) + " intents: " )
1280 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1281 sort_keys=True,
1282 indent=4,
1283 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001284 for i in range( numControllers ):
1285 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hall390696c2015-05-05 17:13:41 -07001286 main.log.debug( "ONOS" + str( i + 1 ) + " intents: " )
1287 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1288 sort_keys=True,
1289 indent=4,
1290 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001291 else:
Jon Hall390696c2015-05-05 17:13:41 -07001292 main.log.debug( nodes[ i ].name + " intents match ONOS" +
1293 str( n ) + " intents" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001294 elif intentsResults and consistentIntents:
1295 intentCheck = main.TRUE
1296 intentState = ONOSIntents[ 0 ]
1297
Jon Hall6aec96b2015-01-19 14:49:31 -08001298 main.step( "Get the flows from each controller" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001299 global flowState
1300 flowState = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001301 ONOSFlows = []
1302 ONOSFlowsJson = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001303 flowCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001304 consistentFlows = True
1305 flowsResults = True
1306 threads = []
1307 for i in range( numControllers ):
1308 t = main.Thread( target=CLIs[i].flows,
1309 name="flows-" + str( i ),
1310 args=[],
1311 kwargs={ 'jsonFormat': True } )
1312 threads.append( t )
1313 t.start()
1314
Jon Halla9d26da2015-03-30 16:45:32 -07001315 # NOTE: Flows command can take some time to run
Jon Hall5cfd23c2015-03-19 11:40:57 -07001316 time.sleep(30)
1317 for t in threads:
1318 t.join()
1319 result = t.result
1320 ONOSFlows.append( result )
1321
1322 for i in range( numControllers ):
1323 num = str( i + 1 )
1324 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001325 main.log.error( "Error in getting ONOS" + num + " flows" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001326 main.log.warn( "ONOS" + num + " flows response: " +
1327 repr( ONOSFlows[ i ] ) )
1328 flowsResults = False
1329 ONOSFlowsJson.append( None )
Jon Hall58c76b72015-02-23 11:09:24 -08001330 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001331 try:
1332 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1333 except ( ValueError, TypeError ):
1334 # FIXME: change this to log.error?
1335 main.log.exception( "Error in parsing ONOS" + num +
1336 " response as json." )
1337 main.log.error( repr( ONOSFlows[ i ] ) )
1338 ONOSFlowsJson.append( None )
1339 flowsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001340 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001341 expect=True,
1342 actual=flowsResults,
1343 onpass="No error in reading flows output",
1344 onfail="Error in reading flows from ONOS" )
1345
1346 main.step( "Check for consistency in Flows from each controller" )
1347 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1348 if all( tmp ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001349 main.log.info( "Flow count is consistent across all ONOS nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001350 else:
1351 consistentFlows = False
1352 utilities.assert_equals(
1353 expect=True,
1354 actual=consistentFlows,
Jon Hall6aec96b2015-01-19 14:49:31 -08001355 onpass="The flow count is consistent across all ONOS nodes",
1356 onfail="ONOS nodes have different flow counts" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001357
Jon Hall5cfd23c2015-03-19 11:40:57 -07001358 if flowsResults and not consistentFlows:
1359 for i in range( numControllers ):
1360 try:
1361 main.log.warn(
1362 "ONOS" + str( i + 1 ) + " flows: " +
1363 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1364 indent=4, separators=( ',', ': ' ) ) )
1365 except ( ValueError, TypeError ):
1366 main.log.warn(
1367 "ONOS" + str( i + 1 ) + " flows: " +
1368 repr( ONOSFlows[ i ] ) )
1369 elif flowsResults and consistentFlows:
1370 flowCheck = main.TRUE
1371 flowState = ONOSFlows[ 0 ]
1372
Jon Hall6aec96b2015-01-19 14:49:31 -08001373 main.step( "Get the OF Table entries" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001374 global flows
Jon Hall6aec96b2015-01-19 14:49:31 -08001375 flows = []
1376 for i in range( 1, 29 ):
Jon Hall8f89dda2015-01-22 16:03:33 -08001377 flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001378 if flowCheck == main.FALSE:
1379 for table in flows:
1380 main.log.warn( table )
Jon Hall6aec96b2015-01-19 14:49:31 -08001381 # TODO: Compare switch flow tables with ONOS flow tables
Jon Hall73cf9cc2014-11-20 22:28:38 -08001382
Jon Hall6aec96b2015-01-19 14:49:31 -08001383 main.step( "Start continuous pings" )
1384 main.Mininet2.pingLong(
1385 src=main.params[ 'PING' ][ 'source1' ],
1386 target=main.params[ 'PING' ][ 'target1' ],
1387 pingTime=500 )
1388 main.Mininet2.pingLong(
1389 src=main.params[ 'PING' ][ 'source2' ],
1390 target=main.params[ 'PING' ][ 'target2' ],
1391 pingTime=500 )
1392 main.Mininet2.pingLong(
1393 src=main.params[ 'PING' ][ 'source3' ],
1394 target=main.params[ 'PING' ][ 'target3' ],
1395 pingTime=500 )
1396 main.Mininet2.pingLong(
1397 src=main.params[ 'PING' ][ 'source4' ],
1398 target=main.params[ 'PING' ][ 'target4' ],
1399 pingTime=500 )
1400 main.Mininet2.pingLong(
1401 src=main.params[ 'PING' ][ 'source5' ],
1402 target=main.params[ 'PING' ][ 'target5' ],
1403 pingTime=500 )
1404 main.Mininet2.pingLong(
1405 src=main.params[ 'PING' ][ 'source6' ],
1406 target=main.params[ 'PING' ][ 'target6' ],
1407 pingTime=500 )
1408 main.Mininet2.pingLong(
1409 src=main.params[ 'PING' ][ 'source7' ],
1410 target=main.params[ 'PING' ][ 'target7' ],
1411 pingTime=500 )
1412 main.Mininet2.pingLong(
1413 src=main.params[ 'PING' ][ 'source8' ],
1414 target=main.params[ 'PING' ][ 'target8' ],
1415 pingTime=500 )
1416 main.Mininet2.pingLong(
1417 src=main.params[ 'PING' ][ 'source9' ],
1418 target=main.params[ 'PING' ][ 'target9' ],
1419 pingTime=500 )
1420 main.Mininet2.pingLong(
1421 src=main.params[ 'PING' ][ 'source10' ],
1422 target=main.params[ 'PING' ][ 'target10' ],
1423 pingTime=500 )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001424
Jon Hall6aec96b2015-01-19 14:49:31 -08001425 main.step( "Collecting topology information from ONOS" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001426 devices = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001427 threads = []
1428 for i in range( numControllers ):
1429 t = main.Thread( target=CLIs[i].devices,
1430 name="devices-" + str( i ),
1431 args=[ ] )
1432 threads.append( t )
1433 t.start()
1434
1435 for t in threads:
1436 t.join()
1437 devices.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001438 hosts = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001439 threads = []
1440 for i in range( numControllers ):
1441 t = main.Thread( target=CLIs[i].hosts,
1442 name="hosts-" + str( i ),
1443 args=[ ] )
1444 threads.append( t )
1445 t.start()
1446
1447 for t in threads:
1448 t.join()
1449 try:
1450 hosts.append( json.loads( t.result ) )
1451 except ( ValueError, TypeError ):
1452 # FIXME: better handling of this, print which node
1453 # Maybe use thread name?
1454 main.log.exception( "Error parsing json output of hosts" )
1455 # FIXME: should this be an empty json object instead?
1456 hosts.append( None )
1457
Jon Hall73cf9cc2014-11-20 22:28:38 -08001458 ports = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001459 threads = []
1460 for i in range( numControllers ):
1461 t = main.Thread( target=CLIs[i].ports,
1462 name="ports-" + str( i ),
1463 args=[ ] )
1464 threads.append( t )
1465 t.start()
1466
1467 for t in threads:
1468 t.join()
1469 ports.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001470 links = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001471 threads = []
1472 for i in range( numControllers ):
1473 t = main.Thread( target=CLIs[i].links,
1474 name="links-" + str( i ),
1475 args=[ ] )
1476 threads.append( t )
1477 t.start()
1478
1479 for t in threads:
1480 t.join()
1481 links.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08001482 clusters = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001483 threads = []
1484 for i in range( numControllers ):
1485 t = main.Thread( target=CLIs[i].clusters,
1486 name="clusters-" + str( i ),
1487 args=[ ] )
1488 threads.append( t )
1489 t.start()
1490
1491 for t in threads:
1492 t.join()
1493 clusters.append( t.result )
Jon Hall529a37f2015-01-28 10:02:00 -08001494 # Compare json objects for hosts and dataplane clusters
Jon Hall94fd0472014-12-08 11:52:42 -08001495
Jon Hall6aec96b2015-01-19 14:49:31 -08001496 # hosts
Jon Hall390696c2015-05-05 17:13:41 -07001497 main.step( "Host view is consistent across ONOS nodes" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001498 consistentHostsResult = main.TRUE
Jon Hall94fd0472014-12-08 11:52:42 -08001499 for controller in range( len( hosts ) ):
Jon Hall8f89dda2015-01-22 16:03:33 -08001500 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08001501 if "Error" not in hosts[ controller ]:
1502 if hosts[ controller ] == hosts[ 0 ]:
Jon Hall94fd0472014-12-08 11:52:42 -08001503 continue
Jon Hall6aec96b2015-01-19 14:49:31 -08001504 else: # hosts not consistent
Jon Hall40d2cbd2015-06-03 16:24:29 -07001505 main.log.error( "hosts from ONOS" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001506 controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001507 " is inconsistent with ONOS1" )
1508 main.log.warn( repr( hosts[ controller ] ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001509 consistentHostsResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08001510
1511 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001512 main.log.error( "Error in getting ONOS hosts from ONOS" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001513 controllerStr )
1514 consistentHostsResult = main.FALSE
1515 main.log.warn( "ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001516 " hosts response: " +
1517 repr( hosts[ controller ] ) )
1518 utilities.assert_equals(
1519 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001520 actual=consistentHostsResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08001521 onpass="Hosts view is consistent across all ONOS nodes",
1522 onfail="ONOS nodes have different views of hosts" )
Jon Hall94fd0472014-12-08 11:52:42 -08001523
Jon Hall390696c2015-05-05 17:13:41 -07001524 main.step( "Each host has an IP address" )
Jon Hall58c76b72015-02-23 11:09:24 -08001525 ipResult = main.TRUE
1526 for controller in range( 0, len( hosts ) ):
1527 controllerStr = str( controller + 1 )
1528 for host in hosts[ controller ]:
Jon Hallfeff3082015-05-19 10:23:26 -07001529 if not host.get( 'ipAddresses', [ ] ):
Jon Hall5cfd23c2015-03-19 11:40:57 -07001530 main.log.error( "DEBUG:Error with host ips on controller" +
1531 controllerStr + ": " + str( host ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001532 ipResult = main.FALSE
1533 utilities.assert_equals(
1534 expect=main.TRUE,
1535 actual=ipResult,
1536 onpass="The ips of the hosts aren't empty",
1537 onfail="The ip of at least one host is missing" )
1538
Jon Hall6aec96b2015-01-19 14:49:31 -08001539 # Strongly connected clusters of devices
Jon Hall390696c2015-05-05 17:13:41 -07001540 main.step( "Cluster view is consistent across ONOS nodes" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001541 consistentClustersResult = main.TRUE
Jon Hall94fd0472014-12-08 11:52:42 -08001542 for controller in range( len( clusters ) ):
Jon Hall5cfd23c2015-03-19 11:40:57 -07001543 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08001544 if "Error" not in clusters[ controller ]:
1545 if clusters[ controller ] == clusters[ 0 ]:
Jon Hall94fd0472014-12-08 11:52:42 -08001546 continue
Jon Hall6aec96b2015-01-19 14:49:31 -08001547 else: # clusters not consistent
Jon Hall40d2cbd2015-06-03 16:24:29 -07001548 main.log.error( "clusters from ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001549 " is inconsistent with ONOS1" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001550 consistentClustersResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08001551
1552 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001553 main.log.error( "Error in getting dataplane clusters " +
Jon Hall8f89dda2015-01-22 16:03:33 -08001554 "from ONOS" + controllerStr )
1555 consistentClustersResult = main.FALSE
1556 main.log.warn( "ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001557 " clusters response: " +
1558 repr( clusters[ controller ] ) )
1559 utilities.assert_equals(
1560 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001561 actual=consistentClustersResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08001562 onpass="Clusters view is consistent across all ONOS nodes",
1563 onfail="ONOS nodes have different views of clusters" )
1564 # there should always only be one cluster
Jon Hall390696c2015-05-05 17:13:41 -07001565 main.step( "Cluster view correct across ONOS nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001566 try:
1567 numClusters = len( json.loads( clusters[ 0 ] ) )
1568 except ( ValueError, TypeError ):
1569 main.log.exception( "Error parsing clusters[0]: " +
1570 repr( clusters[ 0 ] ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001571 clusterResults = main.FALSE
1572 if numClusters == 1:
1573 clusterResults = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08001574 utilities.assert_equals(
1575 expect=1,
Jon Hall8f89dda2015-01-22 16:03:33 -08001576 actual=numClusters,
Jon Hall6aec96b2015-01-19 14:49:31 -08001577 onpass="ONOS shows 1 SCC",
Jon Hall58c76b72015-02-23 11:09:24 -08001578 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
Jon Hall94fd0472014-12-08 11:52:42 -08001579
Jon Hall6aec96b2015-01-19 14:49:31 -08001580 main.step( "Comparing ONOS topology to MN" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001581 devicesResults = main.TRUE
Jon Hall8f89dda2015-01-22 16:03:33 -08001582 linksResults = main.TRUE
Jon Hallb6a54872015-06-12 14:02:42 -07001583 hostsResults = main.TRUE
1584 mnSwitches = main.Mininet1.getSwitches()
1585 mnLinks = main.Mininet1.getLinks()
1586 mnHosts = main.Mininet1.getHosts()
Jon Hall8f89dda2015-01-22 16:03:33 -08001587 for controller in range( numControllers ):
1588 controllerStr = str( controller + 1 )
Jon Hallb6a54872015-06-12 14:02:42 -07001589 if devices[ controller ] and ports[ controller ] and\
1590 "Error" not in devices[ controller ] and\
1591 "Error" not in ports[ controller ]:
1592
Jon Hall8f89dda2015-01-22 16:03:33 -08001593 currentDevicesResult = main.Mininet1.compareSwitches(
Jon Hallb6a54872015-06-12 14:02:42 -07001594 mnSwitches,
1595 json.loads( devices[ controller ] ),
1596 json.loads( ports[ controller ] ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001597 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08001598 currentDevicesResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001599 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08001600 actual=currentDevicesResult,
1601 onpass="ONOS" + controllerStr +
1602 " Switches view is correct",
1603 onfail="ONOS" + controllerStr +
1604 " Switches view is incorrect" )
Jon Hallb6a54872015-06-12 14:02:42 -07001605 if links[ controller ] and "Error" not in links[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08001606 currentLinksResult = main.Mininet1.compareLinks(
Jon Hallb6a54872015-06-12 14:02:42 -07001607 mnSwitches, mnLinks,
1608 json.loads( links[ controller ] ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001609 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08001610 currentLinksResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001611 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08001612 actual=currentLinksResult,
1613 onpass="ONOS" + controllerStr +
1614 " links view is correct",
1615 onfail="ONOS" + controllerStr +
1616 " links view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001617
Jon Hallb6a54872015-06-12 14:02:42 -07001618 if hosts[ controller ] or "Error" not in hosts[ controller ]:
1619 currentHostsResult = main.Mininet1.compareHosts(
1620 mnHosts,
1621 hosts[ controller ] )
1622 else:
1623 currentHostsResult = main.FALSE
1624 utilities.assert_equals( expect=main.TRUE,
1625 actual=currentHostsResult,
1626 onpass="ONOS" + controllerStr +
1627 " hosts exist in Mininet",
1628 onfail="ONOS" + controllerStr +
1629 " hosts don't match Mininet" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001630
Jon Hallb6a54872015-06-12 14:02:42 -07001631 devicesResults = devicesResults and currentDevicesResult
1632 linksResults = linksResults and currentLinksResult
1633 hostsResults = hostsResults and currentHostsResult
1634
1635 main.step( "Device information is correct" )
1636 utilities.assert_equals(
1637 expect=main.TRUE,
1638 actual=devicesResults,
1639 onpass="Device information is correct",
1640 onfail="Device information is incorrect" )
1641
1642 main.step( "Links are correct" )
1643 utilities.assert_equals(
1644 expect=main.TRUE,
1645 actual=linksResults,
1646 onpass="Link are correct",
1647 onfail="Links are incorrect" )
1648
1649 main.step( "Hosts are correct" )
1650 utilities.assert_equals(
1651 expect=main.TRUE,
1652 actual=hostsResults,
1653 onpass="Hosts are correct",
1654 onfail="Hosts are incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001655
Jon Hall6aec96b2015-01-19 14:49:31 -08001656 def CASE6( self, main ):
1657 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001658 The Failure case.
Jon Hall6aec96b2015-01-19 14:49:31 -08001659 """
Jon Hallfeff3082015-05-19 10:23:26 -07001660 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07001661 assert numControllers, "numControllers not defined"
1662 assert main, "main not defined"
1663 assert utilities.assert_equals, "utilities.assert_equals not defined"
1664 assert CLIs, "CLIs not defined"
1665 assert nodes, "nodes not defined"
Jon Hallc9eabec2015-06-10 14:33:14 -07001666 try:
1667 labels
1668 except NameError:
1669 main.log.error( "labels not defined, setting to []" )
1670 global labels
1671 labels = []
1672 try:
1673 data
1674 except NameError:
1675 main.log.error( "data not defined, setting to []" )
1676 global data
1677 data = []
Jon Hall390696c2015-05-05 17:13:41 -07001678 # Reset non-persistent variables
1679 try:
1680 iCounterValue = 0
1681 except NameError:
1682 main.log.error( "iCounterValue not defined, setting to 0" )
1683 iCounterValue = 0
1684
Jon Hall5cfd23c2015-03-19 11:40:57 -07001685 main.case( "Restart entire ONOS cluster" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001686
Jon Hall5cfd23c2015-03-19 11:40:57 -07001687 main.step( "Killing ONOS nodes" )
1688 killResults = main.TRUE
Jon Hallfeff3082015-05-19 10:23:26 -07001689 killTime = time.time()
Jon Hall5cfd23c2015-03-19 11:40:57 -07001690 for node in nodes:
1691 killed = main.ONOSbench.onosKill( node.ip_address )
1692 killResults = killResults and killed
Jon Hall390696c2015-05-05 17:13:41 -07001693 utilities.assert_equals( expect=main.TRUE, actual=killResults,
1694 onpass="ONOS nodes killed",
1695 onfail="ONOS kill unsuccessful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001696
Jon Hall6aec96b2015-01-19 14:49:31 -08001697 main.step( "Checking if ONOS is up yet" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001698 for i in range( 2 ):
1699 onosIsupResult = main.TRUE
1700 for node in nodes:
1701 started = main.ONOSbench.isup( node.ip_address )
1702 if not started:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001703 main.log.error( node.name + " didn't start!" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001704 onosIsupResult = onosIsupResult and started
1705 if onosIsupResult == main.TRUE:
1706 break
Jon Hall390696c2015-05-05 17:13:41 -07001707 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1708 onpass="ONOS restarted",
1709 onfail="ONOS restart NOT successful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001710
Jon Hall5cfd23c2015-03-19 11:40:57 -07001711 main.log.step( "Starting ONOS CLI sessions" )
1712 cliResults = main.TRUE
1713 threads = []
1714 for i in range( numControllers ):
1715 t = main.Thread( target=CLIs[i].startOnosCli,
1716 name="startOnosCli-" + str( i ),
1717 args=[nodes[i].ip_address] )
1718 threads.append( t )
1719 t.start()
1720
1721 for t in threads:
1722 t.join()
1723 cliResults = cliResults and t.result
Jon Hall390696c2015-05-05 17:13:41 -07001724 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1725 onpass="ONOS cli started",
1726 onfail="ONOS clis did not restart" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001727
Jon Hallfeff3082015-05-19 10:23:26 -07001728 # Grab the time of restart so we chan check how long the gossip
1729 # protocol has had time to work
1730 main.restartTime = time.time() - killTime
1731 main.log.debug( "Restart time: " + str( main.restartTime ) )
Jon Hallc9eabec2015-06-10 14:33:14 -07001732 labels.append( "Restart" )
1733 data.append( str( main.restartTime ) )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001734
Jon Hallfeff3082015-05-19 10:23:26 -07001735 # FIXME: revisit test plan for election with madan
1736 # Rerun for election on restarted nodes
Jon Hall40d2cbd2015-06-03 16:24:29 -07001737 runResults = main.TRUE
1738 for cli in CLIs:
1739 run = CLIs[0].electionTestRun()
1740 if run != main.TRUE:
1741 main.log.error( "Error running for election on " + cli.name )
1742 runResults = runResults and run
Jon Hallfeff3082015-05-19 10:23:26 -07001743 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1744 onpass="Reran for election",
1745 onfail="Failed to rerun for election" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001746
1747 # TODO: Make this configurable
Jon Hallfeff3082015-05-19 10:23:26 -07001748 time.sleep( 60 )
1749 main.log.debug( CLIs[0].nodes( jsonFormat=False ) )
1750 main.log.debug( CLIs[0].leaders( jsonFormat=False ) )
1751 main.log.debug( CLIs[0].partitions( jsonFormat=False ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001752
Jon Hall6aec96b2015-01-19 14:49:31 -08001753 def CASE7( self, main ):
1754 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001755 Check state after ONOS failure
Jon Hall6aec96b2015-01-19 14:49:31 -08001756 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001757 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -07001758 assert numControllers, "numControllers not defined"
1759 assert main, "main not defined"
1760 assert utilities.assert_equals, "utilities.assert_equals not defined"
1761 assert CLIs, "CLIs not defined"
1762 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08001763 main.case( "Running ONOS Constant State Tests" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001764
Jon Hall5cfd23c2015-03-19 11:40:57 -07001765 main.step( "Check that each switch has a master" )
Jon Hall6aec96b2015-01-19 14:49:31 -08001766 # Assert that each device has a master
Jon Hall5cfd23c2015-03-19 11:40:57 -07001767 rolesNotNull = main.TRUE
1768 threads = []
1769 for i in range( numControllers ):
1770 t = main.Thread( target=CLIs[i].rolesNotNull,
1771 name="rolesNotNull-" + str( i ),
1772 args=[ ] )
1773 threads.append( t )
1774 t.start()
1775
1776 for t in threads:
1777 t.join()
1778 rolesNotNull = rolesNotNull and t.result
Jon Hall6aec96b2015-01-19 14:49:31 -08001779 utilities.assert_equals(
1780 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001781 actual=rolesNotNull,
Jon Hall6aec96b2015-01-19 14:49:31 -08001782 onpass="Each device has a master",
1783 onfail="Some devices don't have a master assigned" )
Jon Hall94fd0472014-12-08 11:52:42 -08001784
Jon Hall390696c2015-05-05 17:13:41 -07001785 main.step( "Read device roles from ONOS" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001786 ONOSMastership = []
1787 mastershipCheck = main.FALSE
1788 consistentMastership = True
1789 rolesResults = True
1790 threads = []
1791 for i in range( numControllers ):
1792 t = main.Thread( target=CLIs[i].roles,
1793 name="roles-" + str( i ),
1794 args=[] )
1795 threads.append( t )
1796 t.start()
1797
1798 for t in threads:
1799 t.join()
1800 ONOSMastership.append( t.result )
1801
1802 for i in range( numControllers ):
1803 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001804 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001805 " roles" )
1806 main.log.warn(
1807 "ONOS" + str( i + 1 ) + " mastership response: " +
1808 repr( ONOSMastership[i] ) )
1809 rolesResults = False
1810 utilities.assert_equals(
1811 expect=True,
1812 actual=rolesResults,
1813 onpass="No error in reading roles output",
1814 onfail="Error in reading roles from ONOS" )
1815
1816 main.step( "Check for consistency in roles from each controller" )
1817 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001818 main.log.info(
Jon Hall6aec96b2015-01-19 14:49:31 -08001819 "Switch roles are consistent across all ONOS nodes" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001820 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001821 consistentMastership = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001822 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001823 expect=True,
Jon Hall8f89dda2015-01-22 16:03:33 -08001824 actual=consistentMastership,
Jon Hall6aec96b2015-01-19 14:49:31 -08001825 onpass="Switch roles are consistent across all ONOS nodes",
1826 onfail="ONOS nodes have different views of switch roles" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001827
Jon Hall5cfd23c2015-03-19 11:40:57 -07001828 if rolesResults and not consistentMastership:
1829 for i in range( numControllers ):
1830 main.log.warn(
1831 "ONOS" + str( i + 1 ) + " roles: ",
1832 json.dumps(
1833 json.loads( ONOSMastership[ i ] ),
1834 sort_keys=True,
1835 indent=4,
1836 separators=( ',', ': ' ) ) )
1837 elif rolesResults and not consistentMastership:
1838 mastershipCheck = main.TRUE
1839
Jon Hallfeff3082015-05-19 10:23:26 -07001840 '''
Jon Hall73cf9cc2014-11-20 22:28:38 -08001841 description2 = "Compare switch roles from before failure"
Jon Hall6aec96b2015-01-19 14:49:31 -08001842 main.step( description2 )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001843 try:
1844 currentJson = json.loads( ONOSMastership[0] )
1845 oldJson = json.loads( mastershipState )
1846 except ( ValueError, TypeError ):
1847 main.log.exception( "Something is wrong with parsing " +
1848 "ONOSMastership[0] or mastershipState" )
1849 main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[0] ) )
1850 main.log.error( "mastershipState" + repr( mastershipState ) )
1851 main.cleanup()
1852 main.exit()
Jon Hall8f89dda2015-01-22 16:03:33 -08001853 mastershipCheck = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08001854 for i in range( 1, 29 ):
1855 switchDPID = str(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001856 main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001857 current = [ switch[ 'master' ] for switch in currentJson
Jon Hall6aec96b2015-01-19 14:49:31 -08001858 if switchDPID in switch[ 'id' ] ]
Jon Hall8f89dda2015-01-22 16:03:33 -08001859 old = [ switch[ 'master' ] for switch in oldJson
Jon Hall6aec96b2015-01-19 14:49:31 -08001860 if switchDPID in switch[ 'id' ] ]
Jon Hall73cf9cc2014-11-20 22:28:38 -08001861 if current == old:
Jon Hall8f89dda2015-01-22 16:03:33 -08001862 mastershipCheck = mastershipCheck and main.TRUE
Jon Hall73cf9cc2014-11-20 22:28:38 -08001863 else:
Jon Hall6aec96b2015-01-19 14:49:31 -08001864 main.log.warn( "Mastership of switch %s changed" % switchDPID )
Jon Hall8f89dda2015-01-22 16:03:33 -08001865 mastershipCheck = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001866 utilities.assert_equals(
1867 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001868 actual=mastershipCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -08001869 onpass="Mastership of Switches was not changed",
1870 onfail="Mastership of some switches changed" )
Jon Hallfeff3082015-05-19 10:23:26 -07001871 '''
Jon Hall6aec96b2015-01-19 14:49:31 -08001872 # NOTE: we expect mastership to change on controller failure
Jon Hall73cf9cc2014-11-20 22:28:38 -08001873
Jon Hall6aec96b2015-01-19 14:49:31 -08001874 main.step( "Get the intents and compare across all nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001875 ONOSIntents = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001876 intentCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001877 consistentIntents = True
1878 intentsResults = True
1879 threads = []
1880 for i in range( numControllers ):
1881 t = main.Thread( target=CLIs[i].intents,
1882 name="intents-" + str( i ),
1883 args=[],
1884 kwargs={ 'jsonFormat': True } )
1885 threads.append( t )
1886 t.start()
1887
1888 for t in threads:
1889 t.join()
1890 ONOSIntents.append( t.result )
1891
1892 for i in range( numControllers ):
1893 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001894 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001895 " intents" )
1896 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1897 repr( ONOSIntents[ i ] ) )
1898 intentsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001899 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001900 expect=True,
1901 actual=intentsResults,
1902 onpass="No error in reading intents output",
1903 onfail="Error in reading intents from ONOS" )
1904
1905 main.step( "Check for consistency in Intents from each controller" )
1906 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001907 main.log.info( "Intents are consistent across all ONOS " +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001908 "nodes" )
1909 else:
1910 consistentIntents = False
Jon Hall390696c2015-05-05 17:13:41 -07001911
1912 # Try to make it easy to figure out what is happening
1913 #
1914 # Intent ONOS1 ONOS2 ...
1915 # 0x01 INSTALLED INSTALLING
1916 # ... ... ...
1917 # ... ... ...
1918 title = " ID"
1919 for n in range( numControllers ):
1920 title += " " * 10 + "ONOS" + str( n + 1 )
1921 main.log.warn( title )
1922 # get all intent keys in the cluster
1923 keys = []
1924 for nodeStr in ONOSIntents:
1925 node = json.loads( nodeStr )
1926 for intent in node:
1927 keys.append( intent.get( 'id' ) )
1928 keys = set( keys )
1929 for key in keys:
1930 row = "%-13s" % key
1931 for nodeStr in ONOSIntents:
1932 node = json.loads( nodeStr )
1933 for intent in node:
1934 if intent.get( 'id' ) == key:
1935 row += "%-15s" % intent.get( 'state' )
1936 main.log.warn( row )
1937 # End table view
1938
Jon Hall5cfd23c2015-03-19 11:40:57 -07001939 utilities.assert_equals(
1940 expect=True,
1941 actual=consistentIntents,
Jon Hall6aec96b2015-01-19 14:49:31 -08001942 onpass="Intents are consistent across all ONOS nodes",
1943 onfail="ONOS nodes have different views of intents" )
Jon Hall1b8f54a2015-02-04 13:24:20 -08001944 intentStates = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001945 for node in ONOSIntents: # Iter through ONOS nodes
Jon Hall1b8f54a2015-02-04 13:24:20 -08001946 nodeStates = []
Jon Hall58c76b72015-02-23 11:09:24 -08001947 # Iter through intents of a node
Jon Hall5cfd23c2015-03-19 11:40:57 -07001948 try:
1949 for intent in json.loads( node ):
1950 nodeStates.append( intent[ 'state' ] )
1951 except ( ValueError, TypeError ):
1952 main.log.exception( "Error in parsing intents" )
1953 main.log.error( repr( node ) )
Jon Hall1b8f54a2015-02-04 13:24:20 -08001954 intentStates.append( nodeStates )
1955 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
1956 main.log.info( dict( out ) )
1957
Jon Hall5cfd23c2015-03-19 11:40:57 -07001958 if intentsResults and not consistentIntents:
1959 for i in range( numControllers ):
1960 main.log.warn( "ONOS" + str( i + 1 ) + " intents: " )
1961 main.log.warn( json.dumps(
1962 json.loads( ONOSIntents[ i ] ),
1963 sort_keys=True,
1964 indent=4,
1965 separators=( ',', ': ' ) ) )
1966 elif intentsResults and consistentIntents:
1967 intentCheck = main.TRUE
1968
Jon Hall58c76b72015-02-23 11:09:24 -08001969 # NOTE: Store has no durability, so intents are lost across system
1970 # restarts
Jon Hall6aec96b2015-01-19 14:49:31 -08001971 """
1972 main.step( "Compare current intents with intents before the failure" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001973 # NOTE: this requires case 5 to pass for intentState to be set.
Jon Hall94fd0472014-12-08 11:52:42 -08001974 # maybe we should stop the test if that fails?
Jon Hall40d2cbd2015-06-03 16:24:29 -07001975 sameIntents = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001976 if intentState and intentState == ONOSIntents[ 0 ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08001977 sameIntents = main.TRUE
Jon Hallfeff3082015-05-19 10:23:26 -07001978 main.log.info( "Intents are consistent with before failure" )
Jon Hall6aec96b2015-01-19 14:49:31 -08001979 # TODO: possibly the states have changed? we may need to figure out
Jon Hall5cfd23c2015-03-19 11:40:57 -07001980 # what the acceptable states are
Jon Hall40d2cbd2015-06-03 16:24:29 -07001981 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
1982 sameIntents = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08001983 try:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001984 before = json.loads( intentState )
1985 after = json.loads( ONOSIntents[ 0 ] )
1986 for intent in before:
1987 if intent not in after:
1988 sameIntents = main.FALSE
Jon Hallc9eabec2015-06-10 14:33:14 -07001989 main.log.debug( "Intent is not currently in ONOS " +
Jon Hall40d2cbd2015-06-03 16:24:29 -07001990 "(at least in the same form):" )
1991 main.log.debug( json.dumps( intent ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001992 except ( ValueError, TypeError ):
1993 main.log.exception( "Exception printing intents" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001994 main.log.debug( repr( ONOSIntents[0] ) )
1995 main.log.debug( repr( intentState ) )
1996 if sameIntents == main.FALSE:
1997 try:
1998 main.log.debug( "ONOS intents before: " )
1999 main.log.debug( json.dumps( json.loads( intentState ),
2000 sort_keys=True, indent=4,
2001 separators=( ',', ': ' ) ) )
2002 main.log.debug( "Current ONOS intents: " )
2003 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
2004 sort_keys=True, indent=4,
2005 separators=( ',', ': ' ) ) )
2006 except ( ValueError, TypeError ):
2007 main.log.exception( "Exception printing intents" )
2008 main.log.debug( repr( ONOSIntents[0] ) )
2009 main.log.debug( repr( intentState ) )
Jon Hall6aec96b2015-01-19 14:49:31 -08002010 utilities.assert_equals(
2011 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002012 actual=sameIntents,
Jon Hall6aec96b2015-01-19 14:49:31 -08002013 onpass="Intents are consistent with before failure",
2014 onfail="The Intents changed during failure" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002015 intentCheck = intentCheck and sameIntents
Jon Hall6aec96b2015-01-19 14:49:31 -08002016 """
2017 main.step( "Get the OF Table entries and compare to before " +
2018 "component failure" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002019 FlowTables = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002020 flows2 = []
2021 for i in range( 28 ):
2022 main.log.info( "Checking flow table on s" + str( i + 1 ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08002023 tmpFlows = main.Mininet2.getFlowTable( 1.3, "s" + str( i + 1 ) )
2024 flows2.append( tmpFlows )
2025 tempResult = main.Mininet2.flowComp(
Jon Hall6aec96b2015-01-19 14:49:31 -08002026 flow1=flows[ i ],
Jon Hall8f89dda2015-01-22 16:03:33 -08002027 flow2=tmpFlows )
2028 FlowTables = FlowTables and tempResult
2029 if FlowTables == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002030 main.log.info( "Differences in flow table for switch: s" +
2031 str( i + 1 ) )
Jon Hall6aec96b2015-01-19 14:49:31 -08002032 utilities.assert_equals(
2033 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002034 actual=FlowTables,
Jon Hall6aec96b2015-01-19 14:49:31 -08002035 onpass="No changes were found in the flow tables",
2036 onfail="Changes were found in the flow tables" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002037
Jon Hall40d2cbd2015-06-03 16:24:29 -07002038 # main.step( "Check the continuous pings to ensure that no packets " +
2039 # "were dropped during component failure" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002040 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
2041 main.params[ 'TESTONIP' ] )
Jon Hall8f89dda2015-01-22 16:03:33 -08002042 LossInPings = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002043 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
2044 for i in range( 8, 18 ):
2045 main.log.info(
2046 "Checking for a loss in pings along flow from s" +
2047 str( i ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08002048 LossInPings = main.Mininet2.checkForLoss(
Jon Hall6aec96b2015-01-19 14:49:31 -08002049 "/tmp/ping.h" +
Jon Hall8f89dda2015-01-22 16:03:33 -08002050 str( i ) ) or LossInPings
2051 if LossInPings == main.TRUE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002052 main.log.info( "Loss in ping detected" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002053 elif LossInPings == main.ERROR:
Jon Hall6aec96b2015-01-19 14:49:31 -08002054 main.log.info( "There are multiple mininet process running" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002055 elif LossInPings == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002056 main.log.info( "No Loss in the pings" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002057 main.log.info( "No loss of dataplane connectivity" )
2058 # utilities.assert_equals(
2059 # expect=main.FALSE,
2060 # actual=LossInPings,
2061 # onpass="No Loss of connectivity",
2062 # onfail="Loss of dataplane connectivity detected" )
2063
Jon Hall58c76b72015-02-23 11:09:24 -08002064 # NOTE: Since intents are not persisted with IntnentStore,
2065 # we expect loss in dataplane connectivity
Jon Hall8f89dda2015-01-22 16:03:33 -08002066 LossInPings = main.FALSE
Jon Hall73cf9cc2014-11-20 22:28:38 -08002067
Jon Hall390696c2015-05-05 17:13:41 -07002068 main.step( "Leadership Election is still functional" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002069 # Test of LeadershipElection
Jon Hall8f89dda2015-01-22 16:03:33 -08002070 leaderList = []
2071 leaderResult = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002072 for cli in CLIs:
2073 leaderN = cli.electionTestLeader()
Jon Hall8f89dda2015-01-22 16:03:33 -08002074 leaderList.append( leaderN )
Jon Hall669173b2014-12-17 11:36:30 -08002075 if leaderN == main.FALSE:
Jon Hallfeff3082015-05-19 10:23:26 -07002076 # error in response
Jon Hall40d2cbd2015-06-03 16:24:29 -07002077 main.log.error( "Something is wrong with " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002078 "electionTestLeader function, check the" +
Jon Hall6aec96b2015-01-19 14:49:31 -08002079 " error logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002080 leaderResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002081 elif leaderN is None:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002082 main.log.error( cli.name +
2083 " shows no leader for the election-app." )
Jon Hall8f89dda2015-01-22 16:03:33 -08002084 leaderResult = main.FALSE
2085 if len( set( leaderList ) ) != 1:
2086 leaderResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002087 main.log.error(
2088 "Inconsistent view of leader for the election test app" )
2089 # TODO: print the list
Jon Hall6aec96b2015-01-19 14:49:31 -08002090 utilities.assert_equals(
2091 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002092 actual=leaderResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002093 onpass="Leadership election passed",
2094 onfail="Something went wrong with Leadership election" )
Jon Hall669173b2014-12-17 11:36:30 -08002095
Jon Hall6aec96b2015-01-19 14:49:31 -08002096 def CASE8( self, main ):
2097 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002098 Compare topo
Jon Hall6aec96b2015-01-19 14:49:31 -08002099 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002100 import sys
Jon Hall6aec96b2015-01-19 14:49:31 -08002101 # FIXME add this path to params
2102 sys.path.append( "/home/admin/sts" )
2103 # assumes that sts is already in you PYTHONPATH
2104 from sts.topology.teston_topology import TestONTopology
Jon Hall73cf9cc2014-11-20 22:28:38 -08002105 import json
2106 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002107 assert numControllers, "numControllers not defined"
2108 assert main, "main not defined"
2109 assert utilities.assert_equals, "utilities.assert_equals not defined"
2110 assert CLIs, "CLIs not defined"
2111 assert nodes, "nodes not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002112
Jon Hallfeff3082015-05-19 10:23:26 -07002113 main.case( "Compare ONOS Topology view to Mininet topology" )
2114 main.caseExplaination = "Compare topology objects between Mininet" +\
2115 " and ONOS"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002116
Jon Hallfeff3082015-05-19 10:23:26 -07002117 main.step( "Comparing ONOS topology to MN" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002118 devicesResults = main.TRUE
Jon Hall8f89dda2015-01-22 16:03:33 -08002119 linksResults = main.TRUE
Jon Hall58c76b72015-02-23 11:09:24 -08002120 hostsResults = main.TRUE
Jon Hallc9eabec2015-06-10 14:33:14 -07002121 hostAttachmentResults = True
Jon Hall8f89dda2015-01-22 16:03:33 -08002122 topoResult = main.FALSE
Jon Hall73cf9cc2014-11-20 22:28:38 -08002123 elapsed = 0
Jon Hallffb386d2014-11-21 13:43:38 -08002124 count = 0
Jon Hall6aec96b2015-01-19 14:49:31 -08002125 main.step( "Collecting topology information from ONOS" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002126 startTime = time.time()
Jon Hall21270ac2015-02-16 17:59:55 -08002127 # Give time for Gossip to work
Jon Hallc9eabec2015-06-10 14:33:14 -07002128 while topoResult == main.FALSE and elapsed < 60:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002129 count += 1
Jon Hall8f89dda2015-01-22 16:03:33 -08002130 cliStart = time.time()
Jon Hall94fd0472014-12-08 11:52:42 -08002131 devices = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002132 threads = []
2133 for i in range( numControllers ):
2134 t = main.Thread( target=CLIs[i].devices,
2135 name="devices-" + str( i ),
2136 args=[ ] )
2137 threads.append( t )
2138 t.start()
2139
2140 for t in threads:
2141 t.join()
2142 devices.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002143 hosts = []
Jon Hall58c76b72015-02-23 11:09:24 -08002144 ipResult = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002145 threads = []
2146 for i in range( numControllers ):
2147 t = main.Thread( target=CLIs[i].hosts,
2148 name="hosts-" + str( i ),
2149 args=[ ] )
2150 threads.append( t )
2151 t.start()
2152
2153 for t in threads:
2154 t.join()
2155 try:
2156 hosts.append( json.loads( t.result ) )
2157 except ( ValueError, TypeError ):
2158 main.log.exception( "Error parsing hosts results" )
2159 main.log.error( repr( t.result ) )
Jon Hall529a37f2015-01-28 10:02:00 -08002160 for controller in range( 0, len( hosts ) ):
2161 controllerStr = str( controller + 1 )
2162 for host in hosts[ controller ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002163 if host is None or host.get( 'ipAddresses', [] ) == []:
Jon Hall529a37f2015-01-28 10:02:00 -08002164 main.log.error(
Jon Hallfeff3082015-05-19 10:23:26 -07002165 "DEBUG:Error with host ipAddresses on controller" +
Jon Hall529a37f2015-01-28 10:02:00 -08002166 controllerStr + ": " + str( host ) )
Jon Hall58c76b72015-02-23 11:09:24 -08002167 ipResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002168 ports = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002169 threads = []
2170 for i in range( numControllers ):
2171 t = main.Thread( target=CLIs[i].ports,
2172 name="ports-" + str( i ),
2173 args=[ ] )
2174 threads.append( t )
2175 t.start()
2176
2177 for t in threads:
2178 t.join()
2179 ports.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002180 links = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002181 threads = []
2182 for i in range( numControllers ):
2183 t = main.Thread( target=CLIs[i].links,
2184 name="links-" + str( i ),
2185 args=[ ] )
2186 threads.append( t )
2187 t.start()
2188
2189 for t in threads:
2190 t.join()
2191 links.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002192 clusters = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002193 threads = []
2194 for i in range( numControllers ):
2195 t = main.Thread( target=CLIs[i].clusters,
2196 name="clusters-" + str( i ),
2197 args=[ ] )
2198 threads.append( t )
2199 t.start()
2200
2201 for t in threads:
2202 t.join()
2203 clusters.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002204
Jon Hall8f89dda2015-01-22 16:03:33 -08002205 elapsed = time.time() - startTime
2206 cliTime = time.time() - cliStart
Jon Hall40d2cbd2015-06-03 16:24:29 -07002207 print "Elapsed time: " + str( elapsed )
Jon Hall8f89dda2015-01-22 16:03:33 -08002208 print "CLI time: " + str( cliTime )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002209
Jon Hallb6a54872015-06-12 14:02:42 -07002210 mnSwitches = main.Mininet1.getSwitches()
2211 mnLinks = main.Mininet1.getLinks()
2212 mnHosts = main.Mininet1.getHosts()
Jon Hall8f89dda2015-01-22 16:03:33 -08002213 for controller in range( numControllers ):
2214 controllerStr = str( controller + 1 )
Jon Hallb6a54872015-06-12 14:02:42 -07002215 if devices[ controller ] and ports[ controller ] and\
2216 "Error" not in devices[ controller ] and\
2217 "Error" not in ports[ controller ]:
2218
Jon Hall8f89dda2015-01-22 16:03:33 -08002219 currentDevicesResult = main.Mininet1.compareSwitches(
Jon Hallb6a54872015-06-12 14:02:42 -07002220 mnSwitches,
2221 json.loads( devices[ controller ] ),
2222 json.loads( ports[ controller ] ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002223 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08002224 currentDevicesResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002225 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08002226 actual=currentDevicesResult,
2227 onpass="ONOS" + controllerStr +
2228 " Switches view is correct",
2229 onfail="ONOS" + controllerStr +
2230 " Switches view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002231
Jon Hallb6a54872015-06-12 14:02:42 -07002232 if links[ controller ] and "Error" not in links[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08002233 currentLinksResult = main.Mininet1.compareLinks(
Jon Hallb6a54872015-06-12 14:02:42 -07002234 mnSwitches, mnLinks,
2235 json.loads( links[ controller ] ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002236 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08002237 currentLinksResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002238 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08002239 actual=currentLinksResult,
2240 onpass="ONOS" + controllerStr +
2241 " links view is correct",
2242 onfail="ONOS" + controllerStr +
2243 " links view is incorrect" )
2244
2245 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2246 currentHostsResult = main.Mininet1.compareHosts(
Jon Hallb6a54872015-06-12 14:02:42 -07002247 mnHosts,
2248 hosts[ controller ] )
Jon Hall58c76b72015-02-23 11:09:24 -08002249 else:
2250 currentHostsResult = main.FALSE
2251 utilities.assert_equals( expect=main.TRUE,
2252 actual=currentHostsResult,
2253 onpass="ONOS" + controllerStr +
2254 " hosts exist in Mininet",
2255 onfail="ONOS" + controllerStr +
2256 " hosts don't match Mininet" )
Jon Hallc9eabec2015-06-10 14:33:14 -07002257 # CHECKING HOST ATTACHMENT POINTS
2258 hostAttachment = True
2259 zeroHosts = False
2260 # FIXME: topo-HA/obelisk specific mappings:
2261 # key is mac and value is dpid
2262 mappings = {}
2263 for i in range( 1, 29 ): # hosts 1 through 28
2264 # set up correct variables:
2265 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2266 if i == 1:
2267 deviceId = "1000".zfill(16)
2268 elif i == 2:
2269 deviceId = "2000".zfill(16)
2270 elif i == 3:
2271 deviceId = "3000".zfill(16)
2272 elif i == 4:
2273 deviceId = "3004".zfill(16)
2274 elif i == 5:
2275 deviceId = "5000".zfill(16)
2276 elif i == 6:
2277 deviceId = "6000".zfill(16)
2278 elif i == 7:
2279 deviceId = "6007".zfill(16)
2280 elif i >= 8 and i <= 17:
2281 dpid = '3' + str( i ).zfill( 3 )
2282 deviceId = dpid.zfill(16)
2283 elif i >= 18 and i <= 27:
2284 dpid = '6' + str( i ).zfill( 3 )
2285 deviceId = dpid.zfill(16)
2286 elif i == 28:
2287 deviceId = "2800".zfill(16)
2288 mappings[ macId ] = deviceId
2289 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2290 if hosts[ controller ] == []:
2291 main.log.warn( "There are no hosts discovered" )
2292 zeroHosts = True
2293 else:
2294 for host in hosts[ controller ]:
2295 mac = None
2296 location = None
2297 device = None
2298 port = None
2299 try:
2300 mac = host.get( 'mac' )
2301 assert mac, "mac field could not be found for this host object"
Jon Hall58c76b72015-02-23 11:09:24 -08002302
Jon Hallc9eabec2015-06-10 14:33:14 -07002303 location = host.get( 'location' )
2304 assert location, "location field could not be found for this host object"
2305
2306 # Trim the protocol identifier off deviceId
2307 device = str( location.get( 'elementId' ) ).split(':')[1]
2308 assert device, "elementId field could not be found for this host location object"
2309
2310 port = location.get( 'port' )
2311 assert port, "port field could not be found for this host location object"
2312
2313 # Now check if this matches where they should be
2314 if mac and device and port:
2315 if str( port ) != "1":
2316 main.log.error( "The attachment port is incorrect for " +
2317 "host " + str( mac ) +
2318 ". Expected: 1 Actual: " + str( port) )
2319 hostAttachment = False
2320 if device != mappings[ str( mac ) ]:
2321 main.log.error( "The attachment device is incorrect for " +
2322 "host " + str( mac ) +
2323 ". Expected: " + mappings[ str( mac ) ] +
2324 " Actual: " + device )
2325 hostAttachment = False
2326 else:
2327 hostAttachment = False
2328 except AssertionError:
2329 main.log.exception( "Json object not as expected" )
2330 main.log.error( repr( host ) )
2331 hostAttachment = False
2332 else:
2333 main.log.error( "No hosts json output or \"Error\"" +
2334 " in output. hosts = " +
2335 repr( hosts[ controller ] ) )
2336 if zeroHosts:
2337 # TODO: Find a way to know if there should be hosts in a
2338 # given point of the test
2339 hostAttachment = True
2340
2341 # END CHECKING HOST ATTACHMENT POINTS
Jon Hall58c76b72015-02-23 11:09:24 -08002342 devicesResults = devicesResults and currentDevicesResult
Jon Hall58c76b72015-02-23 11:09:24 -08002343 linksResults = linksResults and currentLinksResult
2344 hostsResults = hostsResults and currentHostsResult
Jon Hallb6a54872015-06-12 14:02:42 -07002345 hostAttachmentResults = hostAttachmentResults and\
2346 hostAttachment
2347 topoResult = ( devicesResults and linksResults
2348 and hostsResults and ipResult and
2349 hostAttachmentResults )
Jon Hall94fd0472014-12-08 11:52:42 -08002350
Jon Hallc9eabec2015-06-10 14:33:14 -07002351 # Compare json objects for hosts and dataplane clusters
Jon Hall94fd0472014-12-08 11:52:42 -08002352
Jon Hallc9eabec2015-06-10 14:33:14 -07002353 # hosts
2354 main.step( "Hosts view is consistent across all ONOS nodes" )
2355 consistentHostsResult = main.TRUE
2356 for controller in range( len( hosts ) ):
2357 controllerStr = str( controller + 1 )
2358 if "Error" not in hosts[ controller ]:
2359 if hosts[ controller ] == hosts[ 0 ]:
2360 continue
2361 else: # hosts not consistent
2362 main.log.error( "hosts from ONOS" + controllerStr +
2363 " is inconsistent with ONOS1" )
2364 main.log.warn( repr( hosts[ controller ] ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08002365 consistentHostsResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002366
Jon Hallc9eabec2015-06-10 14:33:14 -07002367 else:
2368 main.log.error( "Error in getting ONOS hosts from ONOS" +
2369 controllerStr )
2370 consistentHostsResult = main.FALSE
2371 main.log.warn( "ONOS" + controllerStr +
2372 " hosts response: " +
2373 repr( hosts[ controller ] ) )
2374 utilities.assert_equals(
2375 expect=main.TRUE,
2376 actual=consistentHostsResult,
2377 onpass="Hosts view is consistent across all ONOS nodes",
2378 onfail="ONOS nodes have different views of hosts" )
Jon Hall94fd0472014-12-08 11:52:42 -08002379
Jon Hallc9eabec2015-06-10 14:33:14 -07002380 main.step( "Hosts information is correct" )
2381 hostsResults = hostsResults and ipResult
2382 utilities.assert_equals(
2383 expect=main.TRUE,
2384 actual=hostsResults,
2385 onpass="Host information is correct",
2386 onfail="Host information is incorrect" )
2387
2388 main.step( "Host attachment points to the network" )
2389 utilities.assert_equals(
2390 expect=True,
2391 actual=hostAttachmentResults,
2392 onpass="Hosts are correctly attached to the network",
2393 onfail="ONOS did not correctly attach hosts to the network" )
2394
2395 # Strongly connected clusters of devices
2396 main.step( "Clusters view is consistent across all ONOS nodes" )
2397 consistentClustersResult = main.TRUE
2398 for controller in range( len( clusters ) ):
2399 controllerStr = str( controller + 1 )
2400 if "Error" not in clusters[ controller ]:
2401 if clusters[ controller ] == clusters[ 0 ]:
2402 continue
2403 else: # clusters not consistent
2404 main.log.error( "clusters from ONOS" +
2405 controllerStr +
2406 " is inconsistent with ONOS1" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002407 consistentClustersResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002408
Jon Hallc9eabec2015-06-10 14:33:14 -07002409 else:
2410 main.log.error( "Error in getting dataplane clusters " +
2411 "from ONOS" + controllerStr )
2412 consistentClustersResult = main.FALSE
2413 main.log.warn( "ONOS" + controllerStr +
2414 " clusters response: " +
2415 repr( clusters[ controller ] ) )
2416 utilities.assert_equals(
2417 expect=main.TRUE,
2418 actual=consistentClustersResult,
2419 onpass="Clusters view is consistent across all ONOS nodes",
2420 onfail="ONOS nodes have different views of clusters" )
2421
2422 main.step( "There is only one SCC" )
2423 # there should always only be one cluster
2424 try:
2425 numClusters = len( json.loads( clusters[ 0 ] ) )
2426 except ( ValueError, TypeError ):
2427 main.log.exception( "Error parsing clusters[0]: " +
2428 repr( clusters[0] ) )
2429 clusterResults = main.FALSE
2430 if numClusters == 1:
2431 clusterResults = main.TRUE
2432 utilities.assert_equals(
2433 expect=1,
2434 actual=numClusters,
2435 onpass="ONOS shows 1 SCC",
2436 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2437
Jon Hallb6a54872015-06-12 14:02:42 -07002438 topoResult = ( devicesResults and linksResults
Jon Hallc9eabec2015-06-10 14:33:14 -07002439 and hostsResults and consistentHostsResult
2440 and consistentClustersResult and clusterResults
2441 and ipResult and hostAttachmentResults )
Jon Hall94fd0472014-12-08 11:52:42 -08002442
Jon Hall8f89dda2015-01-22 16:03:33 -08002443 topoResult = topoResult and int( count <= 2 )
2444 note = "note it takes about " + str( int( cliTime ) ) + \
2445 " seconds for the test to make all the cli calls to fetch " +\
2446 "the topology from each ONOS instance"
Jon Hall1b8f54a2015-02-04 13:24:20 -08002447 main.log.info(
Jon Hall8f89dda2015-01-22 16:03:33 -08002448 "Very crass estimate for topology discovery/convergence( " +
2449 str( note ) + " ): " + str( elapsed ) + " seconds, " +
Jon Hall6aec96b2015-01-19 14:49:31 -08002450 str( count ) + " tries" )
Jon Hallc9eabec2015-06-10 14:33:14 -07002451
2452 main.step( "Device information is correct" )
2453 utilities.assert_equals(
2454 expect=main.TRUE,
2455 actual=devicesResults,
2456 onpass="Device information is correct",
2457 onfail="Device information is incorrect" )
2458
Jon Hallc9eabec2015-06-10 14:33:14 -07002459 main.step( "Links are correct" )
2460 utilities.assert_equals(
2461 expect=main.TRUE,
2462 actual=linksResults,
2463 onpass="Link are correct",
2464 onfail="Links are incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002465
Jon Halla9d26da2015-03-30 16:45:32 -07002466 # FIXME: move this to an ONOS state case
2467 main.step( "Checking ONOS nodes" )
2468 nodesOutput = []
Jon Hall390696c2015-05-05 17:13:41 -07002469 nodeResults = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002470 threads = []
2471 for i in range( numControllers ):
2472 t = main.Thread( target=CLIs[i].nodes,
2473 name="nodes-" + str( i ),
2474 args=[ ] )
2475 threads.append( t )
2476 t.start()
2477
2478 for t in threads:
2479 t.join()
2480 nodesOutput.append( t.result )
2481 ips = [ node.ip_address for node in nodes ]
2482 for i in nodesOutput:
2483 try:
2484 current = json.loads( i )
2485 for node in current:
Jon Hall390696c2015-05-05 17:13:41 -07002486 currentResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002487 if node['ip'] in ips: # node in nodes() output is in cell
2488 if node['state'] == 'ACTIVE':
Jon Hall390696c2015-05-05 17:13:41 -07002489 currentResult = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002490 else:
2491 main.log.error( "Error in ONOS node availability" )
2492 main.log.error(
2493 json.dumps( current,
2494 sort_keys=True,
2495 indent=4,
2496 separators=( ',', ': ' ) ) )
2497 break
Jon Hall390696c2015-05-05 17:13:41 -07002498 nodeResults = nodeResults and currentResult
Jon Halla9d26da2015-03-30 16:45:32 -07002499 except ( ValueError, TypeError ):
2500 main.log.error( "Error parsing nodes output" )
2501 main.log.warn( repr( i ) )
Jon Hall390696c2015-05-05 17:13:41 -07002502 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
2503 onpass="Nodes check successful",
2504 onfail="Nodes check NOT successful" )
Jon Halla9d26da2015-03-30 16:45:32 -07002505
Jon Hall6aec96b2015-01-19 14:49:31 -08002506 def CASE9( self, main ):
2507 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002508 Link s3-s28 down
Jon Hall6aec96b2015-01-19 14:49:31 -08002509 """
2510 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002511 assert numControllers, "numControllers not defined"
2512 assert main, "main not defined"
2513 assert utilities.assert_equals, "utilities.assert_equals not defined"
2514 assert CLIs, "CLIs not defined"
2515 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002516 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002517
Jon Hall8f89dda2015-01-22 16:03:33 -08002518 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002519
Jon Hall6aec96b2015-01-19 14:49:31 -08002520 description = "Turn off a link to ensure that Link Discovery " +\
Jon Hall58c76b72015-02-23 11:09:24 -08002521 "is working properly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002522 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002523
Jon Hall6aec96b2015-01-19 14:49:31 -08002524 main.step( "Kill Link between s3 and s28" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002525 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
Jon Hall58c76b72015-02-23 11:09:24 -08002526 main.log.info( "Waiting " + str( linkSleep ) +
2527 " seconds for link down to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002528 time.sleep( linkSleep )
2529 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002530 onpass="Link down successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002531 onfail="Failed to bring link down" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002532 # TODO do some sort of check here
Jon Hall73cf9cc2014-11-20 22:28:38 -08002533
Jon Hall6aec96b2015-01-19 14:49:31 -08002534 def CASE10( self, main ):
2535 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002536 Link s3-s28 up
Jon Hall6aec96b2015-01-19 14:49:31 -08002537 """
2538 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002539 assert numControllers, "numControllers not defined"
2540 assert main, "main not defined"
2541 assert utilities.assert_equals, "utilities.assert_equals not defined"
2542 assert CLIs, "CLIs not defined"
2543 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002544 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002545
Jon Hall8f89dda2015-01-22 16:03:33 -08002546 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002547
Jon Hall6aec96b2015-01-19 14:49:31 -08002548 description = "Restore a link to ensure that Link Discovery is " + \
Jon Hall63604932015-02-26 17:09:50 -08002549 "working properly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002550 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002551
Jon Hall6aec96b2015-01-19 14:49:31 -08002552 main.step( "Bring link between s3 and s28 back up" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002553 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
Jon Hall58c76b72015-02-23 11:09:24 -08002554 main.log.info( "Waiting " + str( linkSleep ) +
2555 " seconds for link up to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002556 time.sleep( linkSleep )
2557 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002558 onpass="Link up successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002559 onfail="Failed to bring link up" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002560 # TODO do some sort of check here
Jon Hall73cf9cc2014-11-20 22:28:38 -08002561
Jon Hall6aec96b2015-01-19 14:49:31 -08002562 def CASE11( self, main ):
2563 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002564 Switch Down
Jon Hall6aec96b2015-01-19 14:49:31 -08002565 """
2566 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002567 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002568 assert numControllers, "numControllers not defined"
2569 assert main, "main not defined"
2570 assert utilities.assert_equals, "utilities.assert_equals not defined"
2571 assert CLIs, "CLIs not defined"
2572 assert nodes, "nodes not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002573
Jon Hall8f89dda2015-01-22 16:03:33 -08002574 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002575
2576 description = "Killing a switch to ensure it is discovered correctly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002577 main.case( description )
2578 switch = main.params[ 'kill' ][ 'switch' ]
2579 switchDPID = main.params[ 'kill' ][ 'dpid' ]
Jon Hall73cf9cc2014-11-20 22:28:38 -08002580
Jon Hall6aec96b2015-01-19 14:49:31 -08002581 # TODO: Make this switch parameterizable
2582 main.step( "Kill " + switch )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002583 main.log.info( "Deleting " + switch )
Jon Hall8f89dda2015-01-22 16:03:33 -08002584 main.Mininet1.delSwitch( switch )
2585 main.log.info( "Waiting " + str( switchSleep ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002586 " seconds for switch down to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002587 time.sleep( switchSleep )
2588 device = main.ONOScli1.getDevice( dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002589 # Peek at the deleted switch
2590 main.log.warn( str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002591 result = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002592 if device and device[ 'available' ] is False:
Jon Hall94fd0472014-12-08 11:52:42 -08002593 result = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002594 utilities.assert_equals( expect=main.TRUE, actual=result,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002595 onpass="Kill switch successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002596 onfail="Failed to kill switch?" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002597
Jon Hall6aec96b2015-01-19 14:49:31 -08002598 def CASE12( self, main ):
2599 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002600 Switch Up
Jon Hall6aec96b2015-01-19 14:49:31 -08002601 """
2602 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002603 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002604 assert numControllers, "numControllers not defined"
2605 assert main, "main not defined"
2606 assert utilities.assert_equals, "utilities.assert_equals not defined"
2607 assert CLIs, "CLIs not defined"
2608 assert nodes, "nodes not defined"
2609 assert ONOS1Port, "ONOS1Port not defined"
2610 assert ONOS2Port, "ONOS2Port not defined"
2611 assert ONOS3Port, "ONOS3Port not defined"
2612 assert ONOS4Port, "ONOS4Port not defined"
2613 assert ONOS5Port, "ONOS5Port not defined"
2614 assert ONOS6Port, "ONOS6Port not defined"
2615 assert ONOS7Port, "ONOS7Port not defined"
Jon Hall669173b2014-12-17 11:36:30 -08002616
Jon Hall8f89dda2015-01-22 16:03:33 -08002617 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
Jon Hall6aec96b2015-01-19 14:49:31 -08002618 switch = main.params[ 'kill' ][ 'switch' ]
2619 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2620 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hall73cf9cc2014-11-20 22:28:38 -08002621 description = "Adding a switch to ensure it is discovered correctly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002622 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002623
Jon Hall6aec96b2015-01-19 14:49:31 -08002624 main.step( "Add back " + switch )
Jon Hall8f89dda2015-01-22 16:03:33 -08002625 main.Mininet1.addSwitch( switch, dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002626 for peer in links:
Jon Hall8f89dda2015-01-22 16:03:33 -08002627 main.Mininet1.addLink( switch, peer )
Jon Hall58c76b72015-02-23 11:09:24 -08002628 main.Mininet1.assignSwController( sw=switch.split( 's' )[ 1 ],
2629 count=numControllers,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002630 ip1=nodes[ 0 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002631 port1=ONOS1Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002632 ip2=nodes[ 1 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002633 port2=ONOS2Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002634 ip3=nodes[ 2 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002635 port3=ONOS3Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002636 ip4=nodes[ 3 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002637 port4=ONOS4Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002638 ip5=nodes[ 4 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002639 port5=ONOS5Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002640 ip6=nodes[ 5 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002641 port6=ONOS6Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002642 ip7=nodes[ 6 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002643 port7=ONOS7Port )
2644 main.log.info( "Waiting " + str( switchSleep ) +
2645 " seconds for switch up to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002646 time.sleep( switchSleep )
2647 device = main.ONOScli1.getDevice( dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002648 # Peek at the deleted switch
2649 main.log.warn( str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002650 result = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002651 if device and device[ 'available' ]:
Jon Hall94fd0472014-12-08 11:52:42 -08002652 result = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002653 utilities.assert_equals( expect=main.TRUE, actual=result,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002654 onpass="add switch successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002655 onfail="Failed to add switch?" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002656
Jon Hall6aec96b2015-01-19 14:49:31 -08002657 def CASE13( self, main ):
2658 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002659 Clean up
Jon Hall6aec96b2015-01-19 14:49:31 -08002660 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002661 import os
2662 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002663 assert numControllers, "numControllers not defined"
2664 assert main, "main not defined"
2665 assert utilities.assert_equals, "utilities.assert_equals not defined"
2666 assert CLIs, "CLIs not defined"
2667 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002668
2669 # printing colors to terminal
Jon Hall5cfd23c2015-03-19 11:40:57 -07002670 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2671 'blue': '\033[94m', 'green': '\033[92m',
2672 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
Jon Hall40d2cbd2015-06-03 16:24:29 -07002673 main.case( "Test Cleanup" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002674 main.step( "Killing tcpdumps" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002675 main.Mininet2.stopTcpdump()
Jon Hall73cf9cc2014-11-20 22:28:38 -08002676
Jon Hall6aec96b2015-01-19 14:49:31 -08002677 main.step( "Copying MN pcap and ONOS log files to test station" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002678 testname = main.TEST
Jon Hall8f89dda2015-01-22 16:03:33 -08002679 teststationUser = main.params[ 'TESTONUSER' ]
2680 teststationIP = main.params[ 'TESTONIP' ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002681 # NOTE: MN Pcap file is being saved to ~/packet_captures
Jon Hall73cf9cc2014-11-20 22:28:38 -08002682 # scp this file as MN and TestON aren't necessarily the same vm
Jon Hall6aec96b2015-01-19 14:49:31 -08002683 # FIXME: scp
2684 # mn files
2685 # TODO: Load these from params
2686 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002687 logFolder = "/opt/onos/log/"
2688 logFiles = [ "karaf.log", "karaf.log.1" ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002689 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002690 dstDir = "~/packet_captures/"
2691 for f in logFiles:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002692 for node in nodes:
2693 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2694 ":" + logFolder + f + " " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002695 teststationUser + "@" +
2696 teststationIP + ":" +
2697 dstDir + str( testname ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002698 "-" + node.name + "-" + f )
Jon Hall58c76b72015-02-23 11:09:24 -08002699 main.ONOSbench.handle.expect( "\$" )
2700
Jon Hall6aec96b2015-01-19 14:49:31 -08002701 # std*.log's
2702 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002703 logFolder = "/opt/onos/var/"
2704 logFiles = [ "stderr.log", "stdout.log" ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002705 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002706 dstDir = "~/packet_captures/"
2707 for f in logFiles:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002708 for node in nodes:
2709 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2710 ":" + logFolder + f + " " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002711 teststationUser + "@" +
2712 teststationIP + ":" +
2713 dstDir + str( testname ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002714 "-" + node.name + "-" + f )
Jon Hall58c76b72015-02-23 11:09:24 -08002715 main.ONOSbench.handle.expect( "\$" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002716 # sleep so scp can finish
2717 time.sleep( 10 )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002718
2719 main.step( "Stopping Mininet" )
Jon Hall390696c2015-05-05 17:13:41 -07002720 mnResult = main.Mininet1.stopNet()
2721 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2722 onpass="Mininet stopped",
2723 onfail="MN cleanup NOT successful" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002724
2725 main.step( "Checking ONOS Logs for errors" )
2726 for node in nodes:
2727 print colors[ 'purple' ] + "Checking logs for errors on " + \
2728 node.name + ":" + colors[ 'end' ]
Jon Hall40d2cbd2015-06-03 16:24:29 -07002729 print main.ONOSbench.checkLogs( node.ip_address, restart=True )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002730
Jon Hall6aec96b2015-01-19 14:49:31 -08002731 main.step( "Packing and rotating pcap archives" )
2732 os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002733
Jon Hallfeff3082015-05-19 10:23:26 -07002734 try:
2735 timerLog = open( main.logdir + "/Timers.csv", 'w')
Jon Hallc9eabec2015-06-10 14:33:14 -07002736 main.log.error( ", ".join( labels ) + "\n" + ", ".join( data ) )
2737 timerLog.write( ", ".join( labels ) + "\n" + ", ".join( data ) )
Jon Hallfeff3082015-05-19 10:23:26 -07002738 timerLog.close()
2739 except NameError, e:
2740 main.log.exception(e)
2741
Jon Hall6aec96b2015-01-19 14:49:31 -08002742 def CASE14( self, main ):
2743 """
Jon Hall669173b2014-12-17 11:36:30 -08002744 start election app on all onos nodes
Jon Hall6aec96b2015-01-19 14:49:31 -08002745 """
Jon Hall5cfd23c2015-03-19 11:40:57 -07002746 assert numControllers, "numControllers not defined"
2747 assert main, "main not defined"
2748 assert utilities.assert_equals, "utilities.assert_equals not defined"
2749 assert CLIs, "CLIs not defined"
2750 assert nodes, "nodes not defined"
2751
Jon Hall390696c2015-05-05 17:13:41 -07002752 main.case("Start Leadership Election app")
2753 main.step( "Install leadership election app" )
Jon Hallfeff3082015-05-19 10:23:26 -07002754 appResult = main.ONOScli1.activateApp( "org.onosproject.election" )
2755 utilities.assert_equals(
2756 expect=main.TRUE,
2757 actual=appResult,
2758 onpass="Election app installed",
2759 onfail="Something went wrong with installing Leadership election" )
2760
2761 main.step( "Run for election on each node" )
2762 leaderResult = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002763 leaders = []
2764 for cli in CLIs:
Jon Hall390696c2015-05-05 17:13:41 -07002765 cli.electionTestRun()
2766 for cli in CLIs:
Jon Halla9d26da2015-03-30 16:45:32 -07002767 leader = cli.electionTestLeader()
2768 if leader is None or leader == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002769 main.log.error( cli.name + ": Leader for the election app " +
Jon Halla9d26da2015-03-30 16:45:32 -07002770 "should be an ONOS node, instead got '" +
2771 str( leader ) + "'" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002772 leaderResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002773 leaders.append( leader )
Jon Hall6aec96b2015-01-19 14:49:31 -08002774 utilities.assert_equals(
2775 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002776 actual=leaderResult,
Jon Hallfeff3082015-05-19 10:23:26 -07002777 onpass="Successfully ran for leadership",
2778 onfail="Failed to run for leadership" )
2779
2780 main.step( "Check that each node shows the same leader" )
2781 sameLeader = main.TRUE
2782 if len( set( leaders ) ) != 1:
2783 sameLeader = main.FALSE
2784 main.log.error( "Results of electionTestLeader is order of CLIs:" +
2785 str( leaders ) )
2786 utilities.assert_equals(
2787 expect=main.TRUE,
2788 actual=sameLeader,
2789 onpass="Leadership is consistent for the election topic",
2790 onfail="Nodes have different leaders" )
Jon Hall669173b2014-12-17 11:36:30 -08002791
Jon Hall6aec96b2015-01-19 14:49:31 -08002792 def CASE15( self, main ):
2793 """
Jon Hall669173b2014-12-17 11:36:30 -08002794 Check that Leadership Election is still functional
Jon Hall6aec96b2015-01-19 14:49:31 -08002795 """
Jon Hall390696c2015-05-05 17:13:41 -07002796 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002797 assert numControllers, "numControllers not defined"
2798 assert main, "main not defined"
2799 assert utilities.assert_equals, "utilities.assert_equals not defined"
2800 assert CLIs, "CLIs not defined"
2801 assert nodes, "nodes not defined"
2802
Jon Hall8f89dda2015-01-22 16:03:33 -08002803 leaderResult = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08002804 description = "Check that Leadership Election is still functional"
Jon Hall6aec96b2015-01-19 14:49:31 -08002805 main.case( description )
Jon Hallfeff3082015-05-19 10:23:26 -07002806 # NOTE: Need to re-run since being a canidate is not persistant
2807 main.step( "Run for election on each node" )
2808 leaderResult = main.TRUE
2809 leaders = []
2810 for cli in CLIs:
2811 cli.electionTestRun()
2812 for cli in CLIs:
2813 leader = cli.electionTestLeader()
2814 if leader is None or leader == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002815 main.log.error( cli.name + ": Leader for the election app " +
Jon Hallfeff3082015-05-19 10:23:26 -07002816 "should be an ONOS node, instead got '" +
2817 str( leader ) + "'" )
2818 leaderResult = main.FALSE
2819 leaders.append( leader )
2820 utilities.assert_equals(
2821 expect=main.TRUE,
2822 actual=leaderResult,
2823 onpass="Successfully ran for leadership",
2824 onfail="Failed to run for leadership" )
2825
2826 main.step( "Check that each node shows the same leader" )
2827 sameLeader = main.TRUE
2828 if len( set( leaders ) ) != 1:
2829 sameLeader = main.FALSE
2830 main.log.error( "Results of electionTestLeader is order of CLIs:" +
2831 str( leaders ) )
2832 utilities.assert_equals(
2833 expect=main.TRUE,
2834 actual=sameLeader,
2835 onpass="Leadership is consistent for the election topic",
2836 onfail="Nodes have different leaders" )
2837
Jon Hall6aec96b2015-01-19 14:49:31 -08002838 main.step( "Find current leader and withdraw" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002839 leader = main.ONOScli1.electionTestLeader()
Jon Halla9d26da2015-03-30 16:45:32 -07002840 # do some sanity checking on leader before using it
Jon Hall8f89dda2015-01-22 16:03:33 -08002841 withdrawResult = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002842 if leader is None or leader == main.FALSE:
Jon Hallfeff3082015-05-19 10:23:26 -07002843 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -08002844 "Leader for the election app should be an ONOS node," +
Jon Hall58c76b72015-02-23 11:09:24 -08002845 "instead got '" + str( leader ) + "'" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002846 leaderResult = main.FALSE
Jon Hall63604932015-02-26 17:09:50 -08002847 oldLeader = None
Jon Hall5cfd23c2015-03-19 11:40:57 -07002848 for i in range( len( CLIs ) ):
2849 if leader == nodes[ i ].ip_address:
2850 oldLeader = CLIs[ i ]
2851 break
Jon Halla9d26da2015-03-30 16:45:32 -07002852 else: # FOR/ELSE statement
Jon Hall5cfd23c2015-03-19 11:40:57 -07002853 main.log.error( "Leader election, could not find current leader" )
Jon Hall63604932015-02-26 17:09:50 -08002854 if oldLeader:
2855 withdrawResult = oldLeader.electionTestWithdraw()
Jon Hall6aec96b2015-01-19 14:49:31 -08002856 utilities.assert_equals(
2857 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002858 actual=withdrawResult,
Jon Hallfeff3082015-05-19 10:23:26 -07002859 onpass="Node was withdrawn from election",
2860 onfail="Node was not withdrawn from election" )
Jon Hall669173b2014-12-17 11:36:30 -08002861
Jon Hall6aec96b2015-01-19 14:49:31 -08002862 main.step( "Make sure new leader is elected" )
Jon Halla9d26da2015-03-30 16:45:32 -07002863 # FIXME: use threads
Jon Hall8f89dda2015-01-22 16:03:33 -08002864 leaderList = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002865 for cli in CLIs:
2866 leaderN = cli.electionTestLeader()
2867 leaderList.append( leaderN )
Jon Hall669173b2014-12-17 11:36:30 -08002868 if leaderN == leader:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002869 main.log.error( cli.name + " still sees " + str( leader ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002870 " as leader after they withdrew" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002871 leaderResult = main.FALSE
Jon Hall669173b2014-12-17 11:36:30 -08002872 elif leaderN == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002873 # error in response
2874 # TODO: add check for "Command not found:" in the driver, this
Jon Hall5cfd23c2015-03-19 11:40:57 -07002875 # means the app isn't loaded
Jon Hall40d2cbd2015-06-03 16:24:29 -07002876 main.log.error( "Something is wrong with " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002877 "electionTestLeader function, " +
Jon Hall6aec96b2015-01-19 14:49:31 -08002878 "check the error logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002879 leaderResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002880 elif leaderN is None:
2881 # node may not have recieved the event yet
Jon Hall390696c2015-05-05 17:13:41 -07002882 time.sleep(7)
Jon Halla9d26da2015-03-30 16:45:32 -07002883 leaderN = cli.electionTestLeader()
2884 leaderList.pop()
2885 leaderList.append( leaderN )
Jon Hall8f89dda2015-01-22 16:03:33 -08002886 consistentLeader = main.FALSE
2887 if len( set( leaderList ) ) == 1:
Jon Hall6aec96b2015-01-19 14:49:31 -08002888 main.log.info( "Each Election-app sees '" +
Jon Hall8f89dda2015-01-22 16:03:33 -08002889 str( leaderList[ 0 ] ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002890 "' as the leader" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002891 consistentLeader = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08002892 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002893 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -08002894 "Inconsistent responses for leader of Election-app:" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002895 for n in range( len( leaderList ) ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07002896 main.log.error( "ONOS" + str( n + 1 ) + " response: " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002897 str( leaderList[ n ] ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002898 leaderResult = leaderResult and consistentLeader
Jon Hall6aec96b2015-01-19 14:49:31 -08002899 utilities.assert_equals(
2900 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002901 actual=leaderResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002902 onpass="Leadership election passed",
2903 onfail="Something went wrong with Leadership election" )
Jon Hall669173b2014-12-17 11:36:30 -08002904
Jon Hall58c76b72015-02-23 11:09:24 -08002905 main.step( "Run for election on old leader( just so everyone " +
2906 "is in the hat )" )
Jon Hall63604932015-02-26 17:09:50 -08002907 if oldLeader:
2908 runResult = oldLeader.electionTestRun()
2909 else:
2910 runResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002911 utilities.assert_equals(
2912 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002913 actual=runResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002914 onpass="App re-ran for election",
2915 onfail="App failed to run for election" )
Jon Hall390696c2015-05-05 17:13:41 -07002916
Jon Hallfeff3082015-05-19 10:23:26 -07002917 main.step( "Leader did not change when old leader re-ran" )
Jon Hall390696c2015-05-05 17:13:41 -07002918 afterRun = main.ONOScli1.electionTestLeader()
2919 # verify leader didn't just change
2920 if afterRun == leaderList[ 0 ]:
2921 afterResult = main.TRUE
2922 else:
2923 afterResult = main.FALSE
Jon Hall669173b2014-12-17 11:36:30 -08002924
Jon Hall6aec96b2015-01-19 14:49:31 -08002925 utilities.assert_equals(
2926 expect=main.TRUE,
Jon Hall390696c2015-05-05 17:13:41 -07002927 actual=afterResult,
2928 onpass="Old leader successfully re-ran for election",
Jon Hall6aec96b2015-01-19 14:49:31 -08002929 onfail="Something went wrong with Leadership election after " +
2930 "the old leader re-ran for election" )
Jon Hall390696c2015-05-05 17:13:41 -07002931
Jon Hall390696c2015-05-05 17:13:41 -07002932 def CASE16( self, main ):
2933 """
2934 Install Distributed Primitives app
2935 """
Jon Hall40d2cbd2015-06-03 16:24:29 -07002936 import time
Jon Hall390696c2015-05-05 17:13:41 -07002937 assert numControllers, "numControllers not defined"
2938 assert main, "main not defined"
2939 assert utilities.assert_equals, "utilities.assert_equals not defined"
2940 assert CLIs, "CLIs not defined"
2941 assert nodes, "nodes not defined"
2942
2943 # Variables for the distributed primitives tests
2944 global pCounterName
2945 global iCounterName
2946 global pCounterValue
2947 global iCounterValue
2948 global onosSet
2949 global onosSetName
2950 pCounterName = "TestON-Partitions"
2951 iCounterName = "TestON-inMemory"
2952 pCounterValue = 0
2953 iCounterValue = 0
2954 onosSet = set([])
2955 onosSetName = "TestON-set"
2956
2957 description = "Install Primitives app"
2958 main.case( description )
2959 main.step( "Install Primitives app" )
2960 appName = "org.onosproject.distributedprimitives"
2961 appResults = CLIs[0].activateApp( appName )
2962 utilities.assert_equals( expect=main.TRUE,
2963 actual=appResults,
2964 onpass="Primitives app activated",
2965 onfail="Primitives app not activated" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002966 time.sleep( 5 ) # To allow all nodes to activate
Jon Hall390696c2015-05-05 17:13:41 -07002967
2968 def CASE17( self, main ):
2969 """
2970 Check for basic functionality with distributed primitives
2971 """
Jon Hallc9eabec2015-06-10 14:33:14 -07002972 import json
Jon Hall390696c2015-05-05 17:13:41 -07002973 # Make sure variables are defined/set
2974 assert numControllers, "numControllers not defined"
2975 assert main, "main not defined"
2976 assert utilities.assert_equals, "utilities.assert_equals not defined"
2977 assert CLIs, "CLIs not defined"
2978 assert nodes, "nodes not defined"
2979 assert pCounterName, "pCounterName not defined"
2980 assert iCounterName, "iCounterName not defined"
2981 assert onosSetName, "onosSetName not defined"
2982 # NOTE: assert fails if value is 0/None/Empty/False
2983 try:
2984 pCounterValue
2985 except NameError:
2986 main.log.error( "pCounterValue not defined, setting to 0" )
2987 pCounterValue = 0
2988 try:
2989 iCounterValue
2990 except NameError:
2991 main.log.error( "iCounterValue not defined, setting to 0" )
2992 iCounterValue = 0
2993 try:
2994 onosSet
2995 except NameError:
2996 main.log.error( "onosSet not defined, setting to empty Set" )
2997 onosSet = set([])
2998 # Variables for the distributed primitives tests. These are local only
2999 addValue = "a"
3000 addAllValue = "a b c d e f"
3001 retainValue = "c d e f"
3002
3003 description = "Check for basic functionality with distributed " +\
3004 "primitives"
3005 main.case( description )
3006 main.caseExplaination = "Test the methods of the distributed primitives (counters and sets) throught the cli"
3007 # DISTRIBUTED ATOMIC COUNTERS
3008 main.step( "Increment and get a default counter on each node" )
3009 pCounters = []
3010 threads = []
Jon Hallfeff3082015-05-19 10:23:26 -07003011 addedPValues = []
Jon Hall390696c2015-05-05 17:13:41 -07003012 for i in range( numControllers ):
3013 t = main.Thread( target=CLIs[i].counterTestIncrement,
3014 name="counterIncrement-" + str( i ),
3015 args=[ pCounterName ] )
3016 pCounterValue += 1
Jon Hallfeff3082015-05-19 10:23:26 -07003017 addedPValues.append( pCounterValue )
Jon Hall390696c2015-05-05 17:13:41 -07003018 threads.append( t )
3019 t.start()
3020
3021 for t in threads:
3022 t.join()
3023 pCounters.append( t.result )
3024 # Check that counter incremented numController times
3025 pCounterResults = True
Jon Hallfeff3082015-05-19 10:23:26 -07003026 for i in addedPValues:
Jon Hall40d2cbd2015-06-03 16:24:29 -07003027 tmpResult = i in pCounters
Jon Hallfeff3082015-05-19 10:23:26 -07003028 pCounterResults = pCounterResults and tmpResult
3029 if not tmpResult:
3030 main.log.error( str( i ) + " is not in partitioned "
3031 "counter incremented results" )
Jon Hall390696c2015-05-05 17:13:41 -07003032 utilities.assert_equals( expect=True,
3033 actual=pCounterResults,
3034 onpass="Default counter incremented",
3035 onfail="Error incrementing default" +
3036 " counter" )
3037
3038 main.step( "Increment and get an in memory counter on each node" )
3039 iCounters = []
Jon Hallfeff3082015-05-19 10:23:26 -07003040 addedIValues = []
Jon Hall390696c2015-05-05 17:13:41 -07003041 threads = []
3042 for i in range( numControllers ):
3043 t = main.Thread( target=CLIs[i].counterTestIncrement,
3044 name="icounterIncrement-" + str( i ),
3045 args=[ iCounterName ],
3046 kwargs={ "inMemory": True } )
3047 iCounterValue += 1
Jon Hallfeff3082015-05-19 10:23:26 -07003048 addedIValues.append( iCounterValue )
Jon Hall390696c2015-05-05 17:13:41 -07003049 threads.append( t )
3050 t.start()
3051
3052 for t in threads:
3053 t.join()
3054 iCounters.append( t.result )
3055 # Check that counter incremented numController times
3056 iCounterResults = True
Jon Hallfeff3082015-05-19 10:23:26 -07003057 for i in addedIValues:
3058 tmpResult = i in iCounters
3059 iCounterResults = iCounterResults and tmpResult
3060 if not tmpResult:
3061 main.log.error( str( i ) + " is not in the in-memory "
3062 "counter incremented results" )
Jon Hall390696c2015-05-05 17:13:41 -07003063 utilities.assert_equals( expect=True,
3064 actual=iCounterResults,
3065 onpass="In memory counter incremented",
3066 onfail="Error incrementing in memory" +
3067 " counter" )
3068
3069 main.step( "Check counters are consistant across nodes" )
3070 onosCounters = []
3071 threads = []
3072 for i in range( numControllers ):
3073 t = main.Thread( target=CLIs[i].counters,
3074 name="counters-" + str( i ) )
3075 threads.append( t )
3076 t.start()
3077 for t in threads:
3078 t.join()
3079 onosCounters.append( t.result )
3080 tmp = [ i == onosCounters[ 0 ] for i in onosCounters ]
3081 if all( tmp ):
3082 main.log.info( "Counters are consistent across all nodes" )
3083 consistentCounterResults = main.TRUE
3084 else:
3085 main.log.error( "Counters are not consistent across all nodes" )
3086 consistentCounterResults = main.FALSE
3087 utilities.assert_equals( expect=main.TRUE,
3088 actual=consistentCounterResults,
3089 onpass="ONOS counters are consistent " +
3090 "across nodes",
3091 onfail="ONOS Counters are inconsistent " +
3092 "across nodes" )
3093
3094 main.step( "Counters we added have the correct values" )
3095 correctResults = main.TRUE
3096 for i in range( numControllers ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07003097 current = json.loads( onosCounters[i] )
3098 pValue = None
3099 iValue = None
Jon Hall390696c2015-05-05 17:13:41 -07003100 try:
Jon Hall40d2cbd2015-06-03 16:24:29 -07003101 for database in current:
3102 partitioned = database.get( 'partitionedDatabaseCounters' )
3103 if partitioned:
3104 for value in partitioned:
3105 if value.get( 'name' ) == pCounterName:
3106 pValue = value.get( 'value' )
3107 break
3108 inMemory = database.get( 'inMemoryDatabaseCounters' )
3109 if inMemory:
3110 for value in inMemory:
3111 if value.get( 'name' ) == iCounterName:
3112 iValue = value.get( 'value' )
3113 break
Jon Hall390696c2015-05-05 17:13:41 -07003114 except AttributeError, e:
3115 main.log.error( "ONOS" + str( i + 1 ) + " counters result " +
3116 "is not as expected" )
3117 correctResults = main.FALSE
Jon Hall40d2cbd2015-06-03 16:24:29 -07003118 if pValue == pCounterValue:
3119 main.log.info( "Partitioned counter value is correct" )
3120 else:
3121 main.log.error( "Partitioned counter value is incorrect," +
3122 " expected value: " + str( pCounterValue )
3123 + " current value: " + str( pValue ) )
3124 correctResults = main.FALSE
3125 if iValue == iCounterValue:
3126 main.log.info( "In memory counter value is correct" )
3127 else:
3128 main.log.error( "In memory counter value is incorrect, " +
3129 "expected value: " + str( iCounterValue ) +
3130 " current value: " + str( iValue ) )
3131 correctResults = main.FALSE
Jon Hall390696c2015-05-05 17:13:41 -07003132 utilities.assert_equals( expect=main.TRUE,
3133 actual=correctResults,
3134 onpass="Added counters are correct",
3135 onfail="Added counters are incorrect" )
3136 # DISTRIBUTED SETS
3137 main.step( "Distributed Set get" )
3138 size = len( onosSet )
3139 getResponses = []
3140 threads = []
3141 for i in range( numControllers ):
3142 t = main.Thread( target=CLIs[i].setTestGet,
3143 name="setTestGet-" + str( i ),
3144 args=[ onosSetName ] )
3145 threads.append( t )
3146 t.start()
3147 for t in threads:
3148 t.join()
3149 getResponses.append( t.result )
3150
3151 getResults = main.TRUE
3152 for i in range( numControllers ):
3153 if isinstance( getResponses[ i ], list):
3154 current = set( getResponses[ i ] )
3155 if len( current ) == len( getResponses[ i ] ):
3156 # no repeats
3157 if onosSet != current:
3158 main.log.error( "ONOS" + str( i + 1 ) +
3159 " has incorrect view" +
3160 " of set " + onosSetName + ":\n" +
3161 str( getResponses[ i ] ) )
3162 main.log.debug( "Expected: " + str( onosSet ) )
3163 main.log.debug( "Actual: " + str( current ) )
3164 getResults = main.FALSE
3165 else:
3166 # error, set is not a set
3167 main.log.error( "ONOS" + str( i + 1 ) +
3168 " has repeat elements in" +
3169 " set " + onosSetName + ":\n" +
3170 str( getResponses[ i ] ) )
3171 getResults = main.FALSE
3172 elif getResponses[ i ] == main.ERROR:
3173 getResults = main.FALSE
3174 utilities.assert_equals( expect=main.TRUE,
3175 actual=getResults,
3176 onpass="Set elements are correct",
3177 onfail="Set elements are incorrect" )
3178
3179 main.step( "Distributed Set size" )
3180 sizeResponses = []
3181 threads = []
3182 for i in range( numControllers ):
3183 t = main.Thread( target=CLIs[i].setTestSize,
3184 name="setTestSize-" + str( i ),
3185 args=[ onosSetName ] )
3186 threads.append( t )
3187 t.start()
3188 for t in threads:
3189 t.join()
3190 sizeResponses.append( t.result )
3191
3192 sizeResults = main.TRUE
3193 for i in range( numControllers ):
3194 if size != sizeResponses[ i ]:
3195 sizeResults = main.FALSE
3196 main.log.error( "ONOS" + str( i + 1 ) +
3197 " expected a size of " + str( size ) +
3198 " for set " + onosSetName +
3199 " but got " + str( sizeResponses[ i ] ) )
3200 utilities.assert_equals( expect=main.TRUE,
3201 actual=sizeResults,
3202 onpass="Set sizes are correct",
3203 onfail="Set sizes are incorrect" )
3204
3205 main.step( "Distributed Set add()" )
3206 onosSet.add( addValue )
3207 addResponses = []
3208 threads = []
3209 for i in range( numControllers ):
3210 t = main.Thread( target=CLIs[i].setTestAdd,
3211 name="setTestAdd-" + str( i ),
3212 args=[ onosSetName, addValue ] )
3213 threads.append( t )
3214 t.start()
3215 for t in threads:
3216 t.join()
3217 addResponses.append( t.result )
3218
3219 # main.TRUE = successfully changed the set
3220 # main.FALSE = action resulted in no change in set
3221 # main.ERROR - Some error in executing the function
3222 addResults = main.TRUE
3223 for i in range( numControllers ):
3224 if addResponses[ i ] == main.TRUE:
3225 # All is well
3226 pass
3227 elif addResponses[ i ] == main.FALSE:
3228 # Already in set, probably fine
3229 pass
3230 elif addResponses[ i ] == main.ERROR:
3231 # Error in execution
3232 addResults = main.FALSE
3233 else:
3234 # unexpected result
3235 addResults = main.FALSE
3236 if addResults != main.TRUE:
3237 main.log.error( "Error executing set add" )
3238
3239 # Check if set is still correct
3240 size = len( onosSet )
3241 getResponses = []
3242 threads = []
3243 for i in range( numControllers ):
3244 t = main.Thread( target=CLIs[i].setTestGet,
3245 name="setTestGet-" + str( i ),
3246 args=[ onosSetName ] )
3247 threads.append( t )
3248 t.start()
3249 for t in threads:
3250 t.join()
3251 getResponses.append( t.result )
3252 getResults = main.TRUE
3253 for i in range( numControllers ):
3254 if isinstance( getResponses[ i ], list):
3255 current = set( getResponses[ i ] )
3256 if len( current ) == len( getResponses[ i ] ):
3257 # no repeats
3258 if onosSet != current:
3259 main.log.error( "ONOS" + str( i + 1 ) +
3260 " has incorrect view" +
3261 " of set " + onosSetName + ":\n" +
3262 str( getResponses[ i ] ) )
3263 main.log.debug( "Expected: " + str( onosSet ) )
3264 main.log.debug( "Actual: " + str( current ) )
3265 getResults = main.FALSE
3266 else:
3267 # error, set is not a set
3268 main.log.error( "ONOS" + str( i + 1 ) +
3269 " has repeat elements in" +
3270 " set " + onosSetName + ":\n" +
3271 str( getResponses[ i ] ) )
3272 getResults = main.FALSE
3273 elif getResponses[ i ] == main.ERROR:
3274 getResults = main.FALSE
3275 sizeResponses = []
3276 threads = []
3277 for i in range( numControllers ):
3278 t = main.Thread( target=CLIs[i].setTestSize,
3279 name="setTestSize-" + str( i ),
3280 args=[ onosSetName ] )
3281 threads.append( t )
3282 t.start()
3283 for t in threads:
3284 t.join()
3285 sizeResponses.append( t.result )
3286 sizeResults = main.TRUE
3287 for i in range( numControllers ):
3288 if size != sizeResponses[ i ]:
3289 sizeResults = main.FALSE
3290 main.log.error( "ONOS" + str( i + 1 ) +
3291 " expected a size of " + str( size ) +
3292 " for set " + onosSetName +
3293 " but got " + str( sizeResponses[ i ] ) )
3294 addResults = addResults and getResults and sizeResults
3295 utilities.assert_equals( expect=main.TRUE,
3296 actual=addResults,
3297 onpass="Set add correct",
3298 onfail="Set add was incorrect" )
3299
3300 main.step( "Distributed Set addAll()" )
3301 onosSet.update( addAllValue.split() )
3302 addResponses = []
3303 threads = []
3304 for i in range( numControllers ):
3305 t = main.Thread( target=CLIs[i].setTestAdd,
3306 name="setTestAddAll-" + str( i ),
3307 args=[ onosSetName, addAllValue ] )
3308 threads.append( t )
3309 t.start()
3310 for t in threads:
3311 t.join()
3312 addResponses.append( t.result )
3313
3314 # main.TRUE = successfully changed the set
3315 # main.FALSE = action resulted in no change in set
3316 # main.ERROR - Some error in executing the function
3317 addAllResults = main.TRUE
3318 for i in range( numControllers ):
3319 if addResponses[ i ] == main.TRUE:
3320 # All is well
3321 pass
3322 elif addResponses[ i ] == main.FALSE:
3323 # Already in set, probably fine
3324 pass
3325 elif addResponses[ i ] == main.ERROR:
3326 # Error in execution
3327 addAllResults = main.FALSE
3328 else:
3329 # unexpected result
3330 addAllResults = main.FALSE
3331 if addAllResults != main.TRUE:
3332 main.log.error( "Error executing set addAll" )
3333
3334 # Check if set is still correct
3335 size = len( onosSet )
3336 getResponses = []
3337 threads = []
3338 for i in range( numControllers ):
3339 t = main.Thread( target=CLIs[i].setTestGet,
3340 name="setTestGet-" + str( i ),
3341 args=[ onosSetName ] )
3342 threads.append( t )
3343 t.start()
3344 for t in threads:
3345 t.join()
3346 getResponses.append( t.result )
3347 getResults = main.TRUE
3348 for i in range( numControllers ):
3349 if isinstance( getResponses[ i ], list):
3350 current = set( getResponses[ i ] )
3351 if len( current ) == len( getResponses[ i ] ):
3352 # no repeats
3353 if onosSet != current:
3354 main.log.error( "ONOS" + str( i + 1 ) +
3355 " has incorrect view" +
3356 " of set " + onosSetName + ":\n" +
3357 str( getResponses[ i ] ) )
3358 main.log.debug( "Expected: " + str( onosSet ) )
3359 main.log.debug( "Actual: " + str( current ) )
3360 getResults = main.FALSE
3361 else:
3362 # error, set is not a set
3363 main.log.error( "ONOS" + str( i + 1 ) +
3364 " has repeat elements in" +
3365 " set " + onosSetName + ":\n" +
3366 str( getResponses[ i ] ) )
3367 getResults = main.FALSE
3368 elif getResponses[ i ] == main.ERROR:
3369 getResults = main.FALSE
3370 sizeResponses = []
3371 threads = []
3372 for i in range( numControllers ):
3373 t = main.Thread( target=CLIs[i].setTestSize,
3374 name="setTestSize-" + str( i ),
3375 args=[ onosSetName ] )
3376 threads.append( t )
3377 t.start()
3378 for t in threads:
3379 t.join()
3380 sizeResponses.append( t.result )
3381 sizeResults = main.TRUE
3382 for i in range( numControllers ):
3383 if size != sizeResponses[ i ]:
3384 sizeResults = main.FALSE
3385 main.log.error( "ONOS" + str( i + 1 ) +
3386 " expected a size of " + str( size ) +
3387 " for set " + onosSetName +
3388 " but got " + str( sizeResponses[ i ] ) )
3389 addAllResults = addAllResults and getResults and sizeResults
3390 utilities.assert_equals( expect=main.TRUE,
3391 actual=addAllResults,
3392 onpass="Set addAll correct",
3393 onfail="Set addAll was incorrect" )
3394
3395 main.step( "Distributed Set contains()" )
3396 containsResponses = []
3397 threads = []
3398 for i in range( numControllers ):
3399 t = main.Thread( target=CLIs[i].setTestGet,
3400 name="setContains-" + str( i ),
3401 args=[ onosSetName ],
3402 kwargs={ "values": addValue } )
3403 threads.append( t )
3404 t.start()
3405 for t in threads:
3406 t.join()
3407 # NOTE: This is the tuple
3408 containsResponses.append( t.result )
3409
3410 containsResults = main.TRUE
3411 for i in range( numControllers ):
3412 if containsResponses[ i ] == main.ERROR:
3413 containsResults = main.FALSE
3414 else:
3415 containsResults = containsResults and\
3416 containsResponses[ i ][ 1 ]
3417 utilities.assert_equals( expect=main.TRUE,
3418 actual=containsResults,
3419 onpass="Set contains is functional",
3420 onfail="Set contains failed" )
3421
3422 main.step( "Distributed Set containsAll()" )
3423 containsAllResponses = []
3424 threads = []
3425 for i in range( numControllers ):
3426 t = main.Thread( target=CLIs[i].setTestGet,
3427 name="setContainsAll-" + str( i ),
3428 args=[ onosSetName ],
3429 kwargs={ "values": addAllValue } )
3430 threads.append( t )
3431 t.start()
3432 for t in threads:
3433 t.join()
3434 # NOTE: This is the tuple
3435 containsAllResponses.append( t.result )
3436
3437 containsAllResults = main.TRUE
3438 for i in range( numControllers ):
3439 if containsResponses[ i ] == main.ERROR:
3440 containsResults = main.FALSE
3441 else:
3442 containsResults = containsResults and\
3443 containsResponses[ i ][ 1 ]
3444 utilities.assert_equals( expect=main.TRUE,
3445 actual=containsAllResults,
3446 onpass="Set containsAll is functional",
3447 onfail="Set containsAll failed" )
3448
3449 main.step( "Distributed Set remove()" )
3450 onosSet.remove( addValue )
3451 removeResponses = []
3452 threads = []
3453 for i in range( numControllers ):
3454 t = main.Thread( target=CLIs[i].setTestRemove,
3455 name="setTestRemove-" + str( i ),
3456 args=[ onosSetName, addValue ] )
3457 threads.append( t )
3458 t.start()
3459 for t in threads:
3460 t.join()
3461 removeResponses.append( t.result )
3462
3463 # main.TRUE = successfully changed the set
3464 # main.FALSE = action resulted in no change in set
3465 # main.ERROR - Some error in executing the function
3466 removeResults = main.TRUE
3467 for i in range( numControllers ):
3468 if removeResponses[ i ] == main.TRUE:
3469 # All is well
3470 pass
3471 elif removeResponses[ i ] == main.FALSE:
3472 # not in set, probably fine
3473 pass
3474 elif removeResponses[ i ] == main.ERROR:
3475 # Error in execution
3476 removeResults = main.FALSE
3477 else:
3478 # unexpected result
3479 removeResults = main.FALSE
3480 if removeResults != main.TRUE:
3481 main.log.error( "Error executing set remove" )
3482
3483 # Check if set is still correct
3484 size = len( onosSet )
3485 getResponses = []
3486 threads = []
3487 for i in range( numControllers ):
3488 t = main.Thread( target=CLIs[i].setTestGet,
3489 name="setTestGet-" + str( i ),
3490 args=[ onosSetName ] )
3491 threads.append( t )
3492 t.start()
3493 for t in threads:
3494 t.join()
3495 getResponses.append( t.result )
3496 getResults = main.TRUE
3497 for i in range( numControllers ):
3498 if isinstance( getResponses[ i ], list):
3499 current = set( getResponses[ i ] )
3500 if len( current ) == len( getResponses[ i ] ):
3501 # no repeats
3502 if onosSet != current:
3503 main.log.error( "ONOS" + str( i + 1 ) +
3504 " has incorrect view" +
3505 " of set " + onosSetName + ":\n" +
3506 str( getResponses[ i ] ) )
3507 main.log.debug( "Expected: " + str( onosSet ) )
3508 main.log.debug( "Actual: " + str( current ) )
3509 getResults = main.FALSE
3510 else:
3511 # error, set is not a set
3512 main.log.error( "ONOS" + str( i + 1 ) +
3513 " has repeat elements in" +
3514 " set " + onosSetName + ":\n" +
3515 str( getResponses[ i ] ) )
3516 getResults = main.FALSE
3517 elif getResponses[ i ] == main.ERROR:
3518 getResults = main.FALSE
3519 sizeResponses = []
3520 threads = []
3521 for i in range( numControllers ):
3522 t = main.Thread( target=CLIs[i].setTestSize,
3523 name="setTestSize-" + str( i ),
3524 args=[ onosSetName ] )
3525 threads.append( t )
3526 t.start()
3527 for t in threads:
3528 t.join()
3529 sizeResponses.append( t.result )
3530 sizeResults = main.TRUE
3531 for i in range( numControllers ):
3532 if size != sizeResponses[ i ]:
3533 sizeResults = main.FALSE
3534 main.log.error( "ONOS" + str( i + 1 ) +
3535 " expected a size of " + str( size ) +
3536 " for set " + onosSetName +
3537 " but got " + str( sizeResponses[ i ] ) )
3538 removeResults = removeResults and getResults and sizeResults
3539 utilities.assert_equals( expect=main.TRUE,
3540 actual=removeResults,
3541 onpass="Set remove correct",
3542 onfail="Set remove was incorrect" )
3543
3544 main.step( "Distributed Set removeAll()" )
3545 onosSet.difference_update( addAllValue.split() )
3546 removeAllResponses = []
3547 threads = []
3548 try:
3549 for i in range( numControllers ):
3550 t = main.Thread( target=CLIs[i].setTestRemove,
3551 name="setTestRemoveAll-" + str( i ),
3552 args=[ onosSetName, addAllValue ] )
3553 threads.append( t )
3554 t.start()
3555 for t in threads:
3556 t.join()
3557 removeAllResponses.append( t.result )
3558 except Exception, e:
3559 main.log.exception(e)
3560
3561 # main.TRUE = successfully changed the set
3562 # main.FALSE = action resulted in no change in set
3563 # main.ERROR - Some error in executing the function
3564 removeAllResults = main.TRUE
3565 for i in range( numControllers ):
3566 if removeAllResponses[ i ] == main.TRUE:
3567 # All is well
3568 pass
3569 elif removeAllResponses[ i ] == main.FALSE:
3570 # not in set, probably fine
3571 pass
3572 elif removeAllResponses[ i ] == main.ERROR:
3573 # Error in execution
3574 removeAllResults = main.FALSE
3575 else:
3576 # unexpected result
3577 removeAllResults = main.FALSE
3578 if removeAllResults != main.TRUE:
3579 main.log.error( "Error executing set removeAll" )
3580
3581 # Check if set is still correct
3582 size = len( onosSet )
3583 getResponses = []
3584 threads = []
3585 for i in range( numControllers ):
3586 t = main.Thread( target=CLIs[i].setTestGet,
3587 name="setTestGet-" + str( i ),
3588 args=[ onosSetName ] )
3589 threads.append( t )
3590 t.start()
3591 for t in threads:
3592 t.join()
3593 getResponses.append( t.result )
3594 getResults = main.TRUE
3595 for i in range( numControllers ):
3596 if isinstance( getResponses[ i ], list):
3597 current = set( getResponses[ i ] )
3598 if len( current ) == len( getResponses[ i ] ):
3599 # no repeats
3600 if onosSet != current:
3601 main.log.error( "ONOS" + str( i + 1 ) +
3602 " has incorrect view" +
3603 " of set " + onosSetName + ":\n" +
3604 str( getResponses[ i ] ) )
3605 main.log.debug( "Expected: " + str( onosSet ) )
3606 main.log.debug( "Actual: " + str( current ) )
3607 getResults = main.FALSE
3608 else:
3609 # error, set is not a set
3610 main.log.error( "ONOS" + str( i + 1 ) +
3611 " has repeat elements in" +
3612 " set " + onosSetName + ":\n" +
3613 str( getResponses[ i ] ) )
3614 getResults = main.FALSE
3615 elif getResponses[ i ] == main.ERROR:
3616 getResults = main.FALSE
3617 sizeResponses = []
3618 threads = []
3619 for i in range( numControllers ):
3620 t = main.Thread( target=CLIs[i].setTestSize,
3621 name="setTestSize-" + str( i ),
3622 args=[ onosSetName ] )
3623 threads.append( t )
3624 t.start()
3625 for t in threads:
3626 t.join()
3627 sizeResponses.append( t.result )
3628 sizeResults = main.TRUE
3629 for i in range( numControllers ):
3630 if size != sizeResponses[ i ]:
3631 sizeResults = main.FALSE
3632 main.log.error( "ONOS" + str( i + 1 ) +
3633 " expected a size of " + str( size ) +
3634 " for set " + onosSetName +
3635 " but got " + str( sizeResponses[ i ] ) )
3636 removeAllResults = removeAllResults and getResults and sizeResults
3637 utilities.assert_equals( expect=main.TRUE,
3638 actual=removeAllResults,
3639 onpass="Set removeAll correct",
3640 onfail="Set removeAll was incorrect" )
3641
3642 main.step( "Distributed Set addAll()" )
3643 onosSet.update( addAllValue.split() )
3644 addResponses = []
3645 threads = []
3646 for i in range( numControllers ):
3647 t = main.Thread( target=CLIs[i].setTestAdd,
3648 name="setTestAddAll-" + str( i ),
3649 args=[ onosSetName, addAllValue ] )
3650 threads.append( t )
3651 t.start()
3652 for t in threads:
3653 t.join()
3654 addResponses.append( t.result )
3655
3656 # main.TRUE = successfully changed the set
3657 # main.FALSE = action resulted in no change in set
3658 # main.ERROR - Some error in executing the function
3659 addAllResults = main.TRUE
3660 for i in range( numControllers ):
3661 if addResponses[ i ] == main.TRUE:
3662 # All is well
3663 pass
3664 elif addResponses[ i ] == main.FALSE:
3665 # Already in set, probably fine
3666 pass
3667 elif addResponses[ i ] == main.ERROR:
3668 # Error in execution
3669 addAllResults = main.FALSE
3670 else:
3671 # unexpected result
3672 addAllResults = main.FALSE
3673 if addAllResults != main.TRUE:
3674 main.log.error( "Error executing set addAll" )
3675
3676 # Check if set is still correct
3677 size = len( onosSet )
3678 getResponses = []
3679 threads = []
3680 for i in range( numControllers ):
3681 t = main.Thread( target=CLIs[i].setTestGet,
3682 name="setTestGet-" + str( i ),
3683 args=[ onosSetName ] )
3684 threads.append( t )
3685 t.start()
3686 for t in threads:
3687 t.join()
3688 getResponses.append( t.result )
3689 getResults = main.TRUE
3690 for i in range( numControllers ):
3691 if isinstance( getResponses[ i ], list):
3692 current = set( getResponses[ i ] )
3693 if len( current ) == len( getResponses[ i ] ):
3694 # no repeats
3695 if onosSet != current:
3696 main.log.error( "ONOS" + str( i + 1 ) +
3697 " has incorrect view" +
3698 " of set " + onosSetName + ":\n" +
3699 str( getResponses[ i ] ) )
3700 main.log.debug( "Expected: " + str( onosSet ) )
3701 main.log.debug( "Actual: " + str( current ) )
3702 getResults = main.FALSE
3703 else:
3704 # error, set is not a set
3705 main.log.error( "ONOS" + str( i + 1 ) +
3706 " has repeat elements in" +
3707 " set " + onosSetName + ":\n" +
3708 str( getResponses[ i ] ) )
3709 getResults = main.FALSE
3710 elif getResponses[ i ] == main.ERROR:
3711 getResults = main.FALSE
3712 sizeResponses = []
3713 threads = []
3714 for i in range( numControllers ):
3715 t = main.Thread( target=CLIs[i].setTestSize,
3716 name="setTestSize-" + str( i ),
3717 args=[ onosSetName ] )
3718 threads.append( t )
3719 t.start()
3720 for t in threads:
3721 t.join()
3722 sizeResponses.append( t.result )
3723 sizeResults = main.TRUE
3724 for i in range( numControllers ):
3725 if size != sizeResponses[ i ]:
3726 sizeResults = main.FALSE
3727 main.log.error( "ONOS" + str( i + 1 ) +
3728 " expected a size of " + str( size ) +
3729 " for set " + onosSetName +
3730 " but got " + str( sizeResponses[ i ] ) )
3731 addAllResults = addAllResults and getResults and sizeResults
3732 utilities.assert_equals( expect=main.TRUE,
3733 actual=addAllResults,
3734 onpass="Set addAll correct",
3735 onfail="Set addAll was incorrect" )
3736
3737 main.step( "Distributed Set clear()" )
3738 onosSet.clear()
3739 clearResponses = []
3740 threads = []
3741 for i in range( numControllers ):
3742 t = main.Thread( target=CLIs[i].setTestRemove,
3743 name="setTestClear-" + str( i ),
3744 args=[ onosSetName, " "], # Values doesn't matter
3745 kwargs={ "clear": True } )
3746 threads.append( t )
3747 t.start()
3748 for t in threads:
3749 t.join()
3750 clearResponses.append( t.result )
3751
3752 # main.TRUE = successfully changed the set
3753 # main.FALSE = action resulted in no change in set
3754 # main.ERROR - Some error in executing the function
3755 clearResults = main.TRUE
3756 for i in range( numControllers ):
3757 if clearResponses[ i ] == main.TRUE:
3758 # All is well
3759 pass
3760 elif clearResponses[ i ] == main.FALSE:
3761 # Nothing set, probably fine
3762 pass
3763 elif clearResponses[ i ] == main.ERROR:
3764 # Error in execution
3765 clearResults = main.FALSE
3766 else:
3767 # unexpected result
3768 clearResults = main.FALSE
3769 if clearResults != main.TRUE:
3770 main.log.error( "Error executing set clear" )
3771
3772 # Check if set is still correct
3773 size = len( onosSet )
3774 getResponses = []
3775 threads = []
3776 for i in range( numControllers ):
3777 t = main.Thread( target=CLIs[i].setTestGet,
3778 name="setTestGet-" + str( i ),
3779 args=[ onosSetName ] )
3780 threads.append( t )
3781 t.start()
3782 for t in threads:
3783 t.join()
3784 getResponses.append( t.result )
3785 getResults = main.TRUE
3786 for i in range( numControllers ):
3787 if isinstance( getResponses[ i ], list):
3788 current = set( getResponses[ i ] )
3789 if len( current ) == len( getResponses[ i ] ):
3790 # no repeats
3791 if onosSet != current:
3792 main.log.error( "ONOS" + str( i + 1 ) +
3793 " has incorrect view" +
3794 " of set " + onosSetName + ":\n" +
3795 str( getResponses[ i ] ) )
3796 main.log.debug( "Expected: " + str( onosSet ) )
3797 main.log.debug( "Actual: " + str( current ) )
3798 getResults = main.FALSE
3799 else:
3800 # error, set is not a set
3801 main.log.error( "ONOS" + str( i + 1 ) +
3802 " has repeat elements in" +
3803 " set " + onosSetName + ":\n" +
3804 str( getResponses[ i ] ) )
3805 getResults = main.FALSE
3806 elif getResponses[ i ] == main.ERROR:
3807 getResults = main.FALSE
3808 sizeResponses = []
3809 threads = []
3810 for i in range( numControllers ):
3811 t = main.Thread( target=CLIs[i].setTestSize,
3812 name="setTestSize-" + str( i ),
3813 args=[ onosSetName ] )
3814 threads.append( t )
3815 t.start()
3816 for t in threads:
3817 t.join()
3818 sizeResponses.append( t.result )
3819 sizeResults = main.TRUE
3820 for i in range( numControllers ):
3821 if size != sizeResponses[ i ]:
3822 sizeResults = main.FALSE
3823 main.log.error( "ONOS" + str( i + 1 ) +
3824 " expected a size of " + str( size ) +
3825 " for set " + onosSetName +
3826 " but got " + str( sizeResponses[ i ] ) )
3827 clearResults = clearResults and getResults and sizeResults
3828 utilities.assert_equals( expect=main.TRUE,
3829 actual=clearResults,
3830 onpass="Set clear correct",
3831 onfail="Set clear was incorrect" )
3832
3833 main.step( "Distributed Set addAll()" )
3834 onosSet.update( addAllValue.split() )
3835 addResponses = []
3836 threads = []
3837 for i in range( numControllers ):
3838 t = main.Thread( target=CLIs[i].setTestAdd,
3839 name="setTestAddAll-" + str( i ),
3840 args=[ onosSetName, addAllValue ] )
3841 threads.append( t )
3842 t.start()
3843 for t in threads:
3844 t.join()
3845 addResponses.append( t.result )
3846
3847 # main.TRUE = successfully changed the set
3848 # main.FALSE = action resulted in no change in set
3849 # main.ERROR - Some error in executing the function
3850 addAllResults = main.TRUE
3851 for i in range( numControllers ):
3852 if addResponses[ i ] == main.TRUE:
3853 # All is well
3854 pass
3855 elif addResponses[ i ] == main.FALSE:
3856 # Already in set, probably fine
3857 pass
3858 elif addResponses[ i ] == main.ERROR:
3859 # Error in execution
3860 addAllResults = main.FALSE
3861 else:
3862 # unexpected result
3863 addAllResults = main.FALSE
3864 if addAllResults != main.TRUE:
3865 main.log.error( "Error executing set addAll" )
3866
3867 # Check if set is still correct
3868 size = len( onosSet )
3869 getResponses = []
3870 threads = []
3871 for i in range( numControllers ):
3872 t = main.Thread( target=CLIs[i].setTestGet,
3873 name="setTestGet-" + str( i ),
3874 args=[ onosSetName ] )
3875 threads.append( t )
3876 t.start()
3877 for t in threads:
3878 t.join()
3879 getResponses.append( t.result )
3880 getResults = main.TRUE
3881 for i in range( numControllers ):
3882 if isinstance( getResponses[ i ], list):
3883 current = set( getResponses[ i ] )
3884 if len( current ) == len( getResponses[ i ] ):
3885 # no repeats
3886 if onosSet != current:
3887 main.log.error( "ONOS" + str( i + 1 ) +
3888 " has incorrect view" +
3889 " of set " + onosSetName + ":\n" +
3890 str( getResponses[ i ] ) )
3891 main.log.debug( "Expected: " + str( onosSet ) )
3892 main.log.debug( "Actual: " + str( current ) )
3893 getResults = main.FALSE
3894 else:
3895 # error, set is not a set
3896 main.log.error( "ONOS" + str( i + 1 ) +
3897 " has repeat elements in" +
3898 " set " + onosSetName + ":\n" +
3899 str( getResponses[ i ] ) )
3900 getResults = main.FALSE
3901 elif getResponses[ i ] == main.ERROR:
3902 getResults = main.FALSE
3903 sizeResponses = []
3904 threads = []
3905 for i in range( numControllers ):
3906 t = main.Thread( target=CLIs[i].setTestSize,
3907 name="setTestSize-" + str( i ),
3908 args=[ onosSetName ] )
3909 threads.append( t )
3910 t.start()
3911 for t in threads:
3912 t.join()
3913 sizeResponses.append( t.result )
3914 sizeResults = main.TRUE
3915 for i in range( numControllers ):
3916 if size != sizeResponses[ i ]:
3917 sizeResults = main.FALSE
3918 main.log.error( "ONOS" + str( i + 1 ) +
3919 " expected a size of " + str( size ) +
3920 " for set " + onosSetName +
3921 " but got " + str( sizeResponses[ i ] ) )
3922 addAllResults = addAllResults and getResults and sizeResults
3923 utilities.assert_equals( expect=main.TRUE,
3924 actual=addAllResults,
3925 onpass="Set addAll correct",
3926 onfail="Set addAll was incorrect" )
3927
3928 main.step( "Distributed Set retain()" )
3929 onosSet.intersection_update( retainValue.split() )
3930 retainResponses = []
3931 threads = []
3932 for i in range( numControllers ):
3933 t = main.Thread( target=CLIs[i].setTestRemove,
3934 name="setTestRetain-" + str( i ),
3935 args=[ onosSetName, retainValue ],
3936 kwargs={ "retain": True } )
3937 threads.append( t )
3938 t.start()
3939 for t in threads:
3940 t.join()
3941 retainResponses.append( t.result )
3942
3943 # main.TRUE = successfully changed the set
3944 # main.FALSE = action resulted in no change in set
3945 # main.ERROR - Some error in executing the function
3946 retainResults = main.TRUE
3947 for i in range( numControllers ):
3948 if retainResponses[ i ] == main.TRUE:
3949 # All is well
3950 pass
3951 elif retainResponses[ i ] == main.FALSE:
3952 # Already in set, probably fine
3953 pass
3954 elif retainResponses[ i ] == main.ERROR:
3955 # Error in execution
3956 retainResults = main.FALSE
3957 else:
3958 # unexpected result
3959 retainResults = main.FALSE
3960 if retainResults != main.TRUE:
3961 main.log.error( "Error executing set retain" )
3962
3963 # Check if set is still correct
3964 size = len( onosSet )
3965 getResponses = []
3966 threads = []
3967 for i in range( numControllers ):
3968 t = main.Thread( target=CLIs[i].setTestGet,
3969 name="setTestGet-" + str( i ),
3970 args=[ onosSetName ] )
3971 threads.append( t )
3972 t.start()
3973 for t in threads:
3974 t.join()
3975 getResponses.append( t.result )
3976 getResults = main.TRUE
3977 for i in range( numControllers ):
3978 if isinstance( getResponses[ i ], list):
3979 current = set( getResponses[ i ] )
3980 if len( current ) == len( getResponses[ i ] ):
3981 # no repeats
3982 if onosSet != current:
3983 main.log.error( "ONOS" + str( i + 1 ) +
3984 " has incorrect view" +
3985 " of set " + onosSetName + ":\n" +
3986 str( getResponses[ i ] ) )
3987 main.log.debug( "Expected: " + str( onosSet ) )
3988 main.log.debug( "Actual: " + str( current ) )
3989 getResults = main.FALSE
3990 else:
3991 # error, set is not a set
3992 main.log.error( "ONOS" + str( i + 1 ) +
3993 " has repeat elements in" +
3994 " set " + onosSetName + ":\n" +
3995 str( getResponses[ i ] ) )
3996 getResults = main.FALSE
3997 elif getResponses[ i ] == main.ERROR:
3998 getResults = main.FALSE
3999 sizeResponses = []
4000 threads = []
4001 for i in range( numControllers ):
4002 t = main.Thread( target=CLIs[i].setTestSize,
4003 name="setTestSize-" + str( i ),
4004 args=[ onosSetName ] )
4005 threads.append( t )
4006 t.start()
4007 for t in threads:
4008 t.join()
4009 sizeResponses.append( t.result )
4010 sizeResults = main.TRUE
4011 for i in range( numControllers ):
4012 if size != sizeResponses[ i ]:
4013 sizeResults = main.FALSE
4014 main.log.error( "ONOS" + str( i + 1 ) +
4015 " expected a size of " +
4016 str( size ) + " for set " + onosSetName +
4017 " but got " + str( sizeResponses[ i ] ) )
4018 retainResults = retainResults and getResults and sizeResults
4019 utilities.assert_equals( expect=main.TRUE,
4020 actual=retainResults,
4021 onpass="Set retain correct",
4022 onfail="Set retain was incorrect" )
4023