blob: 08d81c26f2fc4d19f2a3414ac18bbbcf27d9a998 [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 a minority 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 HATestMinorityRestart:
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 minority of ONOS nodes - " +
Jon Hall390696c2015-05-05 17:13:41 -070051 "initialization" )
Jon Hall6aec96b2015-01-19 14:49:31 -080052 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 Hall8f89dda2015-01-22 16:03:33 -080074 numControllers = int( main.params[ 'num_controllers' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -080075
Jon Hall5cfd23c2015-03-19 11:40:57 -070076 # FIXME: just get controller port from params?
77 # TODO: do we really need all these?
78 ONOS1Port = main.params[ 'CTRL' ][ 'port1' ]
79 ONOS2Port = main.params[ 'CTRL' ][ 'port2' ]
80 ONOS3Port = main.params[ 'CTRL' ][ 'port3' ]
81 ONOS4Port = main.params[ 'CTRL' ][ 'port4' ]
82 ONOS5Port = main.params[ 'CTRL' ][ 'port5' ]
83 ONOS6Port = main.params[ 'CTRL' ][ 'port6' ]
84 ONOS7Port = main.params[ 'CTRL' ][ 'port7' ]
85
86 global CLIs
87 CLIs = []
88 global nodes
89 nodes = []
90 for i in range( 1, numControllers + 1 ):
91 CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
92 nodes.append( getattr( main, 'ONOS' + str( i ) ) )
93
Jon Hall6aec96b2015-01-19 14:49:31 -080094 main.step( "Applying cell variable to environment" )
Jon Hall8f89dda2015-01-22 16:03:33 -080095 cellResult = main.ONOSbench.setCell( cellName )
96 verifyResult = main.ONOSbench.verifyCell()
Jon Hall73cf9cc2014-11-20 22:28:38 -080097
Jon Hall6aec96b2015-01-19 14:49:31 -080098 # FIXME:this is short term fix
Jon Hall40d2cbd2015-06-03 16:24:29 -070099 main.log.info( "Removing raft logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -0800100 main.ONOSbench.onosRemoveRaftLogs()
Jon Hall5cfd23c2015-03-19 11:40:57 -0700101
Jon Hall40d2cbd2015-06-03 16:24:29 -0700102 main.log.info( "Uninstalling ONOS" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700103 for node in nodes:
104 main.ONOSbench.onosUninstall( node.ip_address )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800105
Jon Hall390696c2015-05-05 17:13:41 -0700106 # Make sure ONOS is DEAD
Jon Hall40d2cbd2015-06-03 16:24:29 -0700107 main.log.info( "Killing any ONOS processes" )
Jon Hall390696c2015-05-05 17:13:41 -0700108 killResults = main.TRUE
109 for node in nodes:
110 killed = main.ONOSbench.onosKill( node.ip_address )
111 killResults = killResults and killed
112
Jon Hall8f89dda2015-01-22 16:03:33 -0800113 cleanInstallResult = main.TRUE
114 gitPullResult = main.TRUE
Jon Hall73cf9cc2014-11-20 22:28:38 -0800115
Jon Hall97f31752015-02-04 12:01:04 -0800116 main.step( "Starting Mininet" )
Jon Hall390696c2015-05-05 17:13:41 -0700117 mnResult = main.Mininet1.startNet( )
118 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
119 onpass="Mininet Started",
120 onfail="Error starting Mininet" )
Jon Hall97f31752015-02-04 12:01:04 -0800121
Jon Hallfeff3082015-05-19 10:23:26 -0700122 main.step( "Git checkout and pull " + gitBranch )
Jon Hall8f89dda2015-01-22 16:03:33 -0800123 if PULLCODE:
Jon Hall529a37f2015-01-28 10:02:00 -0800124 main.ONOSbench.gitCheckout( gitBranch )
Jon Hall8f89dda2015-01-22 16:03:33 -0800125 gitPullResult = main.ONOSbench.gitPull()
Jon Hall390696c2015-05-05 17:13:41 -0700126 # values of 1 or 3 are good
127 utilities.assert_lesser( expect=0, actual=gitPullResult,
128 onpass="Git pull successful",
129 onfail="Git pull failed" )
Jon Hall8f89dda2015-01-22 16:03:33 -0800130 main.ONOSbench.getVersion( report=True )
Jon Hallfeff3082015-05-19 10:23:26 -0700131
132 main.step( "Using mvn clean install" )
133 cleanInstallResult = main.TRUE
Jon Hall40d2cbd2015-06-03 16:24:29 -0700134 if PULLCODE and gitPullResult == main.TRUE:
Jon Hallfeff3082015-05-19 10:23:26 -0700135 cleanInstallResult = main.ONOSbench.cleanInstall()
Jon Hall40d2cbd2015-06-03 16:24:29 -0700136 else:
137 main.log.warn( "Did not pull new code so skipping mvn " +
138 "clean install" )
Jon Hallfeff3082015-05-19 10:23:26 -0700139 utilities.assert_equals( expect=main.TRUE,
140 actual=cleanInstallResult,
141 onpass="MCI successful",
142 onfail="MCI failed" )
Jon Hall390696c2015-05-05 17:13:41 -0700143 # GRAPHS
144 # NOTE: important params here:
145 # job = name of Jenkins job
146 # Plot Name = Plot-HA, only can be used if multiple plots
147 # index = The number of the graph under plot name
148 job = "HAMinorityRestart"
Jon Hall40d2cbd2015-06-03 16:24:29 -0700149 plotName = "Plot-HA"
Jon Hall390696c2015-05-05 17:13:41 -0700150 graphs = '<ac:structured-macro ac:name="html">\n'
151 graphs += '<ac:plain-text-body><![CDATA[\n'
152 graphs += '<iframe src="https://onos-jenkins.onlab.us/job/' + job +\
Jon Hall40d2cbd2015-06-03 16:24:29 -0700153 '/plot/' + plotName + '/getPlot?index=0' +\
154 '&width=500&height=300"' +\
Jon Hall390696c2015-05-05 17:13:41 -0700155 'noborder="0" width="500" height="300" scrolling="yes" ' +\
156 'seamless="seamless"></iframe>\n'
157 graphs += ']]></ac:plain-text-body>\n'
158 graphs += '</ac:structured-macro>\n'
159 main.log.wiki(graphs)
Jon Hall73cf9cc2014-11-20 22:28:38 -0800160
Jon Hall6aec96b2015-01-19 14:49:31 -0800161 main.step( "Creating ONOS package" )
Jon Hall8f89dda2015-01-22 16:03:33 -0800162 packageResult = main.ONOSbench.onosPackage()
Jon Hall390696c2015-05-05 17:13:41 -0700163 utilities.assert_equals( expect=main.TRUE, actual=packageResult,
164 onpass="ONOS package successful",
165 onfail="ONOS package failed" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800166
Jon Hall6aec96b2015-01-19 14:49:31 -0800167 main.step( "Installing ONOS package" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700168 onosInstallResult = main.TRUE
169 for node in nodes:
170 tmpResult = main.ONOSbench.onosInstall( options="-f",
171 node=node.ip_address )
172 onosInstallResult = onosInstallResult and tmpResult
Jon Hall390696c2015-05-05 17:13:41 -0700173 utilities.assert_equals( expect=main.TRUE, actual=onosInstallResult,
174 onpass="ONOS install successful",
175 onfail="ONOS install failed" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800176
Jon Hall6aec96b2015-01-19 14:49:31 -0800177 main.step( "Checking if ONOS is up yet" )
Jon Hall6aec96b2015-01-19 14:49:31 -0800178 for i in range( 2 ):
Jon Hall5cfd23c2015-03-19 11:40:57 -0700179 onosIsupResult = main.TRUE
180 for node in nodes:
181 started = main.ONOSbench.isup( node.ip_address )
182 if not started:
Jon Hall40d2cbd2015-06-03 16:24:29 -0700183 main.log.error( node.name + " didn't start!" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700184 main.ONOSbench.onosStop( node.ip_address )
185 main.ONOSbench.onosStart( node.ip_address )
186 onosIsupResult = onosIsupResult and started
Jon Hall8f89dda2015-01-22 16:03:33 -0800187 if onosIsupResult == main.TRUE:
Jon Hall94fd0472014-12-08 11:52:42 -0800188 break
Jon Hall390696c2015-05-05 17:13:41 -0700189 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
190 onpass="ONOS startup successful",
191 onfail="ONOS startup failed" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800192
Jon Hall5cfd23c2015-03-19 11:40:57 -0700193 main.log.step( "Starting ONOS CLI sessions" )
194 cliResults = main.TRUE
195 threads = []
196 for i in range( numControllers ):
197 t = main.Thread( target=CLIs[i].startOnosCli,
198 name="startOnosCli-" + str( i ),
199 args=[nodes[i].ip_address] )
200 threads.append( t )
201 t.start()
202
203 for t in threads:
204 t.join()
205 cliResults = cliResults and t.result
Jon Hall390696c2015-05-05 17:13:41 -0700206 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
207 onpass="ONOS cli startup successful",
208 onfail="ONOS cli startup failed" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800209
Jon Hall40d2cbd2015-06-03 16:24:29 -0700210 if main.params[ 'tcpdump' ].lower() == "true":
211 main.step( "Start Packet Capture MN" )
212 main.Mininet2.startTcpdump(
213 str( main.params[ 'MNtcpdump' ][ 'folder' ] ) + str( main.TEST )
214 + "-MN.pcap",
215 intf=main.params[ 'MNtcpdump' ][ 'intf' ],
216 port=main.params[ 'MNtcpdump' ][ 'port' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800217
Jon Hall390696c2015-05-05 17:13:41 -0700218 main.step( "App Ids check" )
Jon Halla9d26da2015-03-30 16:45:32 -0700219 appCheck = main.TRUE
220 threads = []
221 for i in range( numControllers ):
222 t = main.Thread( target=CLIs[i].appToIDCheck,
223 name="appToIDCheck-" + str( i ),
224 args=[] )
225 threads.append( t )
226 t.start()
227
228 for t in threads:
229 t.join()
230 appCheck = appCheck and t.result
Jon Halla9d26da2015-03-30 16:45:32 -0700231 if appCheck != main.TRUE:
232 main.log.warn( CLIs[0].apps() )
233 main.log.warn( CLIs[0].appIDs() )
Jon Hall390696c2015-05-05 17:13:41 -0700234 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
235 onpass="App Ids seem to be correct",
236 onfail="Something is wrong with app Ids" )
Jon Halla9d26da2015-03-30 16:45:32 -0700237
Jon Hallfeff3082015-05-19 10:23:26 -0700238 if cliResults == main.FALSE:
239 main.log.error( "Failed to start ONOS, stopping test" )
Jon Hall94fd0472014-12-08 11:52:42 -0800240 main.cleanup()
241 main.exit()
Jon Hall73cf9cc2014-11-20 22:28:38 -0800242
Jon Hall6aec96b2015-01-19 14:49:31 -0800243 def CASE2( self, main ):
244 """
Jon Hallc9eabec2015-06-10 14:33:14 -0700245 Assign devices to controllers
Jon Hall6aec96b2015-01-19 14:49:31 -0800246 """
Jon Hall73cf9cc2014-11-20 22:28:38 -0800247 import re
Jon Hall390696c2015-05-05 17:13:41 -0700248 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -0700249 assert numControllers, "numControllers not defined"
250 assert main, "main not defined"
251 assert utilities.assert_equals, "utilities.assert_equals not defined"
252 assert CLIs, "CLIs not defined"
253 assert nodes, "nodes not defined"
254 assert ONOS1Port, "ONOS1Port not defined"
255 assert ONOS2Port, "ONOS2Port not defined"
256 assert ONOS3Port, "ONOS3Port not defined"
257 assert ONOS4Port, "ONOS4Port not defined"
258 assert ONOS5Port, "ONOS5Port not defined"
259 assert ONOS6Port, "ONOS6Port not defined"
260 assert ONOS7Port, "ONOS7Port not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -0800261
Jon Hallc9eabec2015-06-10 14:33:14 -0700262 main.case( "Assigning devices to controllers" )
Jon Hallfeff3082015-05-19 10:23:26 -0700263 main.caseExplaination = "Assign switches to ONOS using 'ovs-vsctl' " +\
264 "and check that an ONOS node becomes the " +\
Jon Hallc9eabec2015-06-10 14:33:14 -0700265 "master of the device."
Jon Hall6aec96b2015-01-19 14:49:31 -0800266 main.step( "Assign switches to controllers" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800267
Jon Hall5cfd23c2015-03-19 11:40:57 -0700268 # TODO: rewrite this function to take lists of ips and ports?
269 # or list of tuples?
Jon Hall6aec96b2015-01-19 14:49:31 -0800270 for i in range( 1, 29 ):
Jon Hall8f89dda2015-01-22 16:03:33 -0800271 main.Mininet1.assignSwController(
Jon Hall6aec96b2015-01-19 14:49:31 -0800272 sw=str( i ),
Jon Hall8f89dda2015-01-22 16:03:33 -0800273 count=numControllers,
Jon Hall5cfd23c2015-03-19 11:40:57 -0700274 ip1=nodes[ 0 ].ip_address, port1=ONOS1Port,
275 ip2=nodes[ 1 ].ip_address, port2=ONOS2Port,
276 ip3=nodes[ 2 ].ip_address, port3=ONOS3Port,
277 ip4=nodes[ 3 ].ip_address, port4=ONOS4Port,
278 ip5=nodes[ 4 ].ip_address, port5=ONOS5Port,
279 ip6=nodes[ 5 ].ip_address, port6=ONOS6Port,
280 ip7=nodes[ 6 ].ip_address, port7=ONOS7Port )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800281
Jon Hall8f89dda2015-01-22 16:03:33 -0800282 mastershipCheck = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -0800283 for i in range( 1, 29 ):
Jon Hall8f89dda2015-01-22 16:03:33 -0800284 response = main.Mininet1.getSwController( "s" + str( i ) )
Jon Hallffb386d2014-11-21 13:43:38 -0800285 try:
Jon Hall6aec96b2015-01-19 14:49:31 -0800286 main.log.info( str( response ) )
Jon Hallfebb1c72015-03-05 13:30:09 -0800287 except Exception:
Jon Hall6aec96b2015-01-19 14:49:31 -0800288 main.log.info( repr( response ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700289 for node in nodes:
290 if re.search( "tcp:" + node.ip_address, response ):
291 mastershipCheck = mastershipCheck and main.TRUE
292 else:
Jon Halla9d26da2015-03-30 16:45:32 -0700293 main.log.error( "Error, node " + node.ip_address + " is " +
294 "not in the list of controllers s" +
295 str( i ) + " is connecting to." )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700296 mastershipCheck = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -0800297 utilities.assert_equals(
298 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800299 actual=mastershipCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -0800300 onpass="Switch mastership assigned correctly",
301 onfail="Switches not assigned correctly to controllers" )
Jon Hall390696c2015-05-05 17:13:41 -0700302
Jon Hallc9eabec2015-06-10 14:33:14 -0700303 def CASE21( self, main ):
304 """
305 Assign mastership to controllers
306 """
307 import re
308 import time
309 assert numControllers, "numControllers not defined"
310 assert main, "main not defined"
311 assert utilities.assert_equals, "utilities.assert_equals not defined"
312 assert CLIs, "CLIs not defined"
313 assert nodes, "nodes not defined"
314 assert ONOS1Port, "ONOS1Port not defined"
315 assert ONOS2Port, "ONOS2Port not defined"
316 assert ONOS3Port, "ONOS3Port not defined"
317 assert ONOS4Port, "ONOS4Port not defined"
318 assert ONOS5Port, "ONOS5Port not defined"
319 assert ONOS6Port, "ONOS6Port not defined"
320 assert ONOS7Port, "ONOS7Port not defined"
321
322 main.case( "Assigning Controller roles for switches" )
323 main.caseExplaination = "Check that ONOS is connected to each " +\
324 "device. Then manually assign" +\
325 " mastership to specific ONOS nodes using" +\
326 " 'device-role'"
Jon Hall390696c2015-05-05 17:13:41 -0700327 main.step( "Assign mastership of switches to specific controllers" )
Jon Hall6aec96b2015-01-19 14:49:31 -0800328 # Manually assign mastership to the controller we want
Jon Hall8f89dda2015-01-22 16:03:33 -0800329 roleCall = main.TRUE
Jon Hall390696c2015-05-05 17:13:41 -0700330
331 ipList = [ ]
332 deviceList = []
Jon Hall58c76b72015-02-23 11:09:24 -0800333 try:
Jon Halla9d26da2015-03-30 16:45:32 -0700334 for i in range( 1, 29 ): # switches 1 through 28
335 # set up correct variables:
336 if i == 1:
337 ip = nodes[ 0 ].ip_address # ONOS1
338 deviceId = main.ONOScli1.getDevice( "1000" ).get( 'id' )
339 elif i == 2:
340 ip = nodes[ 1 ].ip_address # ONOS2
341 deviceId = main.ONOScli1.getDevice( "2000" ).get( 'id' )
342 elif i == 3:
343 ip = nodes[ 1 ].ip_address # ONOS2
344 deviceId = main.ONOScli1.getDevice( "3000" ).get( 'id' )
345 elif i == 4:
346 ip = nodes[ 3 ].ip_address # ONOS4
347 deviceId = main.ONOScli1.getDevice( "3004" ).get( 'id' )
348 elif i == 5:
349 ip = nodes[ 2 ].ip_address # ONOS3
350 deviceId = main.ONOScli1.getDevice( "5000" ).get( 'id' )
351 elif i == 6:
352 ip = nodes[ 2 ].ip_address # ONOS3
353 deviceId = main.ONOScli1.getDevice( "6000" ).get( 'id' )
354 elif i == 7:
355 ip = nodes[ 5 ].ip_address # ONOS6
356 deviceId = main.ONOScli1.getDevice( "6007" ).get( 'id' )
357 elif i >= 8 and i <= 17:
358 ip = nodes[ 4 ].ip_address # ONOS5
359 dpid = '3' + str( i ).zfill( 3 )
360 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
361 elif i >= 18 and i <= 27:
362 ip = nodes[ 6 ].ip_address # ONOS7
363 dpid = '6' + str( i ).zfill( 3 )
364 deviceId = main.ONOScli1.getDevice( dpid ).get( 'id' )
365 elif i == 28:
366 ip = nodes[ 0 ].ip_address # ONOS1
367 deviceId = main.ONOScli1.getDevice( "2800" ).get( 'id' )
368 else:
369 main.log.error( "You didn't write an else statement for " +
370 "switch s" + str( i ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700371 roleCall = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -0700372 # Assign switch
373 assert deviceId, "No device id for s" + str( i ) + " in ONOS"
374 # TODO: make this controller dynamic
375 roleCall = roleCall and main.ONOScli1.deviceRole( deviceId,
376 ip )
Jon Hall390696c2015-05-05 17:13:41 -0700377 ipList.append( ip )
378 deviceList.append( deviceId )
Jon Hall58c76b72015-02-23 11:09:24 -0800379 except ( AttributeError, AssertionError ):
380 main.log.exception( "Something is wrong with ONOS device view" )
381 main.log.info( main.ONOScli1.devices() )
Jon Hall6aec96b2015-01-19 14:49:31 -0800382 utilities.assert_equals(
383 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800384 actual=roleCall,
Jon Hall6aec96b2015-01-19 14:49:31 -0800385 onpass="Re-assigned switch mastership to designated controller",
Jon Hall8f89dda2015-01-22 16:03:33 -0800386 onfail="Something wrong with deviceRole calls" )
Jon Hall94fd0472014-12-08 11:52:42 -0800387
Jon Hall390696c2015-05-05 17:13:41 -0700388 main.step( "Check mastership was correctly assigned" )
389 roleCheck = main.TRUE
390 # NOTE: This is due to the fact that device mastership change is not
391 # atomic and is actually a multi step process
392 time.sleep( 5 )
393 for i in range( len( ipList ) ):
394 ip = ipList[i]
395 deviceId = deviceList[i]
396 # Check assignment
397 master = main.ONOScli1.getRole( deviceId ).get( 'master' )
398 if ip in master:
399 roleCheck = roleCheck and main.TRUE
400 else:
401 roleCheck = roleCheck and main.FALSE
402 main.log.error( "Error, controller " + ip + " is not" +
403 " master " + "of device " +
404 str( deviceId ) + ". Master is " +
405 repr( master ) + "." )
Jon Hall6aec96b2015-01-19 14:49:31 -0800406 utilities.assert_equals(
407 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800408 actual=roleCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -0800409 onpass="Switches were successfully reassigned to designated " +
410 "controller",
411 onfail="Switches were not successfully reassigned" )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800412
Jon Hall6aec96b2015-01-19 14:49:31 -0800413 def CASE3( self, main ):
Jon Hall73cf9cc2014-11-20 22:28:38 -0800414 """
415 Assign intents
Jon Hall73cf9cc2014-11-20 22:28:38 -0800416 """
417 import time
Jon Hallfebb1c72015-03-05 13:30:09 -0800418 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -0700419 assert numControllers, "numControllers not defined"
420 assert main, "main not defined"
421 assert utilities.assert_equals, "utilities.assert_equals not defined"
422 assert CLIs, "CLIs not defined"
423 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -0800424 main.case( "Adding host Intents" )
Jon Hallfeff3082015-05-19 10:23:26 -0700425 main.caseExplaination = "Discover hosts by using pingall then " +\
426 "assign predetermined host-to-host intents." +\
427 " After installation, check that the intent" +\
428 " is distributed to all nodes and the state" +\
429 " is INSTALLED"
Jon Hall73cf9cc2014-11-20 22:28:38 -0800430
Jon Hall6aec96b2015-01-19 14:49:31 -0800431 # install onos-app-fwd
Jon Hall390696c2015-05-05 17:13:41 -0700432 main.step( "Install reactive forwarding app" )
433 installResults = CLIs[0].activateApp( "org.onosproject.fwd" )
434 utilities.assert_equals( expect=main.TRUE, actual=installResults,
435 onpass="Install fwd successful",
436 onfail="Install fwd failed" )
Jon Halla9d26da2015-03-30 16:45:32 -0700437
Jon Hallfeff3082015-05-19 10:23:26 -0700438 main.step( "Check app ids" )
Jon Halla9d26da2015-03-30 16:45:32 -0700439 appCheck = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -0700440 threads = []
441 for i in range( numControllers ):
Jon Halla9d26da2015-03-30 16:45:32 -0700442 t = main.Thread( target=CLIs[i].appToIDCheck,
443 name="appToIDCheck-" + str( i ),
444 args=[] )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700445 threads.append( t )
446 t.start()
447
448 for t in threads:
449 t.join()
Jon Halla9d26da2015-03-30 16:45:32 -0700450 appCheck = appCheck and t.result
Jon Halla9d26da2015-03-30 16:45:32 -0700451 if appCheck != main.TRUE:
452 main.log.warn( CLIs[0].apps() )
453 main.log.warn( CLIs[0].appIDs() )
Jon Hall390696c2015-05-05 17:13:41 -0700454 utilities.assert_equals( expect=main.TRUE, actual=appCheck,
455 onpass="App Ids seem to be correct",
456 onfail="Something is wrong with app Ids" )
Jon Hall94fd0472014-12-08 11:52:42 -0800457
Jon Hallfeff3082015-05-19 10:23:26 -0700458 main.step( "Discovering Hosts( Via pingall for now )" )
459 # FIXME: Once we have a host discovery mechanism, use that instead
Jon Hall6aec96b2015-01-19 14:49:31 -0800460 # REACTIVE FWD test
Jon Hall8f89dda2015-01-22 16:03:33 -0800461 pingResult = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -0700462 for i in range(2): # Retry if pingall fails first time
463 time1 = time.time()
464 pingResult = main.Mininet1.pingall()
465 utilities.assert_equals(
466 expect=main.TRUE,
467 actual=pingResult,
468 onpass="Reactive Pingall test passed",
Jon Hall390696c2015-05-05 17:13:41 -0700469 onfail="Reactive Pingall failed, " +
470 "one or more ping pairs failed" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700471 time2 = time.time()
Jon Hall390696c2015-05-05 17:13:41 -0700472 main.log.info( "Time for pingall: %2f seconds" %
473 ( time2 - time1 ) )
474 # timeout for fwd flows
475 time.sleep( 11 )
Jon Hall6aec96b2015-01-19 14:49:31 -0800476 # uninstall onos-app-fwd
Jon Hall390696c2015-05-05 17:13:41 -0700477 main.step( "Uninstall reactive forwarding app" )
478 uninstallResult = CLIs[0].deactivateApp( "org.onosproject.fwd" )
479 utilities.assert_equals( expect=main.TRUE, actual=uninstallResult,
480 onpass="Uninstall fwd successful",
481 onfail="Uninstall fwd failed" )
Jon Hallfeff3082015-05-19 10:23:26 -0700482
483 main.step( "Check app ids" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700484 threads = []
Jon Hallfeff3082015-05-19 10:23:26 -0700485 appCheck2 = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -0700486 for i in range( numControllers ):
Jon Halla9d26da2015-03-30 16:45:32 -0700487 t = main.Thread( target=CLIs[i].appToIDCheck,
488 name="appToIDCheck-" + str( i ),
489 args=[] )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700490 threads.append( t )
491 t.start()
Jon Hall73cf9cc2014-11-20 22:28:38 -0800492
Jon Hall5cfd23c2015-03-19 11:40:57 -0700493 for t in threads:
494 t.join()
Jon Hallfeff3082015-05-19 10:23:26 -0700495 appCheck2 = appCheck2 and t.result
496 if appCheck2 != main.TRUE:
Jon Halla9d26da2015-03-30 16:45:32 -0700497 main.log.warn( CLIs[0].apps() )
498 main.log.warn( CLIs[0].appIDs() )
Jon Hallfeff3082015-05-19 10:23:26 -0700499 utilities.assert_equals( expect=main.TRUE, actual=appCheck2,
Jon Hall390696c2015-05-05 17:13:41 -0700500 onpass="App Ids seem to be correct",
501 onfail="Something is wrong with app Ids" )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700502
Jon Hallfeff3082015-05-19 10:23:26 -0700503 main.step( "Add host intents via cli" )
Jon Hall58c76b72015-02-23 11:09:24 -0800504 intentIds = []
Jon Hall6aec96b2015-01-19 14:49:31 -0800505 # TODO: move the host numbers to params
Jon Hall58c76b72015-02-23 11:09:24 -0800506 # Maybe look at all the paths we ping?
Jon Hall8f89dda2015-01-22 16:03:33 -0800507 intentAddResult = True
Jon Hall58c76b72015-02-23 11:09:24 -0800508 hostResult = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -0800509 for i in range( 8, 18 ):
510 main.log.info( "Adding host intent between h" + str( i ) +
511 " and h" + str( i + 10 ) )
512 host1 = "00:00:00:00:00:" + \
513 str( hex( i )[ 2: ] ).zfill( 2 ).upper()
514 host2 = "00:00:00:00:00:" + \
515 str( hex( i + 10 )[ 2: ] ).zfill( 2 ).upper()
Jon Hall1b8f54a2015-02-04 13:24:20 -0800516 # NOTE: getHost can return None
517 host1Dict = main.ONOScli1.getHost( host1 )
518 host2Dict = main.ONOScli1.getHost( host2 )
519 host1Id = None
520 host2Id = None
521 if host1Dict and host2Dict:
522 host1Id = host1Dict.get( 'id', None )
523 host2Id = host2Dict.get( 'id', None )
Jon Hall8f89dda2015-01-22 16:03:33 -0800524 if host1Id and host2Id:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700525 nodeNum = ( i % 7 )
526 tmpId = CLIs[ nodeNum ].addHostIntent( host1Id, host2Id )
Jon Hall63604932015-02-26 17:09:50 -0800527 if tmpId:
528 main.log.info( "Added intent with id: " + tmpId )
529 intentIds.append( tmpId )
530 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700531 main.log.error( "addHostIntent returned: " +
532 repr( tmpId ) )
Jon Hall669173b2014-12-17 11:36:30 -0800533 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700534 main.log.error( "Error, getHost() failed for h" + str( i ) +
535 " and/or h" + str( i + 10 ) )
536 hosts = CLIs[ 0 ].hosts()
537 main.log.warn( "Hosts output: " )
538 try:
539 main.log.warn( json.dumps( json.loads( hosts ),
540 sort_keys=True,
541 indent=4,
542 separators=( ',', ': ' ) ) )
543 except ( ValueError, TypeError ):
544 main.log.warn( repr( hosts ) )
Jon Hall58c76b72015-02-23 11:09:24 -0800545 hostResult = main.FALSE
Jon Hallfeff3082015-05-19 10:23:26 -0700546 utilities.assert_equals( expect=main.TRUE, actual=hostResult,
547 onpass="Found a host id for each host",
548 onfail="Error looking up host ids" )
549
Jon Halla9d26da2015-03-30 16:45:32 -0700550 intentStart = time.time()
Jon Hall58c76b72015-02-23 11:09:24 -0800551 onosIds = main.ONOScli1.getAllIntentsId()
552 main.log.info( "Submitted intents: " + str( intentIds ) )
553 main.log.info( "Intents in ONOS: " + str( onosIds ) )
554 for intent in intentIds:
555 if intent in onosIds:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700556 pass # intent submitted is in onos
Jon Hall58c76b72015-02-23 11:09:24 -0800557 else:
558 intentAddResult = False
Jon Halla9d26da2015-03-30 16:45:32 -0700559 if intentAddResult:
560 intentStop = time.time()
561 else:
562 intentStop = None
Jon Hall1b8f54a2015-02-04 13:24:20 -0800563 # Print the intent states
Jon Hall58c76b72015-02-23 11:09:24 -0800564 intents = main.ONOScli1.intents()
Jon Hall1b8f54a2015-02-04 13:24:20 -0800565 intentStates = []
Jon Hall5cfd23c2015-03-19 11:40:57 -0700566 installedCheck = True
Jon Hall58c76b72015-02-23 11:09:24 -0800567 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
568 count = 0
Jon Hall5cfd23c2015-03-19 11:40:57 -0700569 try:
570 for intent in json.loads( intents ):
571 state = intent.get( 'state', None )
572 if "INSTALLED" not in state:
573 installedCheck = False
574 intentId = intent.get( 'id', None )
575 intentStates.append( ( intentId, state ) )
576 except ( ValueError, TypeError ):
577 main.log.exception( "Error parsing intents" )
Jon Hall58c76b72015-02-23 11:09:24 -0800578 # add submitted intents not in the store
579 tmplist = [ i for i, s in intentStates ]
580 missingIntents = False
581 for i in intentIds:
582 if i not in tmplist:
583 intentStates.append( ( i, " - " ) )
584 missingIntents = True
585 intentStates.sort()
586 for i, s in intentStates:
587 count += 1
588 main.log.info( "%-6s%-15s%-15s" %
589 ( str( count ), str( i ), str( s ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700590 leaders = main.ONOScli1.leaders()
591 try:
Jon Hallc9eabec2015-06-10 14:33:14 -0700592 missing = False
Jon Hall5cfd23c2015-03-19 11:40:57 -0700593 if leaders:
594 parsedLeaders = json.loads( leaders )
595 main.log.warn( json.dumps( parsedLeaders,
596 sort_keys=True,
597 indent=4,
598 separators=( ',', ': ' ) ) )
599 # check for all intent partitions
Jon Hall5cfd23c2015-03-19 11:40:57 -0700600 topics = []
601 for i in range( 14 ):
602 topics.append( "intent-partition-" + str( i ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700603 main.log.debug( topics )
604 ONOStopics = [ j['topic'] for j in parsedLeaders ]
605 for topic in topics:
606 if topic not in ONOStopics:
607 main.log.error( "Error: " + topic +
608 " not in leaders" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700609 missing = True
Jon Hall5cfd23c2015-03-19 11:40:57 -0700610 else:
611 main.log.error( "leaders() returned None" )
612 except ( ValueError, TypeError ):
613 main.log.exception( "Error parsing leaders" )
614 main.log.error( repr( leaders ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700615 # Check all nodes
616 if missing:
617 for node in CLIs:
618 response = node.leaders( jsonFormat=False)
619 main.log.warn( str( node.name ) + " leaders output: \n" +
620 str( response ) )
621
Jon Hall5cfd23c2015-03-19 11:40:57 -0700622 partitions = main.ONOScli1.partitions()
623 try:
624 if partitions :
625 parsedPartitions = json.loads( partitions )
626 main.log.warn( json.dumps( parsedPartitions,
627 sort_keys=True,
628 indent=4,
629 separators=( ',', ': ' ) ) )
630 # TODO check for a leader in all paritions
631 # TODO check for consistency among nodes
632 else:
633 main.log.error( "partitions() returned None" )
634 except ( ValueError, TypeError ):
635 main.log.exception( "Error parsing partitions" )
636 main.log.error( repr( partitions ) )
Jon Hall63604932015-02-26 17:09:50 -0800637 pendingMap = main.ONOScli1.pendingMap()
Jon Hall5cfd23c2015-03-19 11:40:57 -0700638 try:
639 if pendingMap :
640 parsedPending = json.loads( pendingMap )
641 main.log.warn( json.dumps( parsedPending,
642 sort_keys=True,
643 indent=4,
644 separators=( ',', ': ' ) ) )
645 # TODO check something here?
646 else:
647 main.log.error( "pendingMap() returned None" )
648 except ( ValueError, TypeError ):
649 main.log.exception( "Error parsing pending map" )
650 main.log.error( repr( pendingMap ) )
651
Jon Hallfeff3082015-05-19 10:23:26 -0700652 intentAddResult = bool( intentAddResult and not missingIntents and
653 installedCheck )
654 if not intentAddResult:
655 main.log.error( "Error in pushing host intents to ONOS" )
656
Jon Hall390696c2015-05-05 17:13:41 -0700657 main.step( "Intent Anti-Entropy dispersion" )
Jon Halla9d26da2015-03-30 16:45:32 -0700658 for i in range(100):
Jon Hall390696c2015-05-05 17:13:41 -0700659 correct = True
Jon Halla9d26da2015-03-30 16:45:32 -0700660 main.log.info( "Submitted intents: " + str( sorted( intentIds ) ) )
Jon Hall390696c2015-05-05 17:13:41 -0700661 for cli in CLIs:
662 onosIds = []
663 ids = cli.getAllIntentsId()
664 onosIds.append( ids )
665 main.log.debug( "Intents in " + cli.name + ": " +
666 str( sorted( onosIds ) ) )
667 if sorted( ids ) != sorted( intentIds ):
Jon Hallc9eabec2015-06-10 14:33:14 -0700668 main.log.debug( "Set of intent IDs doesn't match" )
Jon Hall390696c2015-05-05 17:13:41 -0700669 correct = False
Jon Hall40d2cbd2015-06-03 16:24:29 -0700670 break
671 else:
672 intents = json.loads( cli.intents() )
673 for intent in intents:
674 if intent[ 'state' ] != "INSTALLED":
Jon Hallc9eabec2015-06-10 14:33:14 -0700675 main.log.warn( "Intent " + intent[ 'id' ] +
676 " is " + intent[ 'state' ] )
Jon Hall40d2cbd2015-06-03 16:24:29 -0700677 correct = False
678 break
Jon Hall390696c2015-05-05 17:13:41 -0700679 if correct:
Jon Halla9d26da2015-03-30 16:45:32 -0700680 break
681 else:
682 time.sleep(1)
Jon Halla9d26da2015-03-30 16:45:32 -0700683 if not intentStop:
684 intentStop = time.time()
Jon Hall390696c2015-05-05 17:13:41 -0700685 global gossipTime
Jon Halla9d26da2015-03-30 16:45:32 -0700686 gossipTime = intentStop - intentStart
687 main.log.info( "It took about " + str( gossipTime ) +
Jon Hall390696c2015-05-05 17:13:41 -0700688 " seconds for all intents to appear in each node" )
Jon Halla9d26da2015-03-30 16:45:32 -0700689 # FIXME: make this time configurable/calculate based off of number of
690 # nodes and gossip rounds
691 utilities.assert_greater_equals(
Jon Hall390696c2015-05-05 17:13:41 -0700692 expect=40, actual=gossipTime,
Jon Halla9d26da2015-03-30 16:45:32 -0700693 onpass="ECM anti-entropy for intents worked within " +
694 "expected time",
695 onfail="Intent ECM anti-entropy took too long" )
Jon Hall390696c2015-05-05 17:13:41 -0700696 if gossipTime <= 40:
Jon Hall678f4512015-03-31 09:48:31 -0700697 intentAddResult = True
Jon Hall58c76b72015-02-23 11:09:24 -0800698
Jon Hall63604932015-02-26 17:09:50 -0800699 if not intentAddResult or "key" in pendingMap:
Jon Hall58c76b72015-02-23 11:09:24 -0800700 import time
Jon Hall63604932015-02-26 17:09:50 -0800701 installedCheck = True
Jon Hall58c76b72015-02-23 11:09:24 -0800702 main.log.info( "Sleeping 60 seconds to see if intents are found" )
703 time.sleep( 60 )
704 onosIds = main.ONOScli1.getAllIntentsId()
705 main.log.info( "Submitted intents: " + str( intentIds ) )
706 main.log.info( "Intents in ONOS: " + str( onosIds ) )
707 # Print the intent states
708 intents = main.ONOScli1.intents()
709 intentStates = []
710 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
711 count = 0
Jon Hall5cfd23c2015-03-19 11:40:57 -0700712 try:
713 for intent in json.loads( intents ):
714 # Iter through intents of a node
715 state = intent.get( 'state', None )
716 if "INSTALLED" not in state:
717 installedCheck = False
718 intentId = intent.get( 'id', None )
719 intentStates.append( ( intentId, state ) )
720 except ( ValueError, TypeError ):
721 main.log.exception( "Error parsing intents" )
Jon Hall58c76b72015-02-23 11:09:24 -0800722 # add submitted intents not in the store
723 tmplist = [ i for i, s in intentStates ]
724 for i in intentIds:
725 if i not in tmplist:
726 intentStates.append( ( i, " - " ) )
727 intentStates.sort()
728 for i, s in intentStates:
729 count += 1
730 main.log.info( "%-6s%-15s%-15s" %
731 ( str( count ), str( i ), str( s ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700732 leaders = main.ONOScli1.leaders()
733 try:
Jon Hallc9eabec2015-06-10 14:33:14 -0700734 missing = False
Jon Hall5cfd23c2015-03-19 11:40:57 -0700735 if leaders:
736 parsedLeaders = json.loads( leaders )
737 main.log.warn( json.dumps( parsedLeaders,
738 sort_keys=True,
739 indent=4,
740 separators=( ',', ': ' ) ) )
741 # check for all intent partitions
742 # check for election
743 topics = []
744 for i in range( 14 ):
745 topics.append( "intent-partition-" + str( i ) )
746 # FIXME: this should only be after we start the app
747 topics.append( "org.onosproject.election" )
748 main.log.debug( topics )
749 ONOStopics = [ j['topic'] for j in parsedLeaders ]
750 for topic in topics:
751 if topic not in ONOStopics:
752 main.log.error( "Error: " + topic +
753 " not in leaders" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700754 missing = True
Jon Hall5cfd23c2015-03-19 11:40:57 -0700755 else:
756 main.log.error( "leaders() returned None" )
757 except ( ValueError, TypeError ):
758 main.log.exception( "Error parsing leaders" )
759 main.log.error( repr( leaders ) )
Jon Hallc9eabec2015-06-10 14:33:14 -0700760 # Check all nodes
761 if missing:
762 for node in CLIs:
763 response = node.leaders( jsonFormat=False)
764 main.log.warn( str( node.name ) + " leaders output: \n" +
765 str( response ) )
766
Jon Hall5cfd23c2015-03-19 11:40:57 -0700767 partitions = main.ONOScli1.partitions()
768 try:
769 if partitions :
770 parsedPartitions = json.loads( partitions )
771 main.log.warn( json.dumps( parsedPartitions,
772 sort_keys=True,
773 indent=4,
774 separators=( ',', ': ' ) ) )
775 # TODO check for a leader in all paritions
776 # TODO check for consistency among nodes
777 else:
778 main.log.error( "partitions() returned None" )
779 except ( ValueError, TypeError ):
780 main.log.exception( "Error parsing partitions" )
781 main.log.error( repr( partitions ) )
782 pendingMap = main.ONOScli1.pendingMap()
783 try:
784 if pendingMap :
785 parsedPending = json.loads( pendingMap )
786 main.log.warn( json.dumps( parsedPending,
787 sort_keys=True,
788 indent=4,
789 separators=( ',', ': ' ) ) )
790 # TODO check something here?
791 else:
792 main.log.error( "pendingMap() returned None" )
793 except ( ValueError, TypeError ):
794 main.log.exception( "Error parsing pending map" )
795 main.log.error( repr( pendingMap ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800796
Jon Hall6aec96b2015-01-19 14:49:31 -0800797 def CASE4( self, main ):
Jon Hall73cf9cc2014-11-20 22:28:38 -0800798 """
799 Ping across added host intents
800 """
Jon Hallfebb1c72015-03-05 13:30:09 -0800801 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -0700802 import time
803 assert numControllers, "numControllers not defined"
804 assert main, "main not defined"
805 assert utilities.assert_equals, "utilities.assert_equals not defined"
806 assert CLIs, "CLIs not defined"
807 assert nodes, "nodes not defined"
Jon Hallfeff3082015-05-19 10:23:26 -0700808 main.case( "Verify connectivity by sendind traffic across Intents" )
809 main.caseExplaination = "Ping across added host intents to check " +\
810 "functionality and check the state of " +\
811 "the intent"
812 main.step( "Ping across added host intents" )
Jon Hall8f89dda2015-01-22 16:03:33 -0800813 PingResult = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -0800814 for i in range( 8, 18 ):
Jon Hall21270ac2015-02-16 17:59:55 -0800815 ping = main.Mininet1.pingHost( src="h" + str( i ),
816 target="h" + str( i + 10 ) )
Jon Hall8f89dda2015-01-22 16:03:33 -0800817 PingResult = PingResult and ping
Jon Hall6aec96b2015-01-19 14:49:31 -0800818 if ping == main.FALSE:
819 main.log.warn( "Ping failed between h" + str( i ) +
820 " and h" + str( i + 10 ) )
821 elif ping == main.TRUE:
822 main.log.info( "Ping test passed!" )
Jon Hall21270ac2015-02-16 17:59:55 -0800823 # Don't set PingResult or you'd override failures
Jon Hall8f89dda2015-01-22 16:03:33 -0800824 if PingResult == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -0700825 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -0800826 "Intents have not been installed correctly, pings failed." )
Jon Hall58c76b72015-02-23 11:09:24 -0800827 # TODO: pretty print
Jon Hall5cfd23c2015-03-19 11:40:57 -0700828 main.log.warn( "ONOS1 intents: " )
829 try:
830 tmpIntents = main.ONOScli1.intents()
831 main.log.warn( json.dumps( json.loads( tmpIntents ),
832 sort_keys=True,
833 indent=4,
834 separators=( ',', ': ' ) ) )
835 except ( ValueError, TypeError ):
836 main.log.warn( repr( tmpIntents ) )
Jon Hall6aec96b2015-01-19 14:49:31 -0800837 utilities.assert_equals(
838 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -0800839 actual=PingResult,
Jon Hall6aec96b2015-01-19 14:49:31 -0800840 onpass="Intents have been installed correctly and pings work",
841 onfail="Intents have not been installed correctly, pings failed." )
Jon Hall73cf9cc2014-11-20 22:28:38 -0800842
Jon Hallfeff3082015-05-19 10:23:26 -0700843 main.step( "Check Intent state" )
Jon Hall40d2cbd2015-06-03 16:24:29 -0700844 installedCheck = False
Jon Hallc9eabec2015-06-10 14:33:14 -0700845 loopCount = 0
846 while not installedCheck and loopCount < 40:
Jon Hall40d2cbd2015-06-03 16:24:29 -0700847 installedCheck = True
848 # Print the intent states
849 intents = main.ONOScli1.intents()
850 intentStates = []
851 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
852 count = 0
853 # Iter through intents of a node
854 try:
855 for intent in json.loads( intents ):
856 state = intent.get( 'state', None )
857 if "INSTALLED" not in state:
858 installedCheck = False
859 intentId = intent.get( 'id', None )
860 intentStates.append( ( intentId, state ) )
861 except ( ValueError, TypeError ):
862 main.log.exception( "Error parsing intents." )
863 # Print states
864 intentStates.sort()
865 for i, s in intentStates:
866 count += 1
867 main.log.info( "%-6s%-15s%-15s" %
868 ( str( count ), str( i ), str( s ) ) )
869 if not installedCheck:
870 time.sleep( 1 )
Jon Hallc9eabec2015-06-10 14:33:14 -0700871 loopCount += 1
Jon Hallfeff3082015-05-19 10:23:26 -0700872 utilities.assert_equals( expect=True, actual=installedCheck,
873 onpass="Intents are all INSTALLED",
Jon Hall40d2cbd2015-06-03 16:24:29 -0700874 onfail="Intents are not all in " +
Jon Hallfeff3082015-05-19 10:23:26 -0700875 "INSTALLED state" )
876
877 main.step( "Check leadership of topics" )
878 leaders = main.ONOScli1.leaders()
879 topicCheck = main.TRUE
880 try:
881 if leaders:
882 parsedLeaders = json.loads( leaders )
883 main.log.warn( json.dumps( parsedLeaders,
884 sort_keys=True,
885 indent=4,
886 separators=( ',', ': ' ) ) )
887 # check for all intent partitions
888 # check for election
889 # TODO: Look at Devices as topics now that it uses this system
890 topics = []
891 for i in range( 14 ):
892 topics.append( "intent-partition-" + str( i ) )
893 # FIXME: this should only be after we start the app
894 # FIXME: topics.append( "org.onosproject.election" )
895 # Print leaders output
896 main.log.debug( topics )
897 ONOStopics = [ j['topic'] for j in parsedLeaders ]
898 for topic in topics:
899 if topic not in ONOStopics:
900 main.log.error( "Error: " + topic +
901 " not in leaders" )
902 topicCheck = main.FALSE
903 else:
904 main.log.error( "leaders() returned None" )
905 topicCheck = main.FALSE
906 except ( ValueError, TypeError ):
907 topicCheck = main.FALSE
908 main.log.exception( "Error parsing leaders" )
909 main.log.error( repr( leaders ) )
910 # TODO: Check for a leader of these topics
Jon Hallc9eabec2015-06-10 14:33:14 -0700911 # Check all nodes
912 if topicCheck:
913 for node in CLIs:
914 response = node.leaders( jsonFormat=False)
915 main.log.warn( str( node.name ) + " leaders output: \n" +
916 str( response ) )
917
Jon Hallfeff3082015-05-19 10:23:26 -0700918 utilities.assert_equals( expect=main.TRUE, actual=topicCheck,
919 onpass="intent Partitions is in leaders",
920 onfail="Some topics were lost " )
921 # Print partitions
922 partitions = main.ONOScli1.partitions()
923 try:
924 if partitions :
925 parsedPartitions = json.loads( partitions )
926 main.log.warn( json.dumps( parsedPartitions,
927 sort_keys=True,
928 indent=4,
929 separators=( ',', ': ' ) ) )
930 # TODO check for a leader in all paritions
931 # TODO check for consistency among nodes
932 else:
933 main.log.error( "partitions() returned None" )
934 except ( ValueError, TypeError ):
935 main.log.exception( "Error parsing partitions" )
936 main.log.error( repr( partitions ) )
937 # Print Pending Map
938 pendingMap = main.ONOScli1.pendingMap()
939 try:
940 if pendingMap :
941 parsedPending = json.loads( pendingMap )
942 main.log.warn( json.dumps( parsedPending,
943 sort_keys=True,
944 indent=4,
945 separators=( ',', ': ' ) ) )
946 # TODO check something here?
947 else:
948 main.log.error( "pendingMap() returned None" )
949 except ( ValueError, TypeError ):
950 main.log.exception( "Error parsing pending map" )
951 main.log.error( repr( pendingMap ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700952
Jon Hall63604932015-02-26 17:09:50 -0800953 if not installedCheck:
Jon Hall5cfd23c2015-03-19 11:40:57 -0700954 main.log.info( "Waiting 60 seconds to see if the state of " +
955 "intents change" )
Jon Hall63604932015-02-26 17:09:50 -0800956 time.sleep( 60 )
957 # Print the intent states
958 intents = main.ONOScli1.intents()
959 intentStates = []
960 main.log.info( "%-6s%-15s%-15s" % ( 'Count', 'ID', 'State' ) )
961 count = 0
962 # Iter through intents of a node
Jon Hall5cfd23c2015-03-19 11:40:57 -0700963 try:
964 for intent in json.loads( intents ):
965 state = intent.get( 'state', None )
966 if "INSTALLED" not in state:
967 installedCheck = False
968 intentId = intent.get( 'id', None )
969 intentStates.append( ( intentId, state ) )
970 except ( ValueError, TypeError ):
971 main.log.exception( "Error parsing intents." )
Jon Hall63604932015-02-26 17:09:50 -0800972 intentStates.sort()
973 for i, s in intentStates:
974 count += 1
975 main.log.info( "%-6s%-15s%-15s" %
976 ( str( count ), str( i ), str( s ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -0700977 leaders = main.ONOScli1.leaders()
978 try:
Jon Hallc9eabec2015-06-10 14:33:14 -0700979 missing = False
Jon Hall5cfd23c2015-03-19 11:40:57 -0700980 if leaders:
981 parsedLeaders = json.loads( leaders )
982 main.log.warn( json.dumps( parsedLeaders,
983 sort_keys=True,
984 indent=4,
985 separators=( ',', ': ' ) ) )
986 # check for all intent partitions
987 # check for election
988 topics = []
989 for i in range( 14 ):
990 topics.append( "intent-partition-" + str( i ) )
991 # FIXME: this should only be after we start the app
992 topics.append( "org.onosproject.election" )
993 main.log.debug( topics )
994 ONOStopics = [ j['topic'] for j in parsedLeaders ]
995 for topic in topics:
996 if topic not in ONOStopics:
997 main.log.error( "Error: " + topic +
998 " not in leaders" )
Jon Hallc9eabec2015-06-10 14:33:14 -0700999 missing = True
Jon Hall5cfd23c2015-03-19 11:40:57 -07001000 else:
1001 main.log.error( "leaders() returned None" )
1002 except ( ValueError, TypeError ):
1003 main.log.exception( "Error parsing leaders" )
1004 main.log.error( repr( leaders ) )
Jon Hallc9eabec2015-06-10 14:33:14 -07001005 if missing:
1006 for node in CLIs:
1007 response = node.leaders( jsonFormat=False)
1008 main.log.warn( str( node.name ) + " leaders output: \n" +
1009 str( response ) )
1010
Jon Hall5cfd23c2015-03-19 11:40:57 -07001011 partitions = main.ONOScli1.partitions()
1012 try:
1013 if partitions :
1014 parsedPartitions = json.loads( partitions )
1015 main.log.warn( json.dumps( parsedPartitions,
1016 sort_keys=True,
1017 indent=4,
1018 separators=( ',', ': ' ) ) )
1019 # TODO check for a leader in all paritions
1020 # TODO check for consistency among nodes
1021 else:
1022 main.log.error( "partitions() returned None" )
1023 except ( ValueError, TypeError ):
1024 main.log.exception( "Error parsing partitions" )
1025 main.log.error( repr( partitions ) )
1026 pendingMap = main.ONOScli1.pendingMap()
1027 try:
1028 if pendingMap :
1029 parsedPending = json.loads( pendingMap )
1030 main.log.warn( json.dumps( parsedPending,
1031 sort_keys=True,
1032 indent=4,
1033 separators=( ',', ': ' ) ) )
1034 # TODO check something here?
1035 else:
1036 main.log.error( "pendingMap() returned None" )
1037 except ( ValueError, TypeError ):
1038 main.log.exception( "Error parsing pending map" )
1039 main.log.error( repr( pendingMap ) )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001040 # Print flowrules
1041 main.log.debug( CLIs[0].flows( jsonFormat=False ) )
Jon Hallfeff3082015-05-19 10:23:26 -07001042 main.step( "Wait a minute then ping again" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001043 # the wait is above
Jon Hallfeff3082015-05-19 10:23:26 -07001044 PingResult = main.TRUE
1045 for i in range( 8, 18 ):
1046 ping = main.Mininet1.pingHost( src="h" + str( i ),
1047 target="h" + str( i + 10 ) )
1048 PingResult = PingResult and ping
1049 if ping == main.FALSE:
1050 main.log.warn( "Ping failed between h" + str( i ) +
1051 " and h" + str( i + 10 ) )
1052 elif ping == main.TRUE:
1053 main.log.info( "Ping test passed!" )
1054 # Don't set PingResult or you'd override failures
1055 if PingResult == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001056 main.log.error(
Jon Hallfeff3082015-05-19 10:23:26 -07001057 "Intents have not been installed correctly, pings failed." )
1058 # TODO: pretty print
1059 main.log.warn( "ONOS1 intents: " )
1060 try:
1061 tmpIntents = main.ONOScli1.intents()
1062 main.log.warn( json.dumps( json.loads( tmpIntents ),
1063 sort_keys=True,
1064 indent=4,
1065 separators=( ',', ': ' ) ) )
1066 except ( ValueError, TypeError ):
1067 main.log.warn( repr( tmpIntents ) )
1068 utilities.assert_equals(
1069 expect=main.TRUE,
1070 actual=PingResult,
1071 onpass="Intents have been installed correctly and pings work",
1072 onfail="Intents have not been installed correctly, pings failed." )
1073
Jon Hall6aec96b2015-01-19 14:49:31 -08001074 def CASE5( self, main ):
1075 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001076 Reading state of ONOS
Jon Hall6aec96b2015-01-19 14:49:31 -08001077 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001078 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -07001079 import time
1080 assert numControllers, "numControllers not defined"
1081 assert main, "main not defined"
1082 assert utilities.assert_equals, "utilities.assert_equals not defined"
1083 assert CLIs, "CLIs not defined"
1084 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08001085 # assumes that sts is already in you PYTHONPATH
1086 from sts.topology.teston_topology import TestONTopology
Jon Hall73cf9cc2014-11-20 22:28:38 -08001087
Jon Hall6aec96b2015-01-19 14:49:31 -08001088 main.case( "Setting up and gathering data for current state" )
1089 # The general idea for this test case is to pull the state of
1090 # ( intents,flows, topology,... ) from each ONOS node
Jon Hall5cfd23c2015-03-19 11:40:57 -07001091 # We can then compare them with each other and also with past states
Jon Hall73cf9cc2014-11-20 22:28:38 -08001092
Jon Hall5cfd23c2015-03-19 11:40:57 -07001093 main.step( "Check that each switch has a master" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001094 global mastershipState
Jon Hall5cfd23c2015-03-19 11:40:57 -07001095 mastershipState = '[]'
Jon Hall94fd0472014-12-08 11:52:42 -08001096
Jon Hall6aec96b2015-01-19 14:49:31 -08001097 # Assert that each device has a master
Jon Hall5cfd23c2015-03-19 11:40:57 -07001098 rolesNotNull = main.TRUE
1099 threads = []
1100 for i in range( numControllers ):
1101 t = main.Thread( target=CLIs[i].rolesNotNull,
1102 name="rolesNotNull-" + str( i ),
1103 args=[] )
1104 threads.append( t )
1105 t.start()
1106
1107 for t in threads:
1108 t.join()
1109 rolesNotNull = rolesNotNull and t.result
Jon Hall6aec96b2015-01-19 14:49:31 -08001110 utilities.assert_equals(
1111 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001112 actual=rolesNotNull,
Jon Hall6aec96b2015-01-19 14:49:31 -08001113 onpass="Each device has a master",
1114 onfail="Some devices don't have a master assigned" )
Jon Hall94fd0472014-12-08 11:52:42 -08001115
Jon Hall5cfd23c2015-03-19 11:40:57 -07001116 main.step( "Get the Mastership of each switch from each controller" )
1117 ONOSMastership = []
1118 mastershipCheck = main.FALSE
1119 consistentMastership = True
1120 rolesResults = True
1121 threads = []
1122 for i in range( numControllers ):
1123 t = main.Thread( target=CLIs[i].roles,
1124 name="roles-" + str( i ),
1125 args=[] )
1126 threads.append( t )
1127 t.start()
1128
1129 for t in threads:
1130 t.join()
1131 ONOSMastership.append( t.result )
1132
1133 for i in range( numControllers ):
1134 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001135 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001136 " roles" )
1137 main.log.warn(
1138 "ONOS" + str( i + 1 ) + " mastership response: " +
1139 repr( ONOSMastership[i] ) )
1140 rolesResults = False
1141 utilities.assert_equals(
1142 expect=True,
1143 actual=rolesResults,
1144 onpass="No error in reading roles output",
1145 onfail="Error in reading roles from ONOS" )
1146
1147 main.step( "Check for consistency in roles from each controller" )
1148 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001149 main.log.info(
Jon Hall6aec96b2015-01-19 14:49:31 -08001150 "Switch roles are consistent across all ONOS nodes" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001151 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001152 consistentMastership = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001153 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001154 expect=True,
Jon Hall8f89dda2015-01-22 16:03:33 -08001155 actual=consistentMastership,
Jon Hall6aec96b2015-01-19 14:49:31 -08001156 onpass="Switch roles are consistent across all ONOS nodes",
1157 onfail="ONOS nodes have different views of switch roles" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001158
Jon Hall5cfd23c2015-03-19 11:40:57 -07001159 if rolesResults and not consistentMastership:
1160 for i in range( numControllers ):
1161 try:
1162 main.log.warn(
1163 "ONOS" + str( i + 1 ) + " roles: ",
1164 json.dumps(
1165 json.loads( ONOSMastership[ i ] ),
1166 sort_keys=True,
1167 indent=4,
1168 separators=( ',', ': ' ) ) )
1169 except ( ValueError, TypeError ):
1170 main.log.warn( repr( ONOSMastership[ i ] ) )
1171 elif rolesResults and consistentMastership:
1172 mastershipCheck = main.TRUE
1173 mastershipState = ONOSMastership[ 0 ]
1174
Jon Hall6aec96b2015-01-19 14:49:31 -08001175 main.step( "Get the intents from each controller" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001176 global intentState
1177 intentState = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001178 ONOSIntents = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001179 intentCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001180 consistentIntents = True
1181 intentsResults = True
1182 threads = []
1183 for i in range( numControllers ):
1184 t = main.Thread( target=CLIs[i].intents,
1185 name="intents-" + str( i ),
1186 args=[],
1187 kwargs={ 'jsonFormat': True } )
1188 threads.append( t )
1189 t.start()
1190
1191 for t in threads:
1192 t.join()
1193 ONOSIntents.append( t.result )
1194
1195 for i in range( numControllers ):
1196 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001197 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001198 " intents" )
1199 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1200 repr( ONOSIntents[ i ] ) )
1201 intentsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001202 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001203 expect=True,
1204 actual=intentsResults,
1205 onpass="No error in reading intents output",
1206 onfail="Error in reading intents from ONOS" )
1207
1208 main.step( "Check for consistency in Intents from each controller" )
1209 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001210 main.log.info( "Intents are consistent across all ONOS " +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001211 "nodes" )
1212 else:
1213 consistentIntents = False
Jon Hall40d2cbd2015-06-03 16:24:29 -07001214 main.log.error( "Intents not consistent" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001215 utilities.assert_equals(
1216 expect=True,
1217 actual=consistentIntents,
Jon Hall6aec96b2015-01-19 14:49:31 -08001218 onpass="Intents are consistent across all ONOS nodes",
1219 onfail="ONOS nodes have different views of intents" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001220
Jon Hall390696c2015-05-05 17:13:41 -07001221 if intentsResults:
1222 # Try to make it easy to figure out what is happening
1223 #
1224 # Intent ONOS1 ONOS2 ...
1225 # 0x01 INSTALLED INSTALLING
1226 # ... ... ...
1227 # ... ... ...
1228 title = " Id"
1229 for n in range( numControllers ):
1230 title += " " * 10 + "ONOS" + str( n + 1 )
1231 main.log.warn( title )
1232 # get all intent keys in the cluster
1233 keys = []
1234 for nodeStr in ONOSIntents:
1235 node = json.loads( nodeStr )
1236 for intent in node:
1237 keys.append( intent.get( 'id' ) )
1238 keys = set( keys )
1239 for key in keys:
1240 row = "%-13s" % key
1241 for nodeStr in ONOSIntents:
1242 node = json.loads( nodeStr )
1243 for intent in node:
1244 if intent.get( 'id', "Error" ) == key:
1245 row += "%-15s" % intent.get( 'state' )
1246 main.log.warn( row )
1247 # End table view
1248
Jon Hall5cfd23c2015-03-19 11:40:57 -07001249 if intentsResults and not consistentIntents:
Jon Hall390696c2015-05-05 17:13:41 -07001250 # print the json objects
Jon Hall5cfd23c2015-03-19 11:40:57 -07001251 n = len(ONOSIntents)
Jon Hall390696c2015-05-05 17:13:41 -07001252 main.log.debug( "ONOS" + str( n ) + " intents: " )
1253 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1254 sort_keys=True,
1255 indent=4,
1256 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001257 for i in range( numControllers ):
1258 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hall390696c2015-05-05 17:13:41 -07001259 main.log.debug( "ONOS" + str( i + 1 ) + " intents: " )
1260 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1261 sort_keys=True,
1262 indent=4,
1263 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001264 else:
Jon Hall390696c2015-05-05 17:13:41 -07001265 main.log.debug( nodes[ i ].name + " intents match ONOS" +
1266 str( n ) + " intents" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001267 elif intentsResults and consistentIntents:
1268 intentCheck = main.TRUE
1269 intentState = ONOSIntents[ 0 ]
1270
Jon Hall6aec96b2015-01-19 14:49:31 -08001271 main.step( "Get the flows from each controller" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001272 global flowState
1273 flowState = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001274 ONOSFlows = []
1275 ONOSFlowsJson = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001276 flowCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001277 consistentFlows = True
1278 flowsResults = True
1279 threads = []
1280 for i in range( numControllers ):
1281 t = main.Thread( target=CLIs[i].flows,
1282 name="flows-" + str( i ),
1283 args=[],
1284 kwargs={ 'jsonFormat': True } )
1285 threads.append( t )
1286 t.start()
1287
Jon Halla9d26da2015-03-30 16:45:32 -07001288 # NOTE: Flows command can take some time to run
Jon Hall5cfd23c2015-03-19 11:40:57 -07001289 time.sleep(30)
1290 for t in threads:
1291 t.join()
1292 result = t.result
1293 ONOSFlows.append( result )
1294
1295 for i in range( numControllers ):
1296 num = str( i + 1 )
1297 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001298 main.log.error( "Error in getting ONOS" + num + " flows" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001299 main.log.warn( "ONOS" + num + " flows response: " +
1300 repr( ONOSFlows[ i ] ) )
1301 flowsResults = False
1302 ONOSFlowsJson.append( None )
Jon Hall58c76b72015-02-23 11:09:24 -08001303 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001304 try:
1305 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1306 except ( ValueError, TypeError ):
1307 # FIXME: change this to log.error?
1308 main.log.exception( "Error in parsing ONOS" + num +
1309 " response as json." )
1310 main.log.error( repr( ONOSFlows[ i ] ) )
1311 ONOSFlowsJson.append( None )
1312 flowsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001313 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001314 expect=True,
1315 actual=flowsResults,
1316 onpass="No error in reading flows output",
1317 onfail="Error in reading flows from ONOS" )
1318
1319 main.step( "Check for consistency in Flows from each controller" )
1320 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1321 if all( tmp ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001322 main.log.info( "Flow count is consistent across all ONOS nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001323 else:
1324 consistentFlows = False
1325 utilities.assert_equals(
1326 expect=True,
1327 actual=consistentFlows,
Jon Hall6aec96b2015-01-19 14:49:31 -08001328 onpass="The flow count is consistent across all ONOS nodes",
1329 onfail="ONOS nodes have different flow counts" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001330
Jon Hall5cfd23c2015-03-19 11:40:57 -07001331 if flowsResults and not consistentFlows:
1332 for i in range( numControllers ):
1333 try:
1334 main.log.warn(
1335 "ONOS" + str( i + 1 ) + " flows: " +
1336 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1337 indent=4, separators=( ',', ': ' ) ) )
1338 except ( ValueError, TypeError ):
1339 main.log.warn(
1340 "ONOS" + str( i + 1 ) + " flows: " +
1341 repr( ONOSFlows[ i ] ) )
1342 elif flowsResults and consistentFlows:
1343 flowCheck = main.TRUE
1344 flowState = ONOSFlows[ 0 ]
1345
Jon Hall6aec96b2015-01-19 14:49:31 -08001346 main.step( "Get the OF Table entries" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001347 global flows
Jon Hall6aec96b2015-01-19 14:49:31 -08001348 flows = []
1349 for i in range( 1, 29 ):
Jon Hall8f89dda2015-01-22 16:03:33 -08001350 flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001351 if flowCheck == main.FALSE:
1352 for table in flows:
1353 main.log.warn( table )
Jon Hall6aec96b2015-01-19 14:49:31 -08001354 # TODO: Compare switch flow tables with ONOS flow tables
Jon Hall73cf9cc2014-11-20 22:28:38 -08001355
Jon Hall6aec96b2015-01-19 14:49:31 -08001356 main.step( "Start continuous pings" )
1357 main.Mininet2.pingLong(
1358 src=main.params[ 'PING' ][ 'source1' ],
1359 target=main.params[ 'PING' ][ 'target1' ],
1360 pingTime=500 )
1361 main.Mininet2.pingLong(
1362 src=main.params[ 'PING' ][ 'source2' ],
1363 target=main.params[ 'PING' ][ 'target2' ],
1364 pingTime=500 )
1365 main.Mininet2.pingLong(
1366 src=main.params[ 'PING' ][ 'source3' ],
1367 target=main.params[ 'PING' ][ 'target3' ],
1368 pingTime=500 )
1369 main.Mininet2.pingLong(
1370 src=main.params[ 'PING' ][ 'source4' ],
1371 target=main.params[ 'PING' ][ 'target4' ],
1372 pingTime=500 )
1373 main.Mininet2.pingLong(
1374 src=main.params[ 'PING' ][ 'source5' ],
1375 target=main.params[ 'PING' ][ 'target5' ],
1376 pingTime=500 )
1377 main.Mininet2.pingLong(
1378 src=main.params[ 'PING' ][ 'source6' ],
1379 target=main.params[ 'PING' ][ 'target6' ],
1380 pingTime=500 )
1381 main.Mininet2.pingLong(
1382 src=main.params[ 'PING' ][ 'source7' ],
1383 target=main.params[ 'PING' ][ 'target7' ],
1384 pingTime=500 )
1385 main.Mininet2.pingLong(
1386 src=main.params[ 'PING' ][ 'source8' ],
1387 target=main.params[ 'PING' ][ 'target8' ],
1388 pingTime=500 )
1389 main.Mininet2.pingLong(
1390 src=main.params[ 'PING' ][ 'source9' ],
1391 target=main.params[ 'PING' ][ 'target9' ],
1392 pingTime=500 )
1393 main.Mininet2.pingLong(
1394 src=main.params[ 'PING' ][ 'source10' ],
1395 target=main.params[ 'PING' ][ 'target10' ],
1396 pingTime=500 )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001397
Jon Hall6aec96b2015-01-19 14:49:31 -08001398 main.step( "Create TestONTopology object" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001399 ctrls = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001400 for node in nodes:
1401 temp = ( node, node.name, node.ip_address, 6633 )
1402 ctrls.append( temp )
1403 MNTopo = TestONTopology( main.Mininet1, ctrls )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001404
Jon Hall6aec96b2015-01-19 14:49:31 -08001405 main.step( "Collecting topology information from ONOS" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001406 devices = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001407 threads = []
1408 for i in range( numControllers ):
1409 t = main.Thread( target=CLIs[i].devices,
1410 name="devices-" + str( i ),
1411 args=[ ] )
1412 threads.append( t )
1413 t.start()
1414
1415 for t in threads:
1416 t.join()
1417 devices.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001418 hosts = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001419 threads = []
1420 for i in range( numControllers ):
1421 t = main.Thread( target=CLIs[i].hosts,
1422 name="hosts-" + str( i ),
1423 args=[ ] )
1424 threads.append( t )
1425 t.start()
1426
1427 for t in threads:
1428 t.join()
1429 try:
1430 hosts.append( json.loads( t.result ) )
1431 except ( ValueError, TypeError ):
1432 # FIXME: better handling of this, print which node
1433 # Maybe use thread name?
1434 main.log.exception( "Error parsing json output of hosts" )
1435 # FIXME: should this be an empty json object instead?
1436 hosts.append( None )
1437
Jon Hall73cf9cc2014-11-20 22:28:38 -08001438 ports = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001439 threads = []
1440 for i in range( numControllers ):
1441 t = main.Thread( target=CLIs[i].ports,
1442 name="ports-" + str( i ),
1443 args=[ ] )
1444 threads.append( t )
1445 t.start()
1446
1447 for t in threads:
1448 t.join()
1449 ports.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001450 links = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001451 threads = []
1452 for i in range( numControllers ):
1453 t = main.Thread( target=CLIs[i].links,
1454 name="links-" + str( i ),
1455 args=[ ] )
1456 threads.append( t )
1457 t.start()
1458
1459 for t in threads:
1460 t.join()
1461 links.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08001462 clusters = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001463 threads = []
1464 for i in range( numControllers ):
1465 t = main.Thread( target=CLIs[i].clusters,
1466 name="clusters-" + str( i ),
1467 args=[ ] )
1468 threads.append( t )
1469 t.start()
1470
1471 for t in threads:
1472 t.join()
1473 clusters.append( t.result )
Jon Hall529a37f2015-01-28 10:02:00 -08001474 # Compare json objects for hosts and dataplane clusters
Jon Hall94fd0472014-12-08 11:52:42 -08001475
Jon Hall6aec96b2015-01-19 14:49:31 -08001476 # hosts
Jon Hall390696c2015-05-05 17:13:41 -07001477 main.step( "Host view is consistent across ONOS nodes" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001478 consistentHostsResult = main.TRUE
Jon Hall94fd0472014-12-08 11:52:42 -08001479 for controller in range( len( hosts ) ):
Jon Hall8f89dda2015-01-22 16:03:33 -08001480 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08001481 if "Error" not in hosts[ controller ]:
1482 if hosts[ controller ] == hosts[ 0 ]:
Jon Hall94fd0472014-12-08 11:52:42 -08001483 continue
Jon Hall6aec96b2015-01-19 14:49:31 -08001484 else: # hosts not consistent
Jon Hall40d2cbd2015-06-03 16:24:29 -07001485 main.log.error( "hosts from ONOS" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001486 controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001487 " is inconsistent with ONOS1" )
1488 main.log.warn( repr( hosts[ controller ] ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001489 consistentHostsResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08001490
1491 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001492 main.log.error( "Error in getting ONOS hosts from ONOS" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001493 controllerStr )
1494 consistentHostsResult = main.FALSE
1495 main.log.warn( "ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001496 " hosts response: " +
1497 repr( hosts[ controller ] ) )
1498 utilities.assert_equals(
1499 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001500 actual=consistentHostsResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08001501 onpass="Hosts view is consistent across all ONOS nodes",
1502 onfail="ONOS nodes have different views of hosts" )
Jon Hall94fd0472014-12-08 11:52:42 -08001503
Jon Hall390696c2015-05-05 17:13:41 -07001504 main.step( "Each host has an IP address" )
Jon Hall58c76b72015-02-23 11:09:24 -08001505 ipResult = main.TRUE
1506 for controller in range( 0, len( hosts ) ):
1507 controllerStr = str( controller + 1 )
1508 for host in hosts[ controller ]:
Jon Hallfeff3082015-05-19 10:23:26 -07001509 if not host.get( 'ipAddresses', [ ] ):
Jon Hall5cfd23c2015-03-19 11:40:57 -07001510 main.log.error( "DEBUG:Error with host ips on controller" +
1511 controllerStr + ": " + str( host ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001512 ipResult = main.FALSE
1513 utilities.assert_equals(
1514 expect=main.TRUE,
1515 actual=ipResult,
1516 onpass="The ips of the hosts aren't empty",
1517 onfail="The ip of at least one host is missing" )
1518
Jon Hall6aec96b2015-01-19 14:49:31 -08001519 # Strongly connected clusters of devices
Jon Hall390696c2015-05-05 17:13:41 -07001520 main.step( "Cluster view is consistent across ONOS nodes" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001521 consistentClustersResult = main.TRUE
Jon Hall94fd0472014-12-08 11:52:42 -08001522 for controller in range( len( clusters ) ):
Jon Hall5cfd23c2015-03-19 11:40:57 -07001523 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08001524 if "Error" not in clusters[ controller ]:
1525 if clusters[ controller ] == clusters[ 0 ]:
Jon Hall94fd0472014-12-08 11:52:42 -08001526 continue
Jon Hall6aec96b2015-01-19 14:49:31 -08001527 else: # clusters not consistent
Jon Hall40d2cbd2015-06-03 16:24:29 -07001528 main.log.error( "clusters from ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001529 " is inconsistent with ONOS1" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001530 consistentClustersResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08001531
1532 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001533 main.log.error( "Error in getting dataplane clusters " +
Jon Hall8f89dda2015-01-22 16:03:33 -08001534 "from ONOS" + controllerStr )
1535 consistentClustersResult = main.FALSE
1536 main.log.warn( "ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001537 " clusters response: " +
1538 repr( clusters[ controller ] ) )
1539 utilities.assert_equals(
1540 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001541 actual=consistentClustersResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08001542 onpass="Clusters view is consistent across all ONOS nodes",
1543 onfail="ONOS nodes have different views of clusters" )
1544 # there should always only be one cluster
Jon Hall390696c2015-05-05 17:13:41 -07001545 main.step( "Cluster view correct across ONOS nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001546 try:
1547 numClusters = len( json.loads( clusters[ 0 ] ) )
1548 except ( ValueError, TypeError ):
1549 main.log.exception( "Error parsing clusters[0]: " +
1550 repr( clusters[ 0 ] ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001551 clusterResults = main.FALSE
1552 if numClusters == 1:
1553 clusterResults = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08001554 utilities.assert_equals(
1555 expect=1,
Jon Hall8f89dda2015-01-22 16:03:33 -08001556 actual=numClusters,
Jon Hall6aec96b2015-01-19 14:49:31 -08001557 onpass="ONOS shows 1 SCC",
Jon Hall58c76b72015-02-23 11:09:24 -08001558 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
Jon Hall94fd0472014-12-08 11:52:42 -08001559
Jon Hall6aec96b2015-01-19 14:49:31 -08001560 main.step( "Comparing ONOS topology to MN" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001561 devicesResults = main.TRUE
1562 portsResults = main.TRUE
1563 linksResults = main.TRUE
1564 for controller in range( numControllers ):
1565 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08001566 if devices[ controller ] or "Error" not in devices[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08001567 currentDevicesResult = main.Mininet1.compareSwitches(
Jon Hall6aec96b2015-01-19 14:49:31 -08001568 MNTopo,
Jon Hall5cfd23c2015-03-19 11:40:57 -07001569 json.loads( devices[ controller ] ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001570 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08001571 currentDevicesResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001572 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08001573 actual=currentDevicesResult,
1574 onpass="ONOS" + controllerStr +
1575 " Switches view is correct",
1576 onfail="ONOS" + controllerStr +
1577 " Switches view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001578
Jon Hall6aec96b2015-01-19 14:49:31 -08001579 if ports[ controller ] or "Error" not in ports[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08001580 currentPortsResult = main.Mininet1.comparePorts(
Jon Hall6aec96b2015-01-19 14:49:31 -08001581 MNTopo,
Jon Hall5cfd23c2015-03-19 11:40:57 -07001582 json.loads( ports[ controller ] ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001583 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08001584 currentPortsResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001585 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08001586 actual=currentPortsResult,
1587 onpass="ONOS" + controllerStr +
1588 " ports view is correct",
1589 onfail="ONOS" + controllerStr +
1590 " ports view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001591
Jon Hall6aec96b2015-01-19 14:49:31 -08001592 if links[ controller ] or "Error" not in links[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08001593 currentLinksResult = main.Mininet1.compareLinks(
Jon Hall6aec96b2015-01-19 14:49:31 -08001594 MNTopo,
Jon Hall5cfd23c2015-03-19 11:40:57 -07001595 json.loads( links[ controller ] ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001596 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08001597 currentLinksResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001598 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08001599 actual=currentLinksResult,
1600 onpass="ONOS" + controllerStr +
1601 " links view is correct",
1602 onfail="ONOS" + controllerStr +
1603 " links view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001604
Jon Hall8f89dda2015-01-22 16:03:33 -08001605 devicesResults = devicesResults and currentDevicesResult
1606 portsResults = portsResults and currentPortsResult
1607 linksResults = linksResults and currentLinksResult
Jon Hall73cf9cc2014-11-20 22:28:38 -08001608
Jon Hall5cfd23c2015-03-19 11:40:57 -07001609 topoResult = ( devicesResults and portsResults and linksResults
1610 and consistentHostsResult and consistentClustersResult
1611 and clusterResults and ipResult )
Jon Hall8f89dda2015-01-22 16:03:33 -08001612 utilities.assert_equals( expect=main.TRUE, actual=topoResult,
Jon Hall58c76b72015-02-23 11:09:24 -08001613 onpass="Topology Check Test successful",
1614 onfail="Topology Check Test NOT successful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001615
Jon Hall6aec96b2015-01-19 14:49:31 -08001616 def CASE6( self, main ):
1617 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001618 The Failure case.
Jon Hall6aec96b2015-01-19 14:49:31 -08001619 """
Jon Hall94fd0472014-12-08 11:52:42 -08001620 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07001621 assert numControllers, "numControllers not defined"
1622 assert main, "main not defined"
1623 assert utilities.assert_equals, "utilities.assert_equals not defined"
1624 assert CLIs, "CLIs not defined"
1625 assert nodes, "nodes not defined"
Jon Hall5cfd23c2015-03-19 11:40:57 -07001626 main.case( "Restart minority of ONOS nodes" )
Jon Hall390696c2015-05-05 17:13:41 -07001627 main.step( "Killing 3 ONOS nodes" )
Jon Hallfeff3082015-05-19 10:23:26 -07001628 killTime = time.time()
Jon Hall390696c2015-05-05 17:13:41 -07001629 # TODO: Randomize these nodes or base this on partitions
Jon Hall5cfd23c2015-03-19 11:40:57 -07001630 # TODO: use threads in this case
Jon Hall390696c2015-05-05 17:13:41 -07001631 killResults = main.ONOSbench.onosKill( nodes[0].ip_address )
Jon Hall6aec96b2015-01-19 14:49:31 -08001632 time.sleep( 10 )
Jon Hall390696c2015-05-05 17:13:41 -07001633 killResults = killResults and\
1634 main.ONOSbench.onosKill( nodes[1].ip_address )
Jon Hall6aec96b2015-01-19 14:49:31 -08001635 time.sleep( 10 )
Jon Hall390696c2015-05-05 17:13:41 -07001636 killResults = killResults and\
1637 main.ONOSbench.onosKill( nodes[2].ip_address )
1638 utilities.assert_equals( expect=main.TRUE, actual=killResults,
1639 onpass="ONOS Killed successfully",
1640 onfail="ONOS kill NOT successful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001641
Jon Hall6aec96b2015-01-19 14:49:31 -08001642 main.step( "Checking if ONOS is up yet" )
Jon Hallffb386d2014-11-21 13:43:38 -08001643 count = 0
Jon Hall8f89dda2015-01-22 16:03:33 -08001644 onosIsupResult = main.FALSE
1645 while onosIsupResult == main.FALSE and count < 10:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001646 onos1Isup = main.ONOSbench.isup( nodes[0].ip_address )
1647 onos2Isup = main.ONOSbench.isup( nodes[1].ip_address )
1648 onos3Isup = main.ONOSbench.isup( nodes[2].ip_address )
Jon Hall8f89dda2015-01-22 16:03:33 -08001649 onosIsupResult = onos1Isup and onos2Isup and onos3Isup
Jon Hallffb386d2014-11-21 13:43:38 -08001650 count = count + 1
Jon Hall73cf9cc2014-11-20 22:28:38 -08001651 # TODO: if it becomes an issue, we can retry this step a few times
Jon Hall390696c2015-05-05 17:13:41 -07001652 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1653 onpass="ONOS restarted successfully",
1654 onfail="ONOS restart NOT successful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001655
Jon Hall390696c2015-05-05 17:13:41 -07001656 main.step( "Restarting ONOS CLIs" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001657 cliResult1 = main.ONOScli1.startOnosCli( nodes[0].ip_address )
1658 cliResult2 = main.ONOScli2.startOnosCli( nodes[1].ip_address )
1659 cliResult3 = main.ONOScli3.startOnosCli( nodes[2].ip_address )
Jon Hall8f89dda2015-01-22 16:03:33 -08001660 cliResults = cliResult1 and cliResult2 and cliResult3
Jon Hall390696c2015-05-05 17:13:41 -07001661 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1662 onpass="ONOS cli restarted",
1663 onfail="ONOS cli did not restart" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001664
Jon Hall21270ac2015-02-16 17:59:55 -08001665 # Grab the time of restart so we chan check how long the gossip
1666 # protocol has had time to work
Jon Hallfeff3082015-05-19 10:23:26 -07001667 main.restartTime = time.time() - killTime
1668 main.log.debug( "Restart time: " + str( main.restartTime ) )
1669 '''
1670 # FIXME: revisit test plan for election with madan
1671 # Rerun for election on restarted nodes
1672 run1 = CLIs[0].electionTestRun()
1673 run2 = CLIs[1].electionTestRun()
1674 run3 = CLIs[2].electionTestRun()
1675 runResults = run1 and run2 and run3
1676 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1677 onpass="Reran for election",
1678 onfail="Failed to rerun for election" )
1679 '''
1680 # TODO: MAke this configurable. Also, we are breaking the above timer
1681 time.sleep( 60 )
1682 main.log.debug( CLIs[0].nodes( jsonFormat=False ) )
1683 main.log.debug( CLIs[0].leaders( jsonFormat=False ) )
1684 main.log.debug( CLIs[0].partitions( jsonFormat=False ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001685
Jon Hall6aec96b2015-01-19 14:49:31 -08001686 def CASE7( self, main ):
1687 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001688 Check state after ONOS failure
Jon Hall6aec96b2015-01-19 14:49:31 -08001689 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001690 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -07001691 assert numControllers, "numControllers not defined"
1692 assert main, "main not defined"
1693 assert utilities.assert_equals, "utilities.assert_equals not defined"
1694 assert CLIs, "CLIs not defined"
1695 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08001696 main.case( "Running ONOS Constant State Tests" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001697
Jon Hall5cfd23c2015-03-19 11:40:57 -07001698 main.step( "Check that each switch has a master" )
Jon Hall6aec96b2015-01-19 14:49:31 -08001699 # Assert that each device has a master
Jon Hall5cfd23c2015-03-19 11:40:57 -07001700 rolesNotNull = main.TRUE
1701 threads = []
1702 for i in range( numControllers ):
1703 t = main.Thread( target=CLIs[i].rolesNotNull,
1704 name="rolesNotNull-" + str( i ),
1705 args=[ ] )
1706 threads.append( t )
1707 t.start()
1708
1709 for t in threads:
1710 t.join()
1711 rolesNotNull = rolesNotNull and t.result
Jon Hall6aec96b2015-01-19 14:49:31 -08001712 utilities.assert_equals(
1713 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001714 actual=rolesNotNull,
Jon Hall6aec96b2015-01-19 14:49:31 -08001715 onpass="Each device has a master",
1716 onfail="Some devices don't have a master assigned" )
Jon Hall94fd0472014-12-08 11:52:42 -08001717
Jon Hall390696c2015-05-05 17:13:41 -07001718 main.step( "Read device roles from ONOS" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001719 ONOSMastership = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001720 consistentMastership = True
1721 rolesResults = True
1722 threads = []
1723 for i in range( numControllers ):
1724 t = main.Thread( target=CLIs[i].roles,
1725 name="roles-" + str( i ),
1726 args=[] )
1727 threads.append( t )
1728 t.start()
1729
1730 for t in threads:
1731 t.join()
1732 ONOSMastership.append( t.result )
1733
1734 for i in range( numControllers ):
1735 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001736 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001737 " roles" )
1738 main.log.warn(
1739 "ONOS" + str( i + 1 ) + " mastership response: " +
1740 repr( ONOSMastership[i] ) )
1741 rolesResults = False
1742 utilities.assert_equals(
1743 expect=True,
1744 actual=rolesResults,
1745 onpass="No error in reading roles output",
1746 onfail="Error in reading roles from ONOS" )
1747
1748 main.step( "Check for consistency in roles from each controller" )
1749 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001750 main.log.info(
Jon Hall6aec96b2015-01-19 14:49:31 -08001751 "Switch roles are consistent across all ONOS nodes" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001752 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001753 consistentMastership = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001754 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001755 expect=True,
Jon Hall8f89dda2015-01-22 16:03:33 -08001756 actual=consistentMastership,
Jon Hall6aec96b2015-01-19 14:49:31 -08001757 onpass="Switch roles are consistent across all ONOS nodes",
1758 onfail="ONOS nodes have different views of switch roles" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001759
Jon Hall5cfd23c2015-03-19 11:40:57 -07001760 if rolesResults and not consistentMastership:
1761 for i in range( numControllers ):
1762 main.log.warn(
1763 "ONOS" + str( i + 1 ) + " roles: ",
1764 json.dumps(
1765 json.loads( ONOSMastership[ i ] ),
1766 sort_keys=True,
1767 indent=4,
1768 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001769
Jon Hallfeff3082015-05-19 10:23:26 -07001770 # NOTE: we expect mastership to change on controller failure
1771 '''
Jon Hall73cf9cc2014-11-20 22:28:38 -08001772 description2 = "Compare switch roles from before failure"
Jon Hall6aec96b2015-01-19 14:49:31 -08001773 main.step( description2 )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001774 try:
1775 currentJson = json.loads( ONOSMastership[0] )
1776 oldJson = json.loads( mastershipState )
1777 except ( ValueError, TypeError ):
1778 main.log.exception( "Something is wrong with parsing " +
1779 "ONOSMastership[0] or mastershipState" )
1780 main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[0] ) )
1781 main.log.error( "mastershipState" + repr( mastershipState ) )
1782 main.cleanup()
1783 main.exit()
Jon Hall8f89dda2015-01-22 16:03:33 -08001784 mastershipCheck = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08001785 for i in range( 1, 29 ):
1786 switchDPID = str(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001787 main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001788 current = [ switch[ 'master' ] for switch in currentJson
Jon Hall6aec96b2015-01-19 14:49:31 -08001789 if switchDPID in switch[ 'id' ] ]
Jon Hall8f89dda2015-01-22 16:03:33 -08001790 old = [ switch[ 'master' ] for switch in oldJson
Jon Hall6aec96b2015-01-19 14:49:31 -08001791 if switchDPID in switch[ 'id' ] ]
Jon Hall73cf9cc2014-11-20 22:28:38 -08001792 if current == old:
Jon Hall8f89dda2015-01-22 16:03:33 -08001793 mastershipCheck = mastershipCheck and main.TRUE
Jon Hall73cf9cc2014-11-20 22:28:38 -08001794 else:
Jon Hall6aec96b2015-01-19 14:49:31 -08001795 main.log.warn( "Mastership of switch %s changed" % switchDPID )
Jon Hall8f89dda2015-01-22 16:03:33 -08001796 mastershipCheck = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001797 utilities.assert_equals(
1798 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001799 actual=mastershipCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -08001800 onpass="Mastership of Switches was not changed",
1801 onfail="Mastership of some switches changed" )
Jon Hallfeff3082015-05-19 10:23:26 -07001802 '''
Jon Hall73cf9cc2014-11-20 22:28:38 -08001803
Jon Hall58c76b72015-02-23 11:09:24 -08001804 main.step( "Get the intents and compare across all nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001805 ONOSIntents = []
Jon Hall58c76b72015-02-23 11:09:24 -08001806 intentCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001807 consistentIntents = True
1808 intentsResults = True
1809 threads = []
1810 for i in range( numControllers ):
1811 t = main.Thread( target=CLIs[i].intents,
1812 name="intents-" + str( i ),
1813 args=[],
1814 kwargs={ 'jsonFormat': True } )
1815 threads.append( t )
1816 t.start()
1817
1818 for t in threads:
1819 t.join()
1820 ONOSIntents.append( t.result )
1821
1822 for i in range( numControllers ):
1823 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001824 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001825 " intents" )
1826 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1827 repr( ONOSIntents[ i ] ) )
1828 intentsResults = False
Jon Hall58c76b72015-02-23 11:09:24 -08001829 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001830 expect=True,
1831 actual=intentsResults,
1832 onpass="No error in reading intents output",
1833 onfail="Error in reading intents from ONOS" )
1834
1835 main.step( "Check for consistency in Intents from each controller" )
1836 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001837 main.log.info( "Intents are consistent across all ONOS " +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001838 "nodes" )
1839 else:
1840 consistentIntents = False
Jon Hall390696c2015-05-05 17:13:41 -07001841
1842 # Try to make it easy to figure out what is happening
1843 #
1844 # Intent ONOS1 ONOS2 ...
1845 # 0x01 INSTALLED INSTALLING
1846 # ... ... ...
1847 # ... ... ...
1848 title = " ID"
1849 for n in range( numControllers ):
1850 title += " " * 10 + "ONOS" + str( n + 1 )
1851 main.log.warn( title )
1852 # get all intent keys in the cluster
1853 keys = []
1854 for nodeStr in ONOSIntents:
1855 node = json.loads( nodeStr )
1856 for intent in node:
1857 keys.append( intent.get( 'id' ) )
1858 keys = set( keys )
1859 for key in keys:
1860 row = "%-13s" % key
1861 for nodeStr in ONOSIntents:
1862 node = json.loads( nodeStr )
1863 for intent in node:
1864 if intent.get( 'id' ) == key:
1865 row += "%-15s" % intent.get( 'state' )
1866 main.log.warn( row )
1867 # End table view
1868
Jon Hall5cfd23c2015-03-19 11:40:57 -07001869 utilities.assert_equals(
1870 expect=True,
1871 actual=consistentIntents,
Jon Hall58c76b72015-02-23 11:09:24 -08001872 onpass="Intents are consistent across all ONOS nodes",
1873 onfail="ONOS nodes have different views of intents" )
Jon Hall58c76b72015-02-23 11:09:24 -08001874 intentStates = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001875 for node in ONOSIntents: # Iter through ONOS nodes
Jon Hall58c76b72015-02-23 11:09:24 -08001876 nodeStates = []
1877 # Iter through intents of a node
Jon Hall5cfd23c2015-03-19 11:40:57 -07001878 try:
1879 for intent in json.loads( node ):
1880 nodeStates.append( intent[ 'state' ] )
1881 except ( ValueError, TypeError ):
1882 main.log.exception( "Error in parsing intents" )
1883 main.log.error( repr( node ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001884 intentStates.append( nodeStates )
1885 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
1886 main.log.info( dict( out ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001887
Jon Hall5cfd23c2015-03-19 11:40:57 -07001888 if intentsResults and not consistentIntents:
1889 for i in range( numControllers ):
1890 main.log.warn( "ONOS" + str( i + 1 ) + " intents: " )
1891 main.log.warn( json.dumps(
1892 json.loads( ONOSIntents[ i ] ),
1893 sort_keys=True,
1894 indent=4,
1895 separators=( ',', ': ' ) ) )
1896 elif intentsResults and consistentIntents:
1897 intentCheck = main.TRUE
1898
Jon Hall58c76b72015-02-23 11:09:24 -08001899 # NOTE: Store has no durability, so intents are lost across system
1900 # restarts
1901 main.step( "Compare current intents with intents before the failure" )
1902 # NOTE: this requires case 5 to pass for intentState to be set.
1903 # maybe we should stop the test if that fails?
Jon Hall40d2cbd2015-06-03 16:24:29 -07001904 sameIntents = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001905 if intentState and intentState == ONOSIntents[ 0 ]:
Jon Hall21270ac2015-02-16 17:59:55 -08001906 sameIntents = main.TRUE
Jon Hallfeff3082015-05-19 10:23:26 -07001907 main.log.info( "Intents are consistent with before failure" )
Jon Hall58c76b72015-02-23 11:09:24 -08001908 # TODO: possibly the states have changed? we may need to figure out
Jon Hall5cfd23c2015-03-19 11:40:57 -07001909 # what the acceptable states are
Jon Hall40d2cbd2015-06-03 16:24:29 -07001910 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
1911 sameIntents = main.TRUE
Jon Hall58c76b72015-02-23 11:09:24 -08001912 try:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001913 before = json.loads( intentState )
1914 after = json.loads( ONOSIntents[ 0 ] )
1915 for intent in before:
1916 if intent not in after:
1917 sameIntents = main.FALSE
Jon Hallc9eabec2015-06-10 14:33:14 -07001918 main.log.debug( "Intent is not currently in ONOS " +
Jon Hall40d2cbd2015-06-03 16:24:29 -07001919 "(at least in the same form):" )
1920 main.log.debug( json.dumps( intent ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001921 except ( ValueError, TypeError ):
1922 main.log.exception( "Exception printing intents" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001923 main.log.debug( repr( ONOSIntents[0] ) )
1924 main.log.debug( repr( intentState ) )
1925 if sameIntents == main.FALSE:
1926 try:
1927 main.log.debug( "ONOS intents before: " )
1928 main.log.debug( json.dumps( json.loads( intentState ),
1929 sort_keys=True, indent=4,
1930 separators=( ',', ': ' ) ) )
1931 main.log.debug( "Current ONOS intents: " )
1932 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
1933 sort_keys=True, indent=4,
1934 separators=( ',', ': ' ) ) )
1935 except ( ValueError, TypeError ):
1936 main.log.exception( "Exception printing intents" )
1937 main.log.debug( repr( ONOSIntents[0] ) )
1938 main.log.debug( repr( intentState ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001939 utilities.assert_equals(
1940 expect=main.TRUE,
1941 actual=sameIntents,
1942 onpass="Intents are consistent with before failure",
1943 onfail="The Intents changed during failure" )
1944 intentCheck = intentCheck and sameIntents
Jon Hall21270ac2015-02-16 17:59:55 -08001945
Jon Hall58c76b72015-02-23 11:09:24 -08001946 main.step( "Get the OF Table entries and compare to before " +
1947 "component failure" )
1948 FlowTables = main.TRUE
1949 flows2 = []
1950 for i in range( 28 ):
1951 main.log.info( "Checking flow table on s" + str( i + 1 ) )
1952 tmpFlows = main.Mininet2.getFlowTable( 1.3, "s" + str( i + 1 ) )
1953 flows2.append( tmpFlows )
1954 tempResult = main.Mininet2.flowComp(
1955 flow1=flows[ i ],
1956 flow2=tmpFlows )
1957 FlowTables = FlowTables and tempResult
1958 if FlowTables == main.FALSE:
1959 main.log.info( "Differences in flow table for switch: s" +
1960 str( i + 1 ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001961 utilities.assert_equals(
1962 expect=main.TRUE,
1963 actual=FlowTables,
1964 onpass="No changes were found in the flow tables",
1965 onfail="Changes were found in the flow tables" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001966
Jon Hall6aec96b2015-01-19 14:49:31 -08001967 main.step( "Check the continuous pings to ensure that no packets " +
1968 "were dropped during component failure" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001969 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
1970 main.params[ 'TESTONIP' ] )
Jon Hall8f89dda2015-01-22 16:03:33 -08001971 LossInPings = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001972 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
1973 for i in range( 8, 18 ):
1974 main.log.info(
1975 "Checking for a loss in pings along flow from s" +
1976 str( i ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001977 LossInPings = main.Mininet2.checkForLoss(
Jon Hall6aec96b2015-01-19 14:49:31 -08001978 "/tmp/ping.h" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001979 str( i ) ) or LossInPings
1980 if LossInPings == main.TRUE:
Jon Hall6aec96b2015-01-19 14:49:31 -08001981 main.log.info( "Loss in ping detected" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001982 elif LossInPings == main.ERROR:
Jon Hall6aec96b2015-01-19 14:49:31 -08001983 main.log.info( "There are multiple mininet process running" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001984 elif LossInPings == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08001985 main.log.info( "No Loss in the pings" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001986 main.log.info( "No loss of dataplane connectivity" )
Jon Hall6aec96b2015-01-19 14:49:31 -08001987 utilities.assert_equals(
1988 expect=main.FALSE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001989 actual=LossInPings,
Jon Hall6aec96b2015-01-19 14:49:31 -08001990 onpass="No Loss of connectivity",
1991 onfail="Loss of dataplane connectivity detected" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001992
Jon Hall390696c2015-05-05 17:13:41 -07001993 main.step( "Leadership Election is still functional" )
Jon Hall6aec96b2015-01-19 14:49:31 -08001994 # Test of LeadershipElection
Jon Hall8f89dda2015-01-22 16:03:33 -08001995 leaderList = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001996 # FIXME: make sure this matches nodes that were restarted
1997 restarted = [ nodes[0].ip_address, nodes[1].ip_address,
1998 nodes[2].ip_address ]
Jon Hall390696c2015-05-05 17:13:41 -07001999
Jon Hall8f89dda2015-01-22 16:03:33 -08002000 leaderResult = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002001 for cli in CLIs:
2002 leaderN = cli.electionTestLeader()
Jon Hall8f89dda2015-01-22 16:03:33 -08002003 leaderList.append( leaderN )
Jon Hall669173b2014-12-17 11:36:30 -08002004 if leaderN == main.FALSE:
Jon Hallfeff3082015-05-19 10:23:26 -07002005 # error in response
Jon Hall40d2cbd2015-06-03 16:24:29 -07002006 main.log.error( "Something is wrong with " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002007 "electionTestLeader function, check the" +
Jon Hall6aec96b2015-01-19 14:49:31 -08002008 " error logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002009 leaderResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002010 elif leaderN is None:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002011 main.log.error( cli.name +
Jon Hall6aec96b2015-01-19 14:49:31 -08002012 " shows no leader for the election-app was" +
2013 " elected after the old one died" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002014 leaderResult = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002015 elif leaderN in restarted:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002016 main.log.error( cli.name + " shows " + str( leaderN ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002017 " as leader for the election-app, but it " +
2018 "was restarted" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002019 leaderResult = main.FALSE
2020 if len( set( leaderList ) ) != 1:
2021 leaderResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002022 main.log.error(
2023 "Inconsistent view of leader for the election test app" )
2024 # TODO: print the list
Jon Hall6aec96b2015-01-19 14:49:31 -08002025 utilities.assert_equals(
2026 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002027 actual=leaderResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002028 onpass="Leadership election passed",
2029 onfail="Something went wrong with Leadership election" )
Jon Hall669173b2014-12-17 11:36:30 -08002030
Jon Hall6aec96b2015-01-19 14:49:31 -08002031 def CASE8( self, main ):
2032 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002033 Compare topo
Jon Hall6aec96b2015-01-19 14:49:31 -08002034 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002035 import sys
Jon Hall6aec96b2015-01-19 14:49:31 -08002036 # FIXME add this path to params
2037 sys.path.append( "/home/admin/sts" )
2038 # assumes that sts is already in you PYTHONPATH
2039 from sts.topology.teston_topology import TestONTopology
Jon Hall73cf9cc2014-11-20 22:28:38 -08002040 import json
2041 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002042 assert numControllers, "numControllers not defined"
2043 assert main, "main not defined"
2044 assert utilities.assert_equals, "utilities.assert_equals not defined"
2045 assert CLIs, "CLIs not defined"
2046 assert nodes, "nodes not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002047
Jon Hallfeff3082015-05-19 10:23:26 -07002048 main.case( "Compare ONOS Topology view to Mininet topology" )
2049 main.caseExplaination = "Compare topology objects between Mininet" +\
2050 " and ONOS"
Jon Hall6aec96b2015-01-19 14:49:31 -08002051 main.step( "Create TestONTopology object" )
Jon Hallfeff3082015-05-19 10:23:26 -07002052 try:
2053 ctrls = []
2054 for node in nodes:
2055 temp = ( node, node.name, node.ip_address, 6633 )
2056 ctrls.append( temp )
2057 MNTopo = TestONTopology( main.Mininet1, ctrls )
2058 except Exception:
2059 objResult = main.FALSE
2060 else:
2061 objResult = main.TRUE
2062 utilities.assert_equals( expect=main.TRUE, actual=objResult,
2063 onpass="Created TestONTopology object",
2064 onfail="Exception while creating " +
2065 "TestONTopology object" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002066
Jon Hallfeff3082015-05-19 10:23:26 -07002067 main.step( "Comparing ONOS topology to MN" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002068 devicesResults = main.TRUE
2069 portsResults = main.TRUE
2070 linksResults = main.TRUE
Jon Hall58c76b72015-02-23 11:09:24 -08002071 hostsResults = main.TRUE
Jon Hallc9eabec2015-06-10 14:33:14 -07002072 hostAttachmentResults = True
Jon Hall8f89dda2015-01-22 16:03:33 -08002073 topoResult = main.FALSE
Jon Hall73cf9cc2014-11-20 22:28:38 -08002074 elapsed = 0
Jon Hallffb386d2014-11-21 13:43:38 -08002075 count = 0
Jon Hall6aec96b2015-01-19 14:49:31 -08002076 main.step( "Collecting topology information from ONOS" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002077 startTime = time.time()
Jon Hall21270ac2015-02-16 17:59:55 -08002078 # Give time for Gossip to work
Jon Hall8f89dda2015-01-22 16:03:33 -08002079 while topoResult == main.FALSE and elapsed < 60:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002080 count += 1
Jon Hall94fd0472014-12-08 11:52:42 -08002081 if count > 1:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002082 # TODO: Deprecate STS usage
Jon Hall58c76b72015-02-23 11:09:24 -08002083 MNTopo = TestONTopology( main.Mininet1, ctrls )
Jon Hall8f89dda2015-01-22 16:03:33 -08002084 cliStart = time.time()
Jon Hall94fd0472014-12-08 11:52:42 -08002085 devices = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002086 threads = []
2087 for i in range( numControllers ):
2088 t = main.Thread( target=CLIs[i].devices,
2089 name="devices-" + str( i ),
2090 args=[ ] )
2091 threads.append( t )
2092 t.start()
2093
2094 for t in threads:
2095 t.join()
2096 devices.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002097 hosts = []
Jon Hall58c76b72015-02-23 11:09:24 -08002098 ipResult = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002099 threads = []
2100 for i in range( numControllers ):
2101 t = main.Thread( target=CLIs[i].hosts,
2102 name="hosts-" + str( i ),
2103 args=[ ] )
2104 threads.append( t )
2105 t.start()
2106
2107 for t in threads:
2108 t.join()
2109 try:
2110 hosts.append( json.loads( t.result ) )
2111 except ( ValueError, TypeError ):
2112 main.log.exception( "Error parsing hosts results" )
2113 main.log.error( repr( t.result ) )
Jon Hall6aec96b2015-01-19 14:49:31 -08002114 for controller in range( 0, len( hosts ) ):
Jon Hall8f89dda2015-01-22 16:03:33 -08002115 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08002116 for host in hosts[ controller ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002117 if host is None or host.get( 'ipAddresses', [] ) == []:
Jon Hall6aec96b2015-01-19 14:49:31 -08002118 main.log.error(
Jon Hall40d2cbd2015-06-03 16:24:29 -07002119 "DEBUG:Error with host ipAddresses on controller" +
Jon Hall8f89dda2015-01-22 16:03:33 -08002120 controllerStr + ": " + str( host ) )
Jon Hall58c76b72015-02-23 11:09:24 -08002121 ipResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002122 ports = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002123 threads = []
2124 for i in range( numControllers ):
2125 t = main.Thread( target=CLIs[i].ports,
2126 name="ports-" + str( i ),
2127 args=[ ] )
2128 threads.append( t )
2129 t.start()
2130
2131 for t in threads:
2132 t.join()
2133 ports.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002134 links = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002135 threads = []
2136 for i in range( numControllers ):
2137 t = main.Thread( target=CLIs[i].links,
2138 name="links-" + str( i ),
2139 args=[ ] )
2140 threads.append( t )
2141 t.start()
2142
2143 for t in threads:
2144 t.join()
2145 links.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002146 clusters = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002147 threads = []
2148 for i in range( numControllers ):
2149 t = main.Thread( target=CLIs[i].clusters,
2150 name="clusters-" + str( i ),
2151 args=[ ] )
2152 threads.append( t )
2153 t.start()
2154
2155 for t in threads:
2156 t.join()
2157 clusters.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002158
Jon Hall8f89dda2015-01-22 16:03:33 -08002159 elapsed = time.time() - startTime
2160 cliTime = time.time() - cliStart
Jon Hallc9eabec2015-06-10 14:33:14 -07002161 print "Elapsed time: " + str( elapsed )
Jon Hall8f89dda2015-01-22 16:03:33 -08002162 print "CLI time: " + str( cliTime )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002163
Jon Hall8f89dda2015-01-22 16:03:33 -08002164 for controller in range( numControllers ):
2165 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08002166 if devices[ controller ] or "Error" not in devices[
2167 controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08002168 currentDevicesResult = main.Mininet1.compareSwitches(
Jon Hall6aec96b2015-01-19 14:49:31 -08002169 MNTopo,
Jon Hall58c76b72015-02-23 11:09:24 -08002170 json.loads( devices[ controller ] ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002171 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08002172 currentDevicesResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002173 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08002174 actual=currentDevicesResult,
2175 onpass="ONOS" + controllerStr +
2176 " Switches view is correct",
2177 onfail="ONOS" + controllerStr +
2178 " Switches view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002179
Jon Hall6aec96b2015-01-19 14:49:31 -08002180 if ports[ controller ] or "Error" not in ports[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08002181 currentPortsResult = main.Mininet1.comparePorts(
Jon Hall6aec96b2015-01-19 14:49:31 -08002182 MNTopo,
Jon Hall58c76b72015-02-23 11:09:24 -08002183 json.loads( ports[ controller ] ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002184 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08002185 currentPortsResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002186 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08002187 actual=currentPortsResult,
2188 onpass="ONOS" + controllerStr +
2189 " ports view is correct",
2190 onfail="ONOS" + controllerStr +
2191 " ports view is incorrect" )
Jon Hall94fd0472014-12-08 11:52:42 -08002192
Jon Hall6aec96b2015-01-19 14:49:31 -08002193 if links[ controller ] or "Error" not in links[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08002194 currentLinksResult = main.Mininet1.compareLinks(
Jon Hall6aec96b2015-01-19 14:49:31 -08002195 MNTopo,
Jon Hall58c76b72015-02-23 11:09:24 -08002196 json.loads( links[ controller ] ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002197 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08002198 currentLinksResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002199 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08002200 actual=currentLinksResult,
2201 onpass="ONOS" + controllerStr +
2202 " links view is correct",
2203 onfail="ONOS" + controllerStr +
2204 " links view is incorrect" )
2205
2206 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2207 currentHostsResult = main.Mininet1.compareHosts(
2208 MNTopo, hosts[ controller ] )
2209 else:
2210 currentHostsResult = main.FALSE
2211 utilities.assert_equals( expect=main.TRUE,
2212 actual=currentHostsResult,
2213 onpass="ONOS" + controllerStr +
2214 " hosts exist in Mininet",
2215 onfail="ONOS" + controllerStr +
2216 " hosts don't match Mininet" )
Jon Hallc9eabec2015-06-10 14:33:14 -07002217 # CHECKING HOST ATTACHMENT POINTS
2218 hostAttachment = True
2219 noHosts = False
2220 # FIXME: topo-HA/obelisk specific mappings:
2221 # key is mac and value is dpid
2222 mappings = {}
2223 for i in range( 1, 29 ): # hosts 1 through 28
2224 # set up correct variables:
2225 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2226 if i == 1:
2227 deviceId = "1000".zfill(16)
2228 elif i == 2:
2229 deviceId = "2000".zfill(16)
2230 elif i == 3:
2231 deviceId = "3000".zfill(16)
2232 elif i == 4:
2233 deviceId = "3004".zfill(16)
2234 elif i == 5:
2235 deviceId = "5000".zfill(16)
2236 elif i == 6:
2237 deviceId = "6000".zfill(16)
2238 elif i == 7:
2239 deviceId = "6007".zfill(16)
2240 elif i >= 8 and i <= 17:
2241 dpid = '3' + str( i ).zfill( 3 )
2242 deviceId = dpid.zfill(16)
2243 elif i >= 18 and i <= 27:
2244 dpid = '6' + str( i ).zfill( 3 )
2245 deviceId = dpid.zfill(16)
2246 elif i == 28:
2247 deviceId = "2800".zfill(16)
2248 mappings[ macId ] = deviceId
2249 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2250 if hosts[ controller ] == []:
2251 main.log.warn( "There are no hosts discovered" )
2252 noHosts = True
2253 else:
2254 for host in hosts[ controller ]:
2255 mac = None
2256 location = None
2257 device = None
2258 port = None
2259 try:
2260 mac = host.get( 'mac' )
2261 assert mac, "mac field could not be found for this host object"
Jon Hall58c76b72015-02-23 11:09:24 -08002262
Jon Hallc9eabec2015-06-10 14:33:14 -07002263 location = host.get( 'location' )
2264 assert location, "location field could not be found for this host object"
2265
2266 # Trim the protocol identifier off deviceId
2267 device = str( location.get( 'elementId' ) ).split(':')[1]
2268 assert device, "elementId field could not be found for this host location object"
2269
2270 port = location.get( 'port' )
2271 assert port, "port field could not be found for this host location object"
2272
2273 # Now check if this matches where they should be
2274 if mac and device and port:
2275 if str( port ) != "1":
2276 main.log.error( "The attachment port is incorrect for " +
2277 "host " + str( mac ) +
2278 ". Expected: 1 Actual: " + str( port) )
2279 hostAttachment = False
2280 if device != mappings[ str( mac ) ]:
2281 main.log.error( "The attachment device is incorrect for " +
2282 "host " + str( mac ) +
2283 ". Expected: " + mappings[ str( mac ) ] +
2284 " Actual: " + device )
2285 hostAttachment = False
2286 else:
2287 hostAttachment = False
2288 except AssertionError:
2289 main.log.exception( "Json object not as expected" )
2290 main.log.error( repr( host ) )
2291 hostAttachment = False
2292 else:
2293 main.log.error( "No hosts json output or \"Error\"" +
2294 " in output. hosts = " +
2295 repr( hosts[ controller ] ) )
2296 if noHosts is False:
2297 hostAttachment = True
2298
2299 # END CHECKING HOST ATTACHMENT POINTS
Jon Hall58c76b72015-02-23 11:09:24 -08002300 devicesResults = devicesResults and currentDevicesResult
2301 portsResults = portsResults and currentPortsResult
2302 linksResults = linksResults and currentLinksResult
2303 hostsResults = hostsResults and currentHostsResult
Jon Hallc9eabec2015-06-10 14:33:14 -07002304 hostAttachmentResults = hostAttachmentResults and hostAttachment
Jon Hall94fd0472014-12-08 11:52:42 -08002305
Jon Hallc9eabec2015-06-10 14:33:14 -07002306 # Compare json objects for hosts and dataplane clusters
Jon Hall94fd0472014-12-08 11:52:42 -08002307
Jon Hallc9eabec2015-06-10 14:33:14 -07002308 # hosts
2309 main.step( "Hosts view is consistent across all ONOS nodes" )
2310 consistentHostsResult = main.TRUE
2311 for controller in range( len( hosts ) ):
2312 controllerStr = str( controller + 1 )
2313 if "Error" not in hosts[ controller ]:
2314 if hosts[ controller ] == hosts[ 0 ]:
2315 continue
2316 else: # hosts not consistent
2317 main.log.error( "hosts from ONOS" + controllerStr +
2318 " is inconsistent with ONOS1" )
2319 main.log.warn( repr( hosts[ controller ] ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08002320 consistentHostsResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002321
Jon Hallc9eabec2015-06-10 14:33:14 -07002322 else:
2323 main.log.error( "Error in getting ONOS hosts from ONOS" +
2324 controllerStr )
2325 consistentHostsResult = main.FALSE
2326 main.log.warn( "ONOS" + controllerStr +
2327 " hosts response: " +
2328 repr( hosts[ controller ] ) )
2329 utilities.assert_equals(
2330 expect=main.TRUE,
2331 actual=consistentHostsResult,
2332 onpass="Hosts view is consistent across all ONOS nodes",
2333 onfail="ONOS nodes have different views of hosts" )
Jon Hall94fd0472014-12-08 11:52:42 -08002334
Jon Hallc9eabec2015-06-10 14:33:14 -07002335 main.step( "Hosts information is correct" )
2336 hostsResults = hostsResults and ipResult
2337 utilities.assert_equals(
2338 expect=main.TRUE,
2339 actual=hostsResults,
2340 onpass="Host information is correct",
2341 onfail="Host information is incorrect" )
2342
2343 main.step( "Host attachment points to the network" )
2344 utilities.assert_equals(
2345 expect=True,
2346 actual=hostAttachmentResults,
2347 onpass="Hosts are correctly attached to the network",
2348 onfail="ONOS did not correctly attach hosts to the network" )
2349
2350 # Strongly connected clusters of devices
2351 main.step( "Clusters view is consistent across all ONOS nodes" )
2352 consistentClustersResult = main.TRUE
2353 for controller in range( len( clusters ) ):
2354 controllerStr = str( controller + 1 )
2355 if "Error" not in clusters[ controller ]:
2356 if clusters[ controller ] == clusters[ 0 ]:
2357 continue
2358 else: # clusters not consistent
2359 main.log.error( "clusters from ONOS" +
2360 controllerStr +
2361 " is inconsistent with ONOS1" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002362 consistentClustersResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002363
Jon Hallc9eabec2015-06-10 14:33:14 -07002364 else:
2365 main.log.error( "Error in getting dataplane clusters " +
2366 "from ONOS" + controllerStr )
2367 consistentClustersResult = main.FALSE
2368 main.log.warn( "ONOS" + controllerStr +
2369 " clusters response: " +
2370 repr( clusters[ controller ] ) )
2371 utilities.assert_equals(
2372 expect=main.TRUE,
2373 actual=consistentClustersResult,
2374 onpass="Clusters view is consistent across all ONOS nodes",
2375 onfail="ONOS nodes have different views of clusters" )
2376
2377 main.step( "There is only one SCC" )
2378 # there should always only be one cluster
2379 try:
2380 numClusters = len( json.loads( clusters[ 0 ] ) )
2381 except ( ValueError, TypeError ):
2382 main.log.exception( "Error parsing clusters[0]: " +
2383 repr( clusters[0] ) )
2384 clusterResults = main.FALSE
2385 if numClusters == 1:
2386 clusterResults = main.TRUE
2387 utilities.assert_equals(
2388 expect=1,
2389 actual=numClusters,
2390 onpass="ONOS shows 1 SCC",
2391 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2392
2393 topoResult = ( devicesResults and portsResults and linksResults
2394 and hostsResults and consistentHostsResult
2395 and consistentClustersResult and clusterResults
2396 and ipResult and hostAttachmentResults )
Jon Hall94fd0472014-12-08 11:52:42 -08002397
Jon Hall8f89dda2015-01-22 16:03:33 -08002398 topoResult = topoResult and int( count <= 2 )
2399 note = "note it takes about " + str( int( cliTime ) ) + \
2400 " seconds for the test to make all the cli calls to fetch " +\
2401 "the topology from each ONOS instance"
Jon Hall1b8f54a2015-02-04 13:24:20 -08002402 main.log.info(
Jon Hall8f89dda2015-01-22 16:03:33 -08002403 "Very crass estimate for topology discovery/convergence( " +
2404 str( note ) + " ): " + str( elapsed ) + " seconds, " +
Jon Hall6aec96b2015-01-19 14:49:31 -08002405 str( count ) + " tries" )
Jon Hallc9eabec2015-06-10 14:33:14 -07002406
2407 main.step( "Device information is correct" )
2408 utilities.assert_equals(
2409 expect=main.TRUE,
2410 actual=devicesResults,
2411 onpass="Device information is correct",
2412 onfail="Device information is incorrect" )
2413
2414 main.step( "Port information is correct" )
2415 utilities.assert_equals(
2416 expect=main.TRUE,
2417 actual=portsResults,
2418 onpass="Port information is correct",
2419 onfail="Port information is incorrect" )
2420
2421 main.step( "Links are correct" )
2422 utilities.assert_equals(
2423 expect=main.TRUE,
2424 actual=linksResults,
2425 onpass="Link are correct",
2426 onfail="Links are incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002427
Jon Halla9d26da2015-03-30 16:45:32 -07002428 # FIXME: move this to an ONOS state case
2429 main.step( "Checking ONOS nodes" )
2430 nodesOutput = []
Jon Hall390696c2015-05-05 17:13:41 -07002431 nodeResults = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002432 threads = []
2433 for i in range( numControllers ):
2434 t = main.Thread( target=CLIs[i].nodes,
2435 name="nodes-" + str( i ),
2436 args=[ ] )
2437 threads.append( t )
2438 t.start()
2439
2440 for t in threads:
2441 t.join()
2442 nodesOutput.append( t.result )
2443 ips = [ node.ip_address for node in nodes ]
2444 for i in nodesOutput:
2445 try:
2446 current = json.loads( i )
2447 for node in current:
Jon Hall390696c2015-05-05 17:13:41 -07002448 currentResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002449 if node['ip'] in ips: # node in nodes() output is in cell
2450 if node['state'] == 'ACTIVE':
Jon Hall390696c2015-05-05 17:13:41 -07002451 currentResult = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002452 else:
2453 main.log.error( "Error in ONOS node availability" )
2454 main.log.error(
2455 json.dumps( current,
2456 sort_keys=True,
2457 indent=4,
2458 separators=( ',', ': ' ) ) )
2459 break
Jon Hall390696c2015-05-05 17:13:41 -07002460 nodeResults = nodeResults and currentResult
Jon Halla9d26da2015-03-30 16:45:32 -07002461 except ( ValueError, TypeError ):
2462 main.log.error( "Error parsing nodes output" )
2463 main.log.warn( repr( i ) )
Jon Hall390696c2015-05-05 17:13:41 -07002464 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
2465 onpass="Nodes check successful",
2466 onfail="Nodes check NOT successful" )
Jon Halla9d26da2015-03-30 16:45:32 -07002467
Jon Hall6aec96b2015-01-19 14:49:31 -08002468 def CASE9( self, main ):
2469 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002470 Link s3-s28 down
Jon Hall6aec96b2015-01-19 14:49:31 -08002471 """
2472 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002473 assert numControllers, "numControllers not defined"
2474 assert main, "main not defined"
2475 assert utilities.assert_equals, "utilities.assert_equals not defined"
2476 assert CLIs, "CLIs not defined"
2477 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002478 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002479
Jon Hall8f89dda2015-01-22 16:03:33 -08002480 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002481
Jon Hall6aec96b2015-01-19 14:49:31 -08002482 description = "Turn off a link to ensure that Link Discovery " +\
Jon Hall58c76b72015-02-23 11:09:24 -08002483 "is working properly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002484 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002485
Jon Hall6aec96b2015-01-19 14:49:31 -08002486 main.step( "Kill Link between s3 and s28" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002487 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
Jon Hall58c76b72015-02-23 11:09:24 -08002488 main.log.info( "Waiting " + str( linkSleep ) +
2489 " seconds for link down to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002490 time.sleep( linkSleep )
2491 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002492 onpass="Link down successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002493 onfail="Failed to bring link down" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002494 # TODO do some sort of check here
Jon Hall73cf9cc2014-11-20 22:28:38 -08002495
Jon Hall6aec96b2015-01-19 14:49:31 -08002496 def CASE10( self, main ):
2497 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002498 Link s3-s28 up
Jon Hall6aec96b2015-01-19 14:49:31 -08002499 """
2500 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002501 assert numControllers, "numControllers not defined"
2502 assert main, "main not defined"
2503 assert utilities.assert_equals, "utilities.assert_equals not defined"
2504 assert CLIs, "CLIs not defined"
2505 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002506 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002507
Jon Hall8f89dda2015-01-22 16:03:33 -08002508 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002509
Jon Hall6aec96b2015-01-19 14:49:31 -08002510 description = "Restore a link to ensure that Link Discovery is " + \
Jon Hall63604932015-02-26 17:09:50 -08002511 "working properly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002512 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002513
Jon Hall6aec96b2015-01-19 14:49:31 -08002514 main.step( "Bring link between s3 and s28 back up" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002515 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
Jon Hall58c76b72015-02-23 11:09:24 -08002516 main.log.info( "Waiting " + str( linkSleep ) +
2517 " seconds for link up to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002518 time.sleep( linkSleep )
2519 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002520 onpass="Link up successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002521 onfail="Failed to bring link up" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002522 # TODO do some sort of check here
Jon Hall73cf9cc2014-11-20 22:28:38 -08002523
Jon Hall6aec96b2015-01-19 14:49:31 -08002524 def CASE11( self, main ):
2525 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002526 Switch Down
Jon Hall6aec96b2015-01-19 14:49:31 -08002527 """
2528 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002529 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002530 assert numControllers, "numControllers not defined"
2531 assert main, "main not defined"
2532 assert utilities.assert_equals, "utilities.assert_equals not defined"
2533 assert CLIs, "CLIs not defined"
2534 assert nodes, "nodes not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002535
Jon Hall8f89dda2015-01-22 16:03:33 -08002536 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002537
2538 description = "Killing a switch to ensure it is discovered correctly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002539 main.case( description )
2540 switch = main.params[ 'kill' ][ 'switch' ]
2541 switchDPID = main.params[ 'kill' ][ 'dpid' ]
Jon Hall73cf9cc2014-11-20 22:28:38 -08002542
Jon Hall6aec96b2015-01-19 14:49:31 -08002543 # TODO: Make this switch parameterizable
2544 main.step( "Kill " + switch )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002545 main.log.info( "Deleting " + switch )
Jon Hall8f89dda2015-01-22 16:03:33 -08002546 main.Mininet1.delSwitch( switch )
2547 main.log.info( "Waiting " + str( switchSleep ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002548 " seconds for switch down to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002549 time.sleep( switchSleep )
2550 device = main.ONOScli1.getDevice( dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002551 # Peek at the deleted switch
2552 main.log.warn( str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002553 result = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002554 if device and device[ 'available' ] is False:
Jon Hall94fd0472014-12-08 11:52:42 -08002555 result = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002556 utilities.assert_equals( expect=main.TRUE, actual=result,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002557 onpass="Kill switch successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002558 onfail="Failed to kill switch?" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002559
Jon Hall6aec96b2015-01-19 14:49:31 -08002560 def CASE12( self, main ):
2561 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002562 Switch Up
Jon Hall6aec96b2015-01-19 14:49:31 -08002563 """
2564 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002565 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002566 assert numControllers, "numControllers not defined"
2567 assert main, "main not defined"
2568 assert utilities.assert_equals, "utilities.assert_equals not defined"
2569 assert CLIs, "CLIs not defined"
2570 assert nodes, "nodes not defined"
2571 assert ONOS1Port, "ONOS1Port not defined"
2572 assert ONOS2Port, "ONOS2Port not defined"
2573 assert ONOS3Port, "ONOS3Port not defined"
2574 assert ONOS4Port, "ONOS4Port not defined"
2575 assert ONOS5Port, "ONOS5Port not defined"
2576 assert ONOS6Port, "ONOS6Port not defined"
2577 assert ONOS7Port, "ONOS7Port not defined"
Jon Hall669173b2014-12-17 11:36:30 -08002578
Jon Hall8f89dda2015-01-22 16:03:33 -08002579 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
Jon Hall6aec96b2015-01-19 14:49:31 -08002580 switch = main.params[ 'kill' ][ 'switch' ]
2581 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2582 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hall73cf9cc2014-11-20 22:28:38 -08002583 description = "Adding a switch to ensure it is discovered correctly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002584 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002585
Jon Hall6aec96b2015-01-19 14:49:31 -08002586 main.step( "Add back " + switch )
Jon Hall8f89dda2015-01-22 16:03:33 -08002587 main.Mininet1.addSwitch( switch, dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002588 for peer in links:
Jon Hall8f89dda2015-01-22 16:03:33 -08002589 main.Mininet1.addLink( switch, peer )
Jon Hall58c76b72015-02-23 11:09:24 -08002590 main.Mininet1.assignSwController( sw=switch.split( 's' )[ 1 ],
2591 count=numControllers,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002592 ip1=nodes[ 0 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002593 port1=ONOS1Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002594 ip2=nodes[ 1 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002595 port2=ONOS2Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002596 ip3=nodes[ 2 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002597 port3=ONOS3Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002598 ip4=nodes[ 3 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002599 port4=ONOS4Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002600 ip5=nodes[ 4 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002601 port5=ONOS5Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002602 ip6=nodes[ 5 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002603 port6=ONOS6Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002604 ip7=nodes[ 6 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002605 port7=ONOS7Port )
2606 main.log.info( "Waiting " + str( switchSleep ) +
2607 " seconds for switch up to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002608 time.sleep( switchSleep )
2609 device = main.ONOScli1.getDevice( dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002610 # Peek at the deleted switch
2611 main.log.warn( str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002612 result = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002613 if device and device[ 'available' ]:
Jon Hall94fd0472014-12-08 11:52:42 -08002614 result = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002615 utilities.assert_equals( expect=main.TRUE, actual=result,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002616 onpass="add switch successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002617 onfail="Failed to add switch?" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002618
Jon Hall6aec96b2015-01-19 14:49:31 -08002619 def CASE13( self, main ):
2620 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002621 Clean up
Jon Hall6aec96b2015-01-19 14:49:31 -08002622 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002623 import os
2624 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002625 assert numControllers, "numControllers not defined"
2626 assert main, "main not defined"
2627 assert utilities.assert_equals, "utilities.assert_equals not defined"
2628 assert CLIs, "CLIs not defined"
2629 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002630
2631 # printing colors to terminal
Jon Hall5cfd23c2015-03-19 11:40:57 -07002632 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2633 'blue': '\033[94m', 'green': '\033[92m',
2634 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
Jon Hall40d2cbd2015-06-03 16:24:29 -07002635 main.case( "Test Cleanup" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002636 main.step( "Killing tcpdumps" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002637 main.Mininet2.stopTcpdump()
Jon Hall73cf9cc2014-11-20 22:28:38 -08002638
Jon Hall6aec96b2015-01-19 14:49:31 -08002639 main.step( "Copying MN pcap and ONOS log files to test station" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002640 testname = main.TEST
Jon Hall8f89dda2015-01-22 16:03:33 -08002641 teststationUser = main.params[ 'TESTONUSER' ]
2642 teststationIP = main.params[ 'TESTONIP' ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002643 # NOTE: MN Pcap file is being saved to ~/packet_captures
Jon Hall73cf9cc2014-11-20 22:28:38 -08002644 # scp this file as MN and TestON aren't necessarily the same vm
Jon Hall6aec96b2015-01-19 14:49:31 -08002645 # FIXME: scp
2646 # mn files
2647 # TODO: Load these from params
2648 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002649 logFolder = "/opt/onos/log/"
2650 logFiles = [ "karaf.log", "karaf.log.1" ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002651 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002652 dstDir = "~/packet_captures/"
2653 for f in logFiles:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002654 for node in nodes:
2655 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2656 ":" + logFolder + f + " " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002657 teststationUser + "@" +
2658 teststationIP + ":" +
2659 dstDir + str( testname ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002660 "-" + node.name + "-" + f )
Jon Hall58c76b72015-02-23 11:09:24 -08002661 main.ONOSbench.handle.expect( "\$" )
2662
Jon Hall6aec96b2015-01-19 14:49:31 -08002663 # std*.log's
2664 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002665 logFolder = "/opt/onos/var/"
2666 logFiles = [ "stderr.log", "stdout.log" ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002667 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002668 dstDir = "~/packet_captures/"
2669 for f in logFiles:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002670 for node in nodes:
2671 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2672 ":" + logFolder + f + " " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002673 teststationUser + "@" +
2674 teststationIP + ":" +
2675 dstDir + str( testname ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002676 "-" + node.name + "-" + f )
Jon Hall58c76b72015-02-23 11:09:24 -08002677 main.ONOSbench.handle.expect( "\$" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002678 # sleep so scp can finish
2679 time.sleep( 10 )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002680
2681 main.step( "Stopping Mininet" )
Jon Hall390696c2015-05-05 17:13:41 -07002682 mnResult = main.Mininet1.stopNet()
2683 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2684 onpass="Mininet stopped",
2685 onfail="MN cleanup NOT successful" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002686
2687 main.step( "Checking ONOS Logs for errors" )
2688 for node in nodes:
2689 print colors[ 'purple' ] + "Checking logs for errors on " + \
2690 node.name + ":" + colors[ 'end' ]
Jon Hall40d2cbd2015-06-03 16:24:29 -07002691 print main.ONOSbench.checkLogs( node.ip_address, restart=True )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002692
Jon Hall6aec96b2015-01-19 14:49:31 -08002693 main.step( "Packing and rotating pcap archives" )
2694 os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002695
Jon Hallfeff3082015-05-19 10:23:26 -07002696 try:
2697 timerLog = open( main.logdir + "/Timers.csv", 'w')
2698 # Overwrite with empty line and close
Jon Hall40d2cbd2015-06-03 16:24:29 -07002699 labels = "Gossip Intents, Restart"
2700 data = str( gossipTime ) + ", " + str( main.restartTime )
2701 timerLog.write( labels + "\n" + data )
Jon Hallfeff3082015-05-19 10:23:26 -07002702 timerLog.close()
2703 except NameError, e:
2704 main.log.exception(e)
2705
Jon Hall6aec96b2015-01-19 14:49:31 -08002706 def CASE14( self, main ):
2707 """
Jon Hall669173b2014-12-17 11:36:30 -08002708 start election app on all onos nodes
Jon Hall6aec96b2015-01-19 14:49:31 -08002709 """
Jon Hall5cfd23c2015-03-19 11:40:57 -07002710 assert numControllers, "numControllers not defined"
2711 assert main, "main not defined"
2712 assert utilities.assert_equals, "utilities.assert_equals not defined"
2713 assert CLIs, "CLIs not defined"
2714 assert nodes, "nodes not defined"
2715
Jon Hall390696c2015-05-05 17:13:41 -07002716 main.case("Start Leadership Election app")
2717 main.step( "Install leadership election app" )
Jon Hallfeff3082015-05-19 10:23:26 -07002718 appResult = main.ONOScli1.activateApp( "org.onosproject.election" )
2719 utilities.assert_equals(
2720 expect=main.TRUE,
2721 actual=appResult,
2722 onpass="Election app installed",
2723 onfail="Something went wrong with installing Leadership election" )
2724
2725 main.step( "Run for election on each node" )
2726 leaderResult = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002727 leaders = []
2728 for cli in CLIs:
Jon Hall390696c2015-05-05 17:13:41 -07002729 cli.electionTestRun()
2730 for cli in CLIs:
Jon Halla9d26da2015-03-30 16:45:32 -07002731 leader = cli.electionTestLeader()
2732 if leader is None or leader == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002733 main.log.error( cli.name + ": Leader for the election app " +
Jon Halla9d26da2015-03-30 16:45:32 -07002734 "should be an ONOS node, instead got '" +
2735 str( leader ) + "'" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002736 leaderResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002737 leaders.append( leader )
Jon Hall6aec96b2015-01-19 14:49:31 -08002738 utilities.assert_equals(
2739 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002740 actual=leaderResult,
Jon Hallfeff3082015-05-19 10:23:26 -07002741 onpass="Successfully ran for leadership",
2742 onfail="Failed to run for leadership" )
2743
2744 main.step( "Check that each node shows the same leader" )
2745 sameLeader = main.TRUE
2746 if len( set( leaders ) ) != 1:
2747 sameLeader = main.FALSE
2748 main.log.error( "Results of electionTestLeader is order of CLIs:" +
2749 str( leaders ) )
2750 utilities.assert_equals(
2751 expect=main.TRUE,
2752 actual=sameLeader,
2753 onpass="Leadership is consistent for the election topic",
2754 onfail="Nodes have different leaders" )
Jon Hall669173b2014-12-17 11:36:30 -08002755
Jon Hall6aec96b2015-01-19 14:49:31 -08002756 def CASE15( self, main ):
2757 """
Jon Hall669173b2014-12-17 11:36:30 -08002758 Check that Leadership Election is still functional
Jon Hall6aec96b2015-01-19 14:49:31 -08002759 """
Jon Hall390696c2015-05-05 17:13:41 -07002760 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002761 assert numControllers, "numControllers not defined"
2762 assert main, "main not defined"
2763 assert utilities.assert_equals, "utilities.assert_equals not defined"
2764 assert CLIs, "CLIs not defined"
2765 assert nodes, "nodes not defined"
2766
Jon Hall8f89dda2015-01-22 16:03:33 -08002767 leaderResult = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08002768 description = "Check that Leadership Election is still functional"
Jon Hall6aec96b2015-01-19 14:49:31 -08002769 main.case( description )
Jon Hallfeff3082015-05-19 10:23:26 -07002770
2771 main.step( "Check that each node shows the same leader" )
2772 sameLeader = main.TRUE
2773 leaders = []
2774 for cli in CLIs:
2775 leader = cli.electionTestLeader()
2776 leaders.append( leader )
2777 if len( set( leaders ) ) != 1:
2778 sameLeader = main.FALSE
2779 main.log.error( "Results of electionTestLeader is order of CLIs:" +
2780 str( leaders ) )
2781 utilities.assert_equals(
2782 expect=main.TRUE,
2783 actual=sameLeader,
2784 onpass="Leadership is consistent for the election topic",
2785 onfail="Nodes have different leaders" )
2786
Jon Hall6aec96b2015-01-19 14:49:31 -08002787 main.step( "Find current leader and withdraw" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002788 leader = main.ONOScli1.electionTestLeader()
Jon Halla9d26da2015-03-30 16:45:32 -07002789 # do some sanity checking on leader before using it
Jon Hall8f89dda2015-01-22 16:03:33 -08002790 withdrawResult = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002791 if leader is None or leader == main.FALSE:
Jon Hallfeff3082015-05-19 10:23:26 -07002792 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -08002793 "Leader for the election app should be an ONOS node," +
Jon Hall58c76b72015-02-23 11:09:24 -08002794 "instead got '" + str( leader ) + "'" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002795 leaderResult = main.FALSE
Jon Hall63604932015-02-26 17:09:50 -08002796 oldLeader = None
Jon Hall5cfd23c2015-03-19 11:40:57 -07002797 for i in range( len( CLIs ) ):
2798 if leader == nodes[ i ].ip_address:
2799 oldLeader = CLIs[ i ]
2800 break
Jon Halla9d26da2015-03-30 16:45:32 -07002801 else: # FOR/ELSE statement
Jon Hall5cfd23c2015-03-19 11:40:57 -07002802 main.log.error( "Leader election, could not find current leader" )
Jon Hall63604932015-02-26 17:09:50 -08002803 if oldLeader:
2804 withdrawResult = oldLeader.electionTestWithdraw()
Jon Hall6aec96b2015-01-19 14:49:31 -08002805 utilities.assert_equals(
2806 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002807 actual=withdrawResult,
Jon Hallfeff3082015-05-19 10:23:26 -07002808 onpass="Node was withdrawn from election",
2809 onfail="Node was not withdrawn from election" )
Jon Hall669173b2014-12-17 11:36:30 -08002810
Jon Hall6aec96b2015-01-19 14:49:31 -08002811 main.step( "Make sure new leader is elected" )
Jon Halla9d26da2015-03-30 16:45:32 -07002812 # FIXME: use threads
Jon Hall8f89dda2015-01-22 16:03:33 -08002813 leaderList = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002814 for cli in CLIs:
2815 leaderN = cli.electionTestLeader()
2816 leaderList.append( leaderN )
Jon Hall669173b2014-12-17 11:36:30 -08002817 if leaderN == leader:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002818 main.log.error( cli.name + " still sees " + str( leader ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002819 " as leader after they withdrew" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002820 leaderResult = main.FALSE
Jon Hall669173b2014-12-17 11:36:30 -08002821 elif leaderN == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002822 # error in response
2823 # TODO: add check for "Command not found:" in the driver, this
Jon Hall5cfd23c2015-03-19 11:40:57 -07002824 # means the app isn't loaded
Jon Hall40d2cbd2015-06-03 16:24:29 -07002825 main.log.error( "Something is wrong with " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002826 "electionTestLeader function, " +
Jon Hall6aec96b2015-01-19 14:49:31 -08002827 "check the error logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002828 leaderResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002829 elif leaderN is None:
2830 # node may not have recieved the event yet
Jon Hall390696c2015-05-05 17:13:41 -07002831 time.sleep(7)
Jon Halla9d26da2015-03-30 16:45:32 -07002832 leaderN = cli.electionTestLeader()
2833 leaderList.pop()
2834 leaderList.append( leaderN )
Jon Hall8f89dda2015-01-22 16:03:33 -08002835 consistentLeader = main.FALSE
2836 if len( set( leaderList ) ) == 1:
Jon Hall6aec96b2015-01-19 14:49:31 -08002837 main.log.info( "Each Election-app sees '" +
Jon Hall8f89dda2015-01-22 16:03:33 -08002838 str( leaderList[ 0 ] ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002839 "' as the leader" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002840 consistentLeader = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08002841 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002842 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -08002843 "Inconsistent responses for leader of Election-app:" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002844 for n in range( len( leaderList ) ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07002845 main.log.error( "ONOS" + str( n + 1 ) + " response: " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002846 str( leaderList[ n ] ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002847 leaderResult = leaderResult and consistentLeader
Jon Hall6aec96b2015-01-19 14:49:31 -08002848 utilities.assert_equals(
2849 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002850 actual=leaderResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002851 onpass="Leadership election passed",
2852 onfail="Something went wrong with Leadership election" )
Jon Hall669173b2014-12-17 11:36:30 -08002853
Jon Hall58c76b72015-02-23 11:09:24 -08002854 main.step( "Run for election on old leader( just so everyone " +
2855 "is in the hat )" )
Jon Hall63604932015-02-26 17:09:50 -08002856 if oldLeader:
2857 runResult = oldLeader.electionTestRun()
2858 else:
2859 runResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002860 utilities.assert_equals(
2861 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002862 actual=runResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002863 onpass="App re-ran for election",
2864 onfail="App failed to run for election" )
Jon Hall390696c2015-05-05 17:13:41 -07002865
Jon Hallfeff3082015-05-19 10:23:26 -07002866 main.step( "Leader did not change when old leader re-ran" )
Jon Hall390696c2015-05-05 17:13:41 -07002867 afterRun = main.ONOScli1.electionTestLeader()
2868 # verify leader didn't just change
2869 if afterRun == leaderList[ 0 ]:
2870 afterResult = main.TRUE
2871 else:
2872 afterResult = main.FALSE
Jon Hall669173b2014-12-17 11:36:30 -08002873
Jon Hall6aec96b2015-01-19 14:49:31 -08002874 utilities.assert_equals(
2875 expect=main.TRUE,
Jon Hall390696c2015-05-05 17:13:41 -07002876 actual=afterResult,
2877 onpass="Old leader successfully re-ran for election",
Jon Hall6aec96b2015-01-19 14:49:31 -08002878 onfail="Something went wrong with Leadership election after " +
2879 "the old leader re-ran for election" )
Jon Hall390696c2015-05-05 17:13:41 -07002880
Jon Hall390696c2015-05-05 17:13:41 -07002881 def CASE16( self, main ):
2882 """
2883 Install Distributed Primitives app
2884 """
Jon Hall40d2cbd2015-06-03 16:24:29 -07002885 import time
Jon Hall390696c2015-05-05 17:13:41 -07002886 assert numControllers, "numControllers not defined"
2887 assert main, "main not defined"
2888 assert utilities.assert_equals, "utilities.assert_equals not defined"
2889 assert CLIs, "CLIs not defined"
2890 assert nodes, "nodes not defined"
2891
2892 # Variables for the distributed primitives tests
2893 global pCounterName
2894 global iCounterName
2895 global pCounterValue
2896 global iCounterValue
2897 global onosSet
2898 global onosSetName
2899 pCounterName = "TestON-Partitions"
2900 iCounterName = "TestON-inMemory"
2901 pCounterValue = 0
2902 iCounterValue = 0
2903 onosSet = set([])
2904 onosSetName = "TestON-set"
2905
2906 description = "Install Primitives app"
2907 main.case( description )
2908 main.step( "Install Primitives app" )
2909 appName = "org.onosproject.distributedprimitives"
2910 appResults = CLIs[0].activateApp( appName )
2911 utilities.assert_equals( expect=main.TRUE,
2912 actual=appResults,
2913 onpass="Primitives app activated",
2914 onfail="Primitives app not activated" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002915 time.sleep( 5 ) # To allow all nodes to activate
Jon Hall390696c2015-05-05 17:13:41 -07002916
2917 def CASE17( self, main ):
2918 """
2919 Check for basic functionality with distributed primitives
2920 """
Jon Hallc9eabec2015-06-10 14:33:14 -07002921 import json
Jon Hall390696c2015-05-05 17:13:41 -07002922 # Make sure variables are defined/set
2923 assert numControllers, "numControllers not defined"
2924 assert main, "main not defined"
2925 assert utilities.assert_equals, "utilities.assert_equals not defined"
2926 assert CLIs, "CLIs not defined"
2927 assert nodes, "nodes not defined"
2928 assert pCounterName, "pCounterName not defined"
2929 assert iCounterName, "iCounterName not defined"
2930 assert onosSetName, "onosSetName not defined"
2931 # NOTE: assert fails if value is 0/None/Empty/False
2932 try:
2933 pCounterValue
2934 except NameError:
2935 main.log.error( "pCounterValue not defined, setting to 0" )
2936 pCounterValue = 0
2937 try:
2938 iCounterValue
2939 except NameError:
2940 main.log.error( "iCounterValue not defined, setting to 0" )
2941 iCounterValue = 0
2942 try:
2943 onosSet
2944 except NameError:
2945 main.log.error( "onosSet not defined, setting to empty Set" )
2946 onosSet = set([])
2947 # Variables for the distributed primitives tests. These are local only
2948 addValue = "a"
2949 addAllValue = "a b c d e f"
2950 retainValue = "c d e f"
2951
2952 description = "Check for basic functionality with distributed " +\
2953 "primitives"
2954 main.case( description )
2955 main.caseExplaination = "Test the methods of the distributed primitives (counters and sets) throught the cli"
2956 # DISTRIBUTED ATOMIC COUNTERS
2957 main.step( "Increment and get a default counter on each node" )
2958 pCounters = []
2959 threads = []
Jon Hallfeff3082015-05-19 10:23:26 -07002960 addedPValues = []
Jon Hall390696c2015-05-05 17:13:41 -07002961 for i in range( numControllers ):
2962 t = main.Thread( target=CLIs[i].counterTestIncrement,
2963 name="counterIncrement-" + str( i ),
2964 args=[ pCounterName ] )
2965 pCounterValue += 1
Jon Hallfeff3082015-05-19 10:23:26 -07002966 addedPValues.append( pCounterValue )
Jon Hall390696c2015-05-05 17:13:41 -07002967 threads.append( t )
2968 t.start()
2969
2970 for t in threads:
2971 t.join()
2972 pCounters.append( t.result )
2973 # Check that counter incremented numController times
2974 pCounterResults = True
Jon Hallfeff3082015-05-19 10:23:26 -07002975 for i in addedPValues:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002976 tmpResult = i in pCounters
Jon Hallfeff3082015-05-19 10:23:26 -07002977 pCounterResults = pCounterResults and tmpResult
2978 if not tmpResult:
2979 main.log.error( str( i ) + " is not in partitioned "
2980 "counter incremented results" )
Jon Hall390696c2015-05-05 17:13:41 -07002981 utilities.assert_equals( expect=True,
2982 actual=pCounterResults,
2983 onpass="Default counter incremented",
2984 onfail="Error incrementing default" +
2985 " counter" )
2986
2987 main.step( "Increment and get an in memory counter on each node" )
2988 iCounters = []
Jon Hallfeff3082015-05-19 10:23:26 -07002989 addedIValues = []
Jon Hall390696c2015-05-05 17:13:41 -07002990 threads = []
2991 for i in range( numControllers ):
2992 t = main.Thread( target=CLIs[i].counterTestIncrement,
2993 name="icounterIncrement-" + str( i ),
2994 args=[ iCounterName ],
2995 kwargs={ "inMemory": True } )
2996 iCounterValue += 1
Jon Hallfeff3082015-05-19 10:23:26 -07002997 addedIValues.append( iCounterValue )
Jon Hall390696c2015-05-05 17:13:41 -07002998 threads.append( t )
2999 t.start()
3000
3001 for t in threads:
3002 t.join()
3003 iCounters.append( t.result )
3004 # Check that counter incremented numController times
3005 iCounterResults = True
Jon Hallfeff3082015-05-19 10:23:26 -07003006 for i in addedIValues:
3007 tmpResult = i in iCounters
3008 iCounterResults = iCounterResults and tmpResult
3009 if not tmpResult:
3010 main.log.error( str( i ) + " is not in the in-memory "
3011 "counter incremented results" )
Jon Hall390696c2015-05-05 17:13:41 -07003012 utilities.assert_equals( expect=True,
3013 actual=iCounterResults,
3014 onpass="In memory counter incremented",
3015 onfail="Error incrementing in memory" +
3016 " counter" )
3017
3018 main.step( "Check counters are consistant across nodes" )
3019 onosCounters = []
3020 threads = []
3021 for i in range( numControllers ):
3022 t = main.Thread( target=CLIs[i].counters,
3023 name="counters-" + str( i ) )
3024 threads.append( t )
3025 t.start()
3026 for t in threads:
3027 t.join()
3028 onosCounters.append( t.result )
3029 tmp = [ i == onosCounters[ 0 ] for i in onosCounters ]
3030 if all( tmp ):
3031 main.log.info( "Counters are consistent across all nodes" )
3032 consistentCounterResults = main.TRUE
3033 else:
3034 main.log.error( "Counters are not consistent across all nodes" )
3035 consistentCounterResults = main.FALSE
3036 utilities.assert_equals( expect=main.TRUE,
3037 actual=consistentCounterResults,
3038 onpass="ONOS counters are consistent " +
3039 "across nodes",
3040 onfail="ONOS Counters are inconsistent " +
3041 "across nodes" )
3042
3043 main.step( "Counters we added have the correct values" )
3044 correctResults = main.TRUE
3045 for i in range( numControllers ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07003046 current = json.loads( onosCounters[i] )
3047 pValue = None
3048 iValue = None
Jon Hall390696c2015-05-05 17:13:41 -07003049 try:
Jon Hall40d2cbd2015-06-03 16:24:29 -07003050 for database in current:
3051 partitioned = database.get( 'partitionedDatabaseCounters' )
3052 if partitioned:
3053 for value in partitioned:
3054 if value.get( 'name' ) == pCounterName:
3055 pValue = value.get( 'value' )
3056 break
3057 inMemory = database.get( 'inMemoryDatabaseCounters' )
3058 if inMemory:
3059 for value in inMemory:
3060 if value.get( 'name' ) == iCounterName:
3061 iValue = value.get( 'value' )
3062 break
Jon Hall390696c2015-05-05 17:13:41 -07003063 except AttributeError, e:
3064 main.log.error( "ONOS" + str( i + 1 ) + " counters result " +
3065 "is not as expected" )
3066 correctResults = main.FALSE
Jon Hall40d2cbd2015-06-03 16:24:29 -07003067 if pValue == pCounterValue:
3068 main.log.info( "Partitioned counter value is correct" )
3069 else:
3070 main.log.error( "Partitioned counter value is incorrect," +
3071 " expected value: " + str( pCounterValue )
3072 + " current value: " + str( pValue ) )
3073 correctResults = main.FALSE
3074 if iValue == iCounterValue:
3075 main.log.info( "In memory counter value is correct" )
3076 else:
3077 main.log.error( "In memory counter value is incorrect, " +
3078 "expected value: " + str( iCounterValue ) +
3079 " current value: " + str( iValue ) )
3080 correctResults = main.FALSE
Jon Hall390696c2015-05-05 17:13:41 -07003081 utilities.assert_equals( expect=main.TRUE,
3082 actual=correctResults,
3083 onpass="Added counters are correct",
3084 onfail="Added counters are incorrect" )
3085 # DISTRIBUTED SETS
3086 main.step( "Distributed Set get" )
3087 size = len( onosSet )
3088 getResponses = []
3089 threads = []
3090 for i in range( numControllers ):
3091 t = main.Thread( target=CLIs[i].setTestGet,
3092 name="setTestGet-" + str( i ),
3093 args=[ onosSetName ] )
3094 threads.append( t )
3095 t.start()
3096 for t in threads:
3097 t.join()
3098 getResponses.append( t.result )
3099
3100 getResults = main.TRUE
3101 for i in range( numControllers ):
3102 if isinstance( getResponses[ i ], list):
3103 current = set( getResponses[ i ] )
3104 if len( current ) == len( getResponses[ i ] ):
3105 # no repeats
3106 if onosSet != current:
3107 main.log.error( "ONOS" + str( i + 1 ) +
3108 " has incorrect view" +
3109 " of set " + onosSetName + ":\n" +
3110 str( getResponses[ i ] ) )
3111 main.log.debug( "Expected: " + str( onosSet ) )
3112 main.log.debug( "Actual: " + str( current ) )
3113 getResults = main.FALSE
3114 else:
3115 # error, set is not a set
3116 main.log.error( "ONOS" + str( i + 1 ) +
3117 " has repeat elements in" +
3118 " set " + onosSetName + ":\n" +
3119 str( getResponses[ i ] ) )
3120 getResults = main.FALSE
3121 elif getResponses[ i ] == main.ERROR:
3122 getResults = main.FALSE
3123 utilities.assert_equals( expect=main.TRUE,
3124 actual=getResults,
3125 onpass="Set elements are correct",
3126 onfail="Set elements are incorrect" )
3127
3128 main.step( "Distributed Set size" )
3129 sizeResponses = []
3130 threads = []
3131 for i in range( numControllers ):
3132 t = main.Thread( target=CLIs[i].setTestSize,
3133 name="setTestSize-" + str( i ),
3134 args=[ onosSetName ] )
3135 threads.append( t )
3136 t.start()
3137 for t in threads:
3138 t.join()
3139 sizeResponses.append( t.result )
3140
3141 sizeResults = main.TRUE
3142 for i in range( numControllers ):
3143 if size != sizeResponses[ i ]:
3144 sizeResults = main.FALSE
3145 main.log.error( "ONOS" + str( i + 1 ) +
3146 " expected a size of " + str( size ) +
3147 " for set " + onosSetName +
3148 " but got " + str( sizeResponses[ i ] ) )
3149 utilities.assert_equals( expect=main.TRUE,
3150 actual=sizeResults,
3151 onpass="Set sizes are correct",
3152 onfail="Set sizes are incorrect" )
3153
3154 main.step( "Distributed Set add()" )
3155 onosSet.add( addValue )
3156 addResponses = []
3157 threads = []
3158 for i in range( numControllers ):
3159 t = main.Thread( target=CLIs[i].setTestAdd,
3160 name="setTestAdd-" + str( i ),
3161 args=[ onosSetName, addValue ] )
3162 threads.append( t )
3163 t.start()
3164 for t in threads:
3165 t.join()
3166 addResponses.append( t.result )
3167
3168 # main.TRUE = successfully changed the set
3169 # main.FALSE = action resulted in no change in set
3170 # main.ERROR - Some error in executing the function
3171 addResults = main.TRUE
3172 for i in range( numControllers ):
3173 if addResponses[ i ] == main.TRUE:
3174 # All is well
3175 pass
3176 elif addResponses[ i ] == main.FALSE:
3177 # Already in set, probably fine
3178 pass
3179 elif addResponses[ i ] == main.ERROR:
3180 # Error in execution
3181 addResults = main.FALSE
3182 else:
3183 # unexpected result
3184 addResults = main.FALSE
3185 if addResults != main.TRUE:
3186 main.log.error( "Error executing set add" )
3187
3188 # Check if set is still correct
3189 size = len( onosSet )
3190 getResponses = []
3191 threads = []
3192 for i in range( numControllers ):
3193 t = main.Thread( target=CLIs[i].setTestGet,
3194 name="setTestGet-" + str( i ),
3195 args=[ onosSetName ] )
3196 threads.append( t )
3197 t.start()
3198 for t in threads:
3199 t.join()
3200 getResponses.append( t.result )
3201 getResults = main.TRUE
3202 for i in range( numControllers ):
3203 if isinstance( getResponses[ i ], list):
3204 current = set( getResponses[ i ] )
3205 if len( current ) == len( getResponses[ i ] ):
3206 # no repeats
3207 if onosSet != current:
3208 main.log.error( "ONOS" + str( i + 1 ) +
3209 " has incorrect view" +
3210 " of set " + onosSetName + ":\n" +
3211 str( getResponses[ i ] ) )
3212 main.log.debug( "Expected: " + str( onosSet ) )
3213 main.log.debug( "Actual: " + str( current ) )
3214 getResults = main.FALSE
3215 else:
3216 # error, set is not a set
3217 main.log.error( "ONOS" + str( i + 1 ) +
3218 " has repeat elements in" +
3219 " set " + onosSetName + ":\n" +
3220 str( getResponses[ i ] ) )
3221 getResults = main.FALSE
3222 elif getResponses[ i ] == main.ERROR:
3223 getResults = main.FALSE
3224 sizeResponses = []
3225 threads = []
3226 for i in range( numControllers ):
3227 t = main.Thread( target=CLIs[i].setTestSize,
3228 name="setTestSize-" + str( i ),
3229 args=[ onosSetName ] )
3230 threads.append( t )
3231 t.start()
3232 for t in threads:
3233 t.join()
3234 sizeResponses.append( t.result )
3235 sizeResults = main.TRUE
3236 for i in range( numControllers ):
3237 if size != sizeResponses[ i ]:
3238 sizeResults = main.FALSE
3239 main.log.error( "ONOS" + str( i + 1 ) +
3240 " expected a size of " + str( size ) +
3241 " for set " + onosSetName +
3242 " but got " + str( sizeResponses[ i ] ) )
3243 addResults = addResults and getResults and sizeResults
3244 utilities.assert_equals( expect=main.TRUE,
3245 actual=addResults,
3246 onpass="Set add correct",
3247 onfail="Set add was incorrect" )
3248
3249 main.step( "Distributed Set addAll()" )
3250 onosSet.update( addAllValue.split() )
3251 addResponses = []
3252 threads = []
3253 for i in range( numControllers ):
3254 t = main.Thread( target=CLIs[i].setTestAdd,
3255 name="setTestAddAll-" + str( i ),
3256 args=[ onosSetName, addAllValue ] )
3257 threads.append( t )
3258 t.start()
3259 for t in threads:
3260 t.join()
3261 addResponses.append( t.result )
3262
3263 # main.TRUE = successfully changed the set
3264 # main.FALSE = action resulted in no change in set
3265 # main.ERROR - Some error in executing the function
3266 addAllResults = main.TRUE
3267 for i in range( numControllers ):
3268 if addResponses[ i ] == main.TRUE:
3269 # All is well
3270 pass
3271 elif addResponses[ i ] == main.FALSE:
3272 # Already in set, probably fine
3273 pass
3274 elif addResponses[ i ] == main.ERROR:
3275 # Error in execution
3276 addAllResults = main.FALSE
3277 else:
3278 # unexpected result
3279 addAllResults = main.FALSE
3280 if addAllResults != main.TRUE:
3281 main.log.error( "Error executing set addAll" )
3282
3283 # Check if set is still correct
3284 size = len( onosSet )
3285 getResponses = []
3286 threads = []
3287 for i in range( numControllers ):
3288 t = main.Thread( target=CLIs[i].setTestGet,
3289 name="setTestGet-" + str( i ),
3290 args=[ onosSetName ] )
3291 threads.append( t )
3292 t.start()
3293 for t in threads:
3294 t.join()
3295 getResponses.append( t.result )
3296 getResults = main.TRUE
3297 for i in range( numControllers ):
3298 if isinstance( getResponses[ i ], list):
3299 current = set( getResponses[ i ] )
3300 if len( current ) == len( getResponses[ i ] ):
3301 # no repeats
3302 if onosSet != current:
3303 main.log.error( "ONOS" + str( i + 1 ) +
3304 " has incorrect view" +
3305 " of set " + onosSetName + ":\n" +
3306 str( getResponses[ i ] ) )
3307 main.log.debug( "Expected: " + str( onosSet ) )
3308 main.log.debug( "Actual: " + str( current ) )
3309 getResults = main.FALSE
3310 else:
3311 # error, set is not a set
3312 main.log.error( "ONOS" + str( i + 1 ) +
3313 " has repeat elements in" +
3314 " set " + onosSetName + ":\n" +
3315 str( getResponses[ i ] ) )
3316 getResults = main.FALSE
3317 elif getResponses[ i ] == main.ERROR:
3318 getResults = main.FALSE
3319 sizeResponses = []
3320 threads = []
3321 for i in range( numControllers ):
3322 t = main.Thread( target=CLIs[i].setTestSize,
3323 name="setTestSize-" + str( i ),
3324 args=[ onosSetName ] )
3325 threads.append( t )
3326 t.start()
3327 for t in threads:
3328 t.join()
3329 sizeResponses.append( t.result )
3330 sizeResults = main.TRUE
3331 for i in range( numControllers ):
3332 if size != sizeResponses[ i ]:
3333 sizeResults = main.FALSE
3334 main.log.error( "ONOS" + str( i + 1 ) +
3335 " expected a size of " + str( size ) +
3336 " for set " + onosSetName +
3337 " but got " + str( sizeResponses[ i ] ) )
3338 addAllResults = addAllResults and getResults and sizeResults
3339 utilities.assert_equals( expect=main.TRUE,
3340 actual=addAllResults,
3341 onpass="Set addAll correct",
3342 onfail="Set addAll was incorrect" )
3343
3344 main.step( "Distributed Set contains()" )
3345 containsResponses = []
3346 threads = []
3347 for i in range( numControllers ):
3348 t = main.Thread( target=CLIs[i].setTestGet,
3349 name="setContains-" + str( i ),
3350 args=[ onosSetName ],
3351 kwargs={ "values": addValue } )
3352 threads.append( t )
3353 t.start()
3354 for t in threads:
3355 t.join()
3356 # NOTE: This is the tuple
3357 containsResponses.append( t.result )
3358
3359 containsResults = main.TRUE
3360 for i in range( numControllers ):
3361 if containsResponses[ i ] == main.ERROR:
3362 containsResults = main.FALSE
3363 else:
3364 containsResults = containsResults and\
3365 containsResponses[ i ][ 1 ]
3366 utilities.assert_equals( expect=main.TRUE,
3367 actual=containsResults,
3368 onpass="Set contains is functional",
3369 onfail="Set contains failed" )
3370
3371 main.step( "Distributed Set containsAll()" )
3372 containsAllResponses = []
3373 threads = []
3374 for i in range( numControllers ):
3375 t = main.Thread( target=CLIs[i].setTestGet,
3376 name="setContainsAll-" + str( i ),
3377 args=[ onosSetName ],
3378 kwargs={ "values": addAllValue } )
3379 threads.append( t )
3380 t.start()
3381 for t in threads:
3382 t.join()
3383 # NOTE: This is the tuple
3384 containsAllResponses.append( t.result )
3385
3386 containsAllResults = main.TRUE
3387 for i in range( numControllers ):
3388 if containsResponses[ i ] == main.ERROR:
3389 containsResults = main.FALSE
3390 else:
3391 containsResults = containsResults and\
3392 containsResponses[ i ][ 1 ]
3393 utilities.assert_equals( expect=main.TRUE,
3394 actual=containsAllResults,
3395 onpass="Set containsAll is functional",
3396 onfail="Set containsAll failed" )
3397
3398 main.step( "Distributed Set remove()" )
3399 onosSet.remove( addValue )
3400 removeResponses = []
3401 threads = []
3402 for i in range( numControllers ):
3403 t = main.Thread( target=CLIs[i].setTestRemove,
3404 name="setTestRemove-" + str( i ),
3405 args=[ onosSetName, addValue ] )
3406 threads.append( t )
3407 t.start()
3408 for t in threads:
3409 t.join()
3410 removeResponses.append( t.result )
3411
3412 # main.TRUE = successfully changed the set
3413 # main.FALSE = action resulted in no change in set
3414 # main.ERROR - Some error in executing the function
3415 removeResults = main.TRUE
3416 for i in range( numControllers ):
3417 if removeResponses[ i ] == main.TRUE:
3418 # All is well
3419 pass
3420 elif removeResponses[ i ] == main.FALSE:
3421 # not in set, probably fine
3422 pass
3423 elif removeResponses[ i ] == main.ERROR:
3424 # Error in execution
3425 removeResults = main.FALSE
3426 else:
3427 # unexpected result
3428 removeResults = main.FALSE
3429 if removeResults != main.TRUE:
3430 main.log.error( "Error executing set remove" )
3431
3432 # Check if set is still correct
3433 size = len( onosSet )
3434 getResponses = []
3435 threads = []
3436 for i in range( numControllers ):
3437 t = main.Thread( target=CLIs[i].setTestGet,
3438 name="setTestGet-" + str( i ),
3439 args=[ onosSetName ] )
3440 threads.append( t )
3441 t.start()
3442 for t in threads:
3443 t.join()
3444 getResponses.append( t.result )
3445 getResults = main.TRUE
3446 for i in range( numControllers ):
3447 if isinstance( getResponses[ i ], list):
3448 current = set( getResponses[ i ] )
3449 if len( current ) == len( getResponses[ i ] ):
3450 # no repeats
3451 if onosSet != current:
3452 main.log.error( "ONOS" + str( i + 1 ) +
3453 " has incorrect view" +
3454 " of set " + onosSetName + ":\n" +
3455 str( getResponses[ i ] ) )
3456 main.log.debug( "Expected: " + str( onosSet ) )
3457 main.log.debug( "Actual: " + str( current ) )
3458 getResults = main.FALSE
3459 else:
3460 # error, set is not a set
3461 main.log.error( "ONOS" + str( i + 1 ) +
3462 " has repeat elements in" +
3463 " set " + onosSetName + ":\n" +
3464 str( getResponses[ i ] ) )
3465 getResults = main.FALSE
3466 elif getResponses[ i ] == main.ERROR:
3467 getResults = main.FALSE
3468 sizeResponses = []
3469 threads = []
3470 for i in range( numControllers ):
3471 t = main.Thread( target=CLIs[i].setTestSize,
3472 name="setTestSize-" + str( i ),
3473 args=[ onosSetName ] )
3474 threads.append( t )
3475 t.start()
3476 for t in threads:
3477 t.join()
3478 sizeResponses.append( t.result )
3479 sizeResults = main.TRUE
3480 for i in range( numControllers ):
3481 if size != sizeResponses[ i ]:
3482 sizeResults = main.FALSE
3483 main.log.error( "ONOS" + str( i + 1 ) +
3484 " expected a size of " + str( size ) +
3485 " for set " + onosSetName +
3486 " but got " + str( sizeResponses[ i ] ) )
3487 removeResults = removeResults and getResults and sizeResults
3488 utilities.assert_equals( expect=main.TRUE,
3489 actual=removeResults,
3490 onpass="Set remove correct",
3491 onfail="Set remove was incorrect" )
3492
3493 main.step( "Distributed Set removeAll()" )
3494 onosSet.difference_update( addAllValue.split() )
3495 removeAllResponses = []
3496 threads = []
3497 try:
3498 for i in range( numControllers ):
3499 t = main.Thread( target=CLIs[i].setTestRemove,
3500 name="setTestRemoveAll-" + str( i ),
3501 args=[ onosSetName, addAllValue ] )
3502 threads.append( t )
3503 t.start()
3504 for t in threads:
3505 t.join()
3506 removeAllResponses.append( t.result )
3507 except Exception, e:
3508 main.log.exception(e)
3509
3510 # main.TRUE = successfully changed the set
3511 # main.FALSE = action resulted in no change in set
3512 # main.ERROR - Some error in executing the function
3513 removeAllResults = main.TRUE
3514 for i in range( numControllers ):
3515 if removeAllResponses[ i ] == main.TRUE:
3516 # All is well
3517 pass
3518 elif removeAllResponses[ i ] == main.FALSE:
3519 # not in set, probably fine
3520 pass
3521 elif removeAllResponses[ i ] == main.ERROR:
3522 # Error in execution
3523 removeAllResults = main.FALSE
3524 else:
3525 # unexpected result
3526 removeAllResults = main.FALSE
3527 if removeAllResults != main.TRUE:
3528 main.log.error( "Error executing set removeAll" )
3529
3530 # Check if set is still correct
3531 size = len( onosSet )
3532 getResponses = []
3533 threads = []
3534 for i in range( numControllers ):
3535 t = main.Thread( target=CLIs[i].setTestGet,
3536 name="setTestGet-" + str( i ),
3537 args=[ onosSetName ] )
3538 threads.append( t )
3539 t.start()
3540 for t in threads:
3541 t.join()
3542 getResponses.append( t.result )
3543 getResults = main.TRUE
3544 for i in range( numControllers ):
3545 if isinstance( getResponses[ i ], list):
3546 current = set( getResponses[ i ] )
3547 if len( current ) == len( getResponses[ i ] ):
3548 # no repeats
3549 if onosSet != current:
3550 main.log.error( "ONOS" + str( i + 1 ) +
3551 " has incorrect view" +
3552 " of set " + onosSetName + ":\n" +
3553 str( getResponses[ i ] ) )
3554 main.log.debug( "Expected: " + str( onosSet ) )
3555 main.log.debug( "Actual: " + str( current ) )
3556 getResults = main.FALSE
3557 else:
3558 # error, set is not a set
3559 main.log.error( "ONOS" + str( i + 1 ) +
3560 " has repeat elements in" +
3561 " set " + onosSetName + ":\n" +
3562 str( getResponses[ i ] ) )
3563 getResults = main.FALSE
3564 elif getResponses[ i ] == main.ERROR:
3565 getResults = main.FALSE
3566 sizeResponses = []
3567 threads = []
3568 for i in range( numControllers ):
3569 t = main.Thread( target=CLIs[i].setTestSize,
3570 name="setTestSize-" + str( i ),
3571 args=[ onosSetName ] )
3572 threads.append( t )
3573 t.start()
3574 for t in threads:
3575 t.join()
3576 sizeResponses.append( t.result )
3577 sizeResults = main.TRUE
3578 for i in range( numControllers ):
3579 if size != sizeResponses[ i ]:
3580 sizeResults = main.FALSE
3581 main.log.error( "ONOS" + str( i + 1 ) +
3582 " expected a size of " + str( size ) +
3583 " for set " + onosSetName +
3584 " but got " + str( sizeResponses[ i ] ) )
3585 removeAllResults = removeAllResults and getResults and sizeResults
3586 utilities.assert_equals( expect=main.TRUE,
3587 actual=removeAllResults,
3588 onpass="Set removeAll correct",
3589 onfail="Set removeAll was incorrect" )
3590
3591 main.step( "Distributed Set addAll()" )
3592 onosSet.update( addAllValue.split() )
3593 addResponses = []
3594 threads = []
3595 for i in range( numControllers ):
3596 t = main.Thread( target=CLIs[i].setTestAdd,
3597 name="setTestAddAll-" + str( i ),
3598 args=[ onosSetName, addAllValue ] )
3599 threads.append( t )
3600 t.start()
3601 for t in threads:
3602 t.join()
3603 addResponses.append( t.result )
3604
3605 # main.TRUE = successfully changed the set
3606 # main.FALSE = action resulted in no change in set
3607 # main.ERROR - Some error in executing the function
3608 addAllResults = main.TRUE
3609 for i in range( numControllers ):
3610 if addResponses[ i ] == main.TRUE:
3611 # All is well
3612 pass
3613 elif addResponses[ i ] == main.FALSE:
3614 # Already in set, probably fine
3615 pass
3616 elif addResponses[ i ] == main.ERROR:
3617 # Error in execution
3618 addAllResults = main.FALSE
3619 else:
3620 # unexpected result
3621 addAllResults = main.FALSE
3622 if addAllResults != main.TRUE:
3623 main.log.error( "Error executing set addAll" )
3624
3625 # Check if set is still correct
3626 size = len( onosSet )
3627 getResponses = []
3628 threads = []
3629 for i in range( numControllers ):
3630 t = main.Thread( target=CLIs[i].setTestGet,
3631 name="setTestGet-" + str( i ),
3632 args=[ onosSetName ] )
3633 threads.append( t )
3634 t.start()
3635 for t in threads:
3636 t.join()
3637 getResponses.append( t.result )
3638 getResults = main.TRUE
3639 for i in range( numControllers ):
3640 if isinstance( getResponses[ i ], list):
3641 current = set( getResponses[ i ] )
3642 if len( current ) == len( getResponses[ i ] ):
3643 # no repeats
3644 if onosSet != current:
3645 main.log.error( "ONOS" + str( i + 1 ) +
3646 " has incorrect view" +
3647 " of set " + onosSetName + ":\n" +
3648 str( getResponses[ i ] ) )
3649 main.log.debug( "Expected: " + str( onosSet ) )
3650 main.log.debug( "Actual: " + str( current ) )
3651 getResults = main.FALSE
3652 else:
3653 # error, set is not a set
3654 main.log.error( "ONOS" + str( i + 1 ) +
3655 " has repeat elements in" +
3656 " set " + onosSetName + ":\n" +
3657 str( getResponses[ i ] ) )
3658 getResults = main.FALSE
3659 elif getResponses[ i ] == main.ERROR:
3660 getResults = main.FALSE
3661 sizeResponses = []
3662 threads = []
3663 for i in range( numControllers ):
3664 t = main.Thread( target=CLIs[i].setTestSize,
3665 name="setTestSize-" + str( i ),
3666 args=[ onosSetName ] )
3667 threads.append( t )
3668 t.start()
3669 for t in threads:
3670 t.join()
3671 sizeResponses.append( t.result )
3672 sizeResults = main.TRUE
3673 for i in range( numControllers ):
3674 if size != sizeResponses[ i ]:
3675 sizeResults = main.FALSE
3676 main.log.error( "ONOS" + str( i + 1 ) +
3677 " expected a size of " + str( size ) +
3678 " for set " + onosSetName +
3679 " but got " + str( sizeResponses[ i ] ) )
3680 addAllResults = addAllResults and getResults and sizeResults
3681 utilities.assert_equals( expect=main.TRUE,
3682 actual=addAllResults,
3683 onpass="Set addAll correct",
3684 onfail="Set addAll was incorrect" )
3685
3686 main.step( "Distributed Set clear()" )
3687 onosSet.clear()
3688 clearResponses = []
3689 threads = []
3690 for i in range( numControllers ):
3691 t = main.Thread( target=CLIs[i].setTestRemove,
3692 name="setTestClear-" + str( i ),
3693 args=[ onosSetName, " "], # Values doesn't matter
3694 kwargs={ "clear": True } )
3695 threads.append( t )
3696 t.start()
3697 for t in threads:
3698 t.join()
3699 clearResponses.append( t.result )
3700
3701 # main.TRUE = successfully changed the set
3702 # main.FALSE = action resulted in no change in set
3703 # main.ERROR - Some error in executing the function
3704 clearResults = main.TRUE
3705 for i in range( numControllers ):
3706 if clearResponses[ i ] == main.TRUE:
3707 # All is well
3708 pass
3709 elif clearResponses[ i ] == main.FALSE:
3710 # Nothing set, probably fine
3711 pass
3712 elif clearResponses[ i ] == main.ERROR:
3713 # Error in execution
3714 clearResults = main.FALSE
3715 else:
3716 # unexpected result
3717 clearResults = main.FALSE
3718 if clearResults != main.TRUE:
3719 main.log.error( "Error executing set clear" )
3720
3721 # Check if set is still correct
3722 size = len( onosSet )
3723 getResponses = []
3724 threads = []
3725 for i in range( numControllers ):
3726 t = main.Thread( target=CLIs[i].setTestGet,
3727 name="setTestGet-" + str( i ),
3728 args=[ onosSetName ] )
3729 threads.append( t )
3730 t.start()
3731 for t in threads:
3732 t.join()
3733 getResponses.append( t.result )
3734 getResults = main.TRUE
3735 for i in range( numControllers ):
3736 if isinstance( getResponses[ i ], list):
3737 current = set( getResponses[ i ] )
3738 if len( current ) == len( getResponses[ i ] ):
3739 # no repeats
3740 if onosSet != current:
3741 main.log.error( "ONOS" + str( i + 1 ) +
3742 " has incorrect view" +
3743 " of set " + onosSetName + ":\n" +
3744 str( getResponses[ i ] ) )
3745 main.log.debug( "Expected: " + str( onosSet ) )
3746 main.log.debug( "Actual: " + str( current ) )
3747 getResults = main.FALSE
3748 else:
3749 # error, set is not a set
3750 main.log.error( "ONOS" + str( i + 1 ) +
3751 " has repeat elements in" +
3752 " set " + onosSetName + ":\n" +
3753 str( getResponses[ i ] ) )
3754 getResults = main.FALSE
3755 elif getResponses[ i ] == main.ERROR:
3756 getResults = main.FALSE
3757 sizeResponses = []
3758 threads = []
3759 for i in range( numControllers ):
3760 t = main.Thread( target=CLIs[i].setTestSize,
3761 name="setTestSize-" + str( i ),
3762 args=[ onosSetName ] )
3763 threads.append( t )
3764 t.start()
3765 for t in threads:
3766 t.join()
3767 sizeResponses.append( t.result )
3768 sizeResults = main.TRUE
3769 for i in range( numControllers ):
3770 if size != sizeResponses[ i ]:
3771 sizeResults = main.FALSE
3772 main.log.error( "ONOS" + str( i + 1 ) +
3773 " expected a size of " + str( size ) +
3774 " for set " + onosSetName +
3775 " but got " + str( sizeResponses[ i ] ) )
3776 clearResults = clearResults and getResults and sizeResults
3777 utilities.assert_equals( expect=main.TRUE,
3778 actual=clearResults,
3779 onpass="Set clear correct",
3780 onfail="Set clear was incorrect" )
3781
3782 main.step( "Distributed Set addAll()" )
3783 onosSet.update( addAllValue.split() )
3784 addResponses = []
3785 threads = []
3786 for i in range( numControllers ):
3787 t = main.Thread( target=CLIs[i].setTestAdd,
3788 name="setTestAddAll-" + str( i ),
3789 args=[ onosSetName, addAllValue ] )
3790 threads.append( t )
3791 t.start()
3792 for t in threads:
3793 t.join()
3794 addResponses.append( t.result )
3795
3796 # main.TRUE = successfully changed the set
3797 # main.FALSE = action resulted in no change in set
3798 # main.ERROR - Some error in executing the function
3799 addAllResults = main.TRUE
3800 for i in range( numControllers ):
3801 if addResponses[ i ] == main.TRUE:
3802 # All is well
3803 pass
3804 elif addResponses[ i ] == main.FALSE:
3805 # Already in set, probably fine
3806 pass
3807 elif addResponses[ i ] == main.ERROR:
3808 # Error in execution
3809 addAllResults = main.FALSE
3810 else:
3811 # unexpected result
3812 addAllResults = main.FALSE
3813 if addAllResults != main.TRUE:
3814 main.log.error( "Error executing set addAll" )
3815
3816 # Check if set is still correct
3817 size = len( onosSet )
3818 getResponses = []
3819 threads = []
3820 for i in range( numControllers ):
3821 t = main.Thread( target=CLIs[i].setTestGet,
3822 name="setTestGet-" + str( i ),
3823 args=[ onosSetName ] )
3824 threads.append( t )
3825 t.start()
3826 for t in threads:
3827 t.join()
3828 getResponses.append( t.result )
3829 getResults = main.TRUE
3830 for i in range( numControllers ):
3831 if isinstance( getResponses[ i ], list):
3832 current = set( getResponses[ i ] )
3833 if len( current ) == len( getResponses[ i ] ):
3834 # no repeats
3835 if onosSet != current:
3836 main.log.error( "ONOS" + str( i + 1 ) +
3837 " has incorrect view" +
3838 " of set " + onosSetName + ":\n" +
3839 str( getResponses[ i ] ) )
3840 main.log.debug( "Expected: " + str( onosSet ) )
3841 main.log.debug( "Actual: " + str( current ) )
3842 getResults = main.FALSE
3843 else:
3844 # error, set is not a set
3845 main.log.error( "ONOS" + str( i + 1 ) +
3846 " has repeat elements in" +
3847 " set " + onosSetName + ":\n" +
3848 str( getResponses[ i ] ) )
3849 getResults = main.FALSE
3850 elif getResponses[ i ] == main.ERROR:
3851 getResults = main.FALSE
3852 sizeResponses = []
3853 threads = []
3854 for i in range( numControllers ):
3855 t = main.Thread( target=CLIs[i].setTestSize,
3856 name="setTestSize-" + str( i ),
3857 args=[ onosSetName ] )
3858 threads.append( t )
3859 t.start()
3860 for t in threads:
3861 t.join()
3862 sizeResponses.append( t.result )
3863 sizeResults = main.TRUE
3864 for i in range( numControllers ):
3865 if size != sizeResponses[ i ]:
3866 sizeResults = main.FALSE
3867 main.log.error( "ONOS" + str( i + 1 ) +
3868 " expected a size of " + str( size ) +
3869 " for set " + onosSetName +
3870 " but got " + str( sizeResponses[ i ] ) )
3871 addAllResults = addAllResults and getResults and sizeResults
3872 utilities.assert_equals( expect=main.TRUE,
3873 actual=addAllResults,
3874 onpass="Set addAll correct",
3875 onfail="Set addAll was incorrect" )
3876
3877 main.step( "Distributed Set retain()" )
3878 onosSet.intersection_update( retainValue.split() )
3879 retainResponses = []
3880 threads = []
3881 for i in range( numControllers ):
3882 t = main.Thread( target=CLIs[i].setTestRemove,
3883 name="setTestRetain-" + str( i ),
3884 args=[ onosSetName, retainValue ],
3885 kwargs={ "retain": True } )
3886 threads.append( t )
3887 t.start()
3888 for t in threads:
3889 t.join()
3890 retainResponses.append( t.result )
3891
3892 # main.TRUE = successfully changed the set
3893 # main.FALSE = action resulted in no change in set
3894 # main.ERROR - Some error in executing the function
3895 retainResults = main.TRUE
3896 for i in range( numControllers ):
3897 if retainResponses[ i ] == main.TRUE:
3898 # All is well
3899 pass
3900 elif retainResponses[ i ] == main.FALSE:
3901 # Already in set, probably fine
3902 pass
3903 elif retainResponses[ i ] == main.ERROR:
3904 # Error in execution
3905 retainResults = main.FALSE
3906 else:
3907 # unexpected result
3908 retainResults = main.FALSE
3909 if retainResults != main.TRUE:
3910 main.log.error( "Error executing set retain" )
3911
3912 # Check if set is still correct
3913 size = len( onosSet )
3914 getResponses = []
3915 threads = []
3916 for i in range( numControllers ):
3917 t = main.Thread( target=CLIs[i].setTestGet,
3918 name="setTestGet-" + str( i ),
3919 args=[ onosSetName ] )
3920 threads.append( t )
3921 t.start()
3922 for t in threads:
3923 t.join()
3924 getResponses.append( t.result )
3925 getResults = main.TRUE
3926 for i in range( numControllers ):
3927 if isinstance( getResponses[ i ], list):
3928 current = set( getResponses[ i ] )
3929 if len( current ) == len( getResponses[ i ] ):
3930 # no repeats
3931 if onosSet != current:
3932 main.log.error( "ONOS" + str( i + 1 ) +
3933 " has incorrect view" +
3934 " of set " + onosSetName + ":\n" +
3935 str( getResponses[ i ] ) )
3936 main.log.debug( "Expected: " + str( onosSet ) )
3937 main.log.debug( "Actual: " + str( current ) )
3938 getResults = main.FALSE
3939 else:
3940 # error, set is not a set
3941 main.log.error( "ONOS" + str( i + 1 ) +
3942 " has repeat elements in" +
3943 " set " + onosSetName + ":\n" +
3944 str( getResponses[ i ] ) )
3945 getResults = main.FALSE
3946 elif getResponses[ i ] == main.ERROR:
3947 getResults = main.FALSE
3948 sizeResponses = []
3949 threads = []
3950 for i in range( numControllers ):
3951 t = main.Thread( target=CLIs[i].setTestSize,
3952 name="setTestSize-" + str( i ),
3953 args=[ onosSetName ] )
3954 threads.append( t )
3955 t.start()
3956 for t in threads:
3957 t.join()
3958 sizeResponses.append( t.result )
3959 sizeResults = main.TRUE
3960 for i in range( numControllers ):
3961 if size != sizeResponses[ i ]:
3962 sizeResults = main.FALSE
3963 main.log.error( "ONOS" + str( i + 1 ) +
3964 " expected a size of " +
3965 str( size ) + " for set " + onosSetName +
3966 " but got " + str( sizeResponses[ i ] ) )
3967 retainResults = retainResults and getResults and sizeResults
3968 utilities.assert_equals( expect=main.TRUE,
3969 actual=retainResults,
3970 onpass="Set retain correct",
3971 onfail="Set retain was incorrect" )
3972