blob: b5ab25e572a055643e7e9a4d91155a401efea9ee [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 Hallb6a54872015-06-12 14:02:42 -0700668 main.log.warn( "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 Hall73cf9cc2014-11-20 22:28:38 -08001085
Jon Hall6aec96b2015-01-19 14:49:31 -08001086 main.case( "Setting up and gathering data for current state" )
1087 # The general idea for this test case is to pull the state of
1088 # ( intents,flows, topology,... ) from each ONOS node
Jon Hall5cfd23c2015-03-19 11:40:57 -07001089 # We can then compare them with each other and also with past states
Jon Hall73cf9cc2014-11-20 22:28:38 -08001090
Jon Hall5cfd23c2015-03-19 11:40:57 -07001091 main.step( "Check that each switch has a master" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001092 global mastershipState
Jon Hall5cfd23c2015-03-19 11:40:57 -07001093 mastershipState = '[]'
Jon Hall94fd0472014-12-08 11:52:42 -08001094
Jon Hall6aec96b2015-01-19 14:49:31 -08001095 # Assert that each device has a master
Jon Hall5cfd23c2015-03-19 11:40:57 -07001096 rolesNotNull = main.TRUE
1097 threads = []
1098 for i in range( numControllers ):
1099 t = main.Thread( target=CLIs[i].rolesNotNull,
1100 name="rolesNotNull-" + str( i ),
1101 args=[] )
1102 threads.append( t )
1103 t.start()
1104
1105 for t in threads:
1106 t.join()
1107 rolesNotNull = rolesNotNull and t.result
Jon Hall6aec96b2015-01-19 14:49:31 -08001108 utilities.assert_equals(
1109 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001110 actual=rolesNotNull,
Jon Hall6aec96b2015-01-19 14:49:31 -08001111 onpass="Each device has a master",
1112 onfail="Some devices don't have a master assigned" )
Jon Hall94fd0472014-12-08 11:52:42 -08001113
Jon Hall5cfd23c2015-03-19 11:40:57 -07001114 main.step( "Get the Mastership of each switch from each controller" )
1115 ONOSMastership = []
1116 mastershipCheck = main.FALSE
1117 consistentMastership = True
1118 rolesResults = True
1119 threads = []
1120 for i in range( numControllers ):
1121 t = main.Thread( target=CLIs[i].roles,
1122 name="roles-" + str( i ),
1123 args=[] )
1124 threads.append( t )
1125 t.start()
1126
1127 for t in threads:
1128 t.join()
1129 ONOSMastership.append( t.result )
1130
1131 for i in range( numControllers ):
1132 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001133 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001134 " roles" )
1135 main.log.warn(
1136 "ONOS" + str( i + 1 ) + " mastership response: " +
1137 repr( ONOSMastership[i] ) )
1138 rolesResults = False
1139 utilities.assert_equals(
1140 expect=True,
1141 actual=rolesResults,
1142 onpass="No error in reading roles output",
1143 onfail="Error in reading roles from ONOS" )
1144
1145 main.step( "Check for consistency in roles from each controller" )
1146 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001147 main.log.info(
Jon Hall6aec96b2015-01-19 14:49:31 -08001148 "Switch roles are consistent across all ONOS nodes" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001149 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001150 consistentMastership = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001151 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001152 expect=True,
Jon Hall8f89dda2015-01-22 16:03:33 -08001153 actual=consistentMastership,
Jon Hall6aec96b2015-01-19 14:49:31 -08001154 onpass="Switch roles are consistent across all ONOS nodes",
1155 onfail="ONOS nodes have different views of switch roles" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001156
Jon Hall5cfd23c2015-03-19 11:40:57 -07001157 if rolesResults and not consistentMastership:
1158 for i in range( numControllers ):
1159 try:
1160 main.log.warn(
1161 "ONOS" + str( i + 1 ) + " roles: ",
1162 json.dumps(
1163 json.loads( ONOSMastership[ i ] ),
1164 sort_keys=True,
1165 indent=4,
1166 separators=( ',', ': ' ) ) )
1167 except ( ValueError, TypeError ):
1168 main.log.warn( repr( ONOSMastership[ i ] ) )
1169 elif rolesResults and consistentMastership:
1170 mastershipCheck = main.TRUE
1171 mastershipState = ONOSMastership[ 0 ]
1172
Jon Hall6aec96b2015-01-19 14:49:31 -08001173 main.step( "Get the intents from each controller" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001174 global intentState
1175 intentState = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001176 ONOSIntents = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001177 intentCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001178 consistentIntents = True
1179 intentsResults = True
1180 threads = []
1181 for i in range( numControllers ):
1182 t = main.Thread( target=CLIs[i].intents,
1183 name="intents-" + str( i ),
1184 args=[],
1185 kwargs={ 'jsonFormat': True } )
1186 threads.append( t )
1187 t.start()
1188
1189 for t in threads:
1190 t.join()
1191 ONOSIntents.append( t.result )
1192
1193 for i in range( numControllers ):
1194 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001195 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001196 " intents" )
1197 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1198 repr( ONOSIntents[ i ] ) )
1199 intentsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001200 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001201 expect=True,
1202 actual=intentsResults,
1203 onpass="No error in reading intents output",
1204 onfail="Error in reading intents from ONOS" )
1205
1206 main.step( "Check for consistency in Intents from each controller" )
1207 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001208 main.log.info( "Intents are consistent across all ONOS " +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001209 "nodes" )
1210 else:
1211 consistentIntents = False
Jon Hall40d2cbd2015-06-03 16:24:29 -07001212 main.log.error( "Intents not consistent" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001213 utilities.assert_equals(
1214 expect=True,
1215 actual=consistentIntents,
Jon Hall6aec96b2015-01-19 14:49:31 -08001216 onpass="Intents are consistent across all ONOS nodes",
1217 onfail="ONOS nodes have different views of intents" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001218
Jon Hall390696c2015-05-05 17:13:41 -07001219 if intentsResults:
1220 # Try to make it easy to figure out what is happening
1221 #
1222 # Intent ONOS1 ONOS2 ...
1223 # 0x01 INSTALLED INSTALLING
1224 # ... ... ...
1225 # ... ... ...
1226 title = " Id"
1227 for n in range( numControllers ):
1228 title += " " * 10 + "ONOS" + str( n + 1 )
1229 main.log.warn( title )
1230 # get all intent keys in the cluster
1231 keys = []
1232 for nodeStr in ONOSIntents:
1233 node = json.loads( nodeStr )
1234 for intent in node:
1235 keys.append( intent.get( 'id' ) )
1236 keys = set( keys )
1237 for key in keys:
1238 row = "%-13s" % key
1239 for nodeStr in ONOSIntents:
1240 node = json.loads( nodeStr )
1241 for intent in node:
1242 if intent.get( 'id', "Error" ) == key:
1243 row += "%-15s" % intent.get( 'state' )
1244 main.log.warn( row )
1245 # End table view
1246
Jon Hall5cfd23c2015-03-19 11:40:57 -07001247 if intentsResults and not consistentIntents:
Jon Hall390696c2015-05-05 17:13:41 -07001248 # print the json objects
Jon Hall5cfd23c2015-03-19 11:40:57 -07001249 n = len(ONOSIntents)
Jon Hall390696c2015-05-05 17:13:41 -07001250 main.log.debug( "ONOS" + str( n ) + " intents: " )
1251 main.log.debug( json.dumps( json.loads( ONOSIntents[ -1 ] ),
1252 sort_keys=True,
1253 indent=4,
1254 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001255 for i in range( numControllers ):
1256 if ONOSIntents[ i ] != ONOSIntents[ -1 ]:
Jon Hall390696c2015-05-05 17:13:41 -07001257 main.log.debug( "ONOS" + str( i + 1 ) + " intents: " )
1258 main.log.debug( json.dumps( json.loads( ONOSIntents[i] ),
1259 sort_keys=True,
1260 indent=4,
1261 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001262 else:
Jon Hall390696c2015-05-05 17:13:41 -07001263 main.log.debug( nodes[ i ].name + " intents match ONOS" +
1264 str( n ) + " intents" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001265 elif intentsResults and consistentIntents:
1266 intentCheck = main.TRUE
1267 intentState = ONOSIntents[ 0 ]
1268
Jon Hall6aec96b2015-01-19 14:49:31 -08001269 main.step( "Get the flows from each controller" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001270 global flowState
1271 flowState = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001272 ONOSFlows = []
1273 ONOSFlowsJson = []
Jon Hall8f89dda2015-01-22 16:03:33 -08001274 flowCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001275 consistentFlows = True
1276 flowsResults = True
1277 threads = []
1278 for i in range( numControllers ):
1279 t = main.Thread( target=CLIs[i].flows,
1280 name="flows-" + str( i ),
1281 args=[],
1282 kwargs={ 'jsonFormat': True } )
1283 threads.append( t )
1284 t.start()
1285
Jon Halla9d26da2015-03-30 16:45:32 -07001286 # NOTE: Flows command can take some time to run
Jon Hall5cfd23c2015-03-19 11:40:57 -07001287 time.sleep(30)
1288 for t in threads:
1289 t.join()
1290 result = t.result
1291 ONOSFlows.append( result )
1292
1293 for i in range( numControllers ):
1294 num = str( i + 1 )
1295 if not ONOSFlows[ i ] or "Error" in ONOSFlows[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001296 main.log.error( "Error in getting ONOS" + num + " flows" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001297 main.log.warn( "ONOS" + num + " flows response: " +
1298 repr( ONOSFlows[ i ] ) )
1299 flowsResults = False
1300 ONOSFlowsJson.append( None )
Jon Hall58c76b72015-02-23 11:09:24 -08001301 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001302 try:
1303 ONOSFlowsJson.append( json.loads( ONOSFlows[ i ] ) )
1304 except ( ValueError, TypeError ):
1305 # FIXME: change this to log.error?
1306 main.log.exception( "Error in parsing ONOS" + num +
1307 " response as json." )
1308 main.log.error( repr( ONOSFlows[ i ] ) )
1309 ONOSFlowsJson.append( None )
1310 flowsResults = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001311 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001312 expect=True,
1313 actual=flowsResults,
1314 onpass="No error in reading flows output",
1315 onfail="Error in reading flows from ONOS" )
1316
1317 main.step( "Check for consistency in Flows from each controller" )
1318 tmp = [ len( i ) == len( ONOSFlowsJson[ 0 ] ) for i in ONOSFlowsJson ]
1319 if all( tmp ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001320 main.log.info( "Flow count is consistent across all ONOS nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001321 else:
1322 consistentFlows = False
1323 utilities.assert_equals(
1324 expect=True,
1325 actual=consistentFlows,
Jon Hall6aec96b2015-01-19 14:49:31 -08001326 onpass="The flow count is consistent across all ONOS nodes",
1327 onfail="ONOS nodes have different flow counts" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001328
Jon Hall5cfd23c2015-03-19 11:40:57 -07001329 if flowsResults and not consistentFlows:
1330 for i in range( numControllers ):
1331 try:
1332 main.log.warn(
1333 "ONOS" + str( i + 1 ) + " flows: " +
1334 json.dumps( json.loads( ONOSFlows[i] ), sort_keys=True,
1335 indent=4, separators=( ',', ': ' ) ) )
1336 except ( ValueError, TypeError ):
1337 main.log.warn(
1338 "ONOS" + str( i + 1 ) + " flows: " +
1339 repr( ONOSFlows[ i ] ) )
1340 elif flowsResults and consistentFlows:
1341 flowCheck = main.TRUE
1342 flowState = ONOSFlows[ 0 ]
1343
Jon Hall6aec96b2015-01-19 14:49:31 -08001344 main.step( "Get the OF Table entries" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001345 global flows
Jon Hall6aec96b2015-01-19 14:49:31 -08001346 flows = []
1347 for i in range( 1, 29 ):
Jon Hall8f89dda2015-01-22 16:03:33 -08001348 flows.append( main.Mininet2.getFlowTable( 1.3, "s" + str( i ) ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001349 if flowCheck == main.FALSE:
1350 for table in flows:
1351 main.log.warn( table )
Jon Hall6aec96b2015-01-19 14:49:31 -08001352 # TODO: Compare switch flow tables with ONOS flow tables
Jon Hall73cf9cc2014-11-20 22:28:38 -08001353
Jon Hall6aec96b2015-01-19 14:49:31 -08001354 main.step( "Start continuous pings" )
1355 main.Mininet2.pingLong(
1356 src=main.params[ 'PING' ][ 'source1' ],
1357 target=main.params[ 'PING' ][ 'target1' ],
1358 pingTime=500 )
1359 main.Mininet2.pingLong(
1360 src=main.params[ 'PING' ][ 'source2' ],
1361 target=main.params[ 'PING' ][ 'target2' ],
1362 pingTime=500 )
1363 main.Mininet2.pingLong(
1364 src=main.params[ 'PING' ][ 'source3' ],
1365 target=main.params[ 'PING' ][ 'target3' ],
1366 pingTime=500 )
1367 main.Mininet2.pingLong(
1368 src=main.params[ 'PING' ][ 'source4' ],
1369 target=main.params[ 'PING' ][ 'target4' ],
1370 pingTime=500 )
1371 main.Mininet2.pingLong(
1372 src=main.params[ 'PING' ][ 'source5' ],
1373 target=main.params[ 'PING' ][ 'target5' ],
1374 pingTime=500 )
1375 main.Mininet2.pingLong(
1376 src=main.params[ 'PING' ][ 'source6' ],
1377 target=main.params[ 'PING' ][ 'target6' ],
1378 pingTime=500 )
1379 main.Mininet2.pingLong(
1380 src=main.params[ 'PING' ][ 'source7' ],
1381 target=main.params[ 'PING' ][ 'target7' ],
1382 pingTime=500 )
1383 main.Mininet2.pingLong(
1384 src=main.params[ 'PING' ][ 'source8' ],
1385 target=main.params[ 'PING' ][ 'target8' ],
1386 pingTime=500 )
1387 main.Mininet2.pingLong(
1388 src=main.params[ 'PING' ][ 'source9' ],
1389 target=main.params[ 'PING' ][ 'target9' ],
1390 pingTime=500 )
1391 main.Mininet2.pingLong(
1392 src=main.params[ 'PING' ][ 'source10' ],
1393 target=main.params[ 'PING' ][ 'target10' ],
1394 pingTime=500 )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001395
Jon Hall6aec96b2015-01-19 14:49:31 -08001396 main.step( "Collecting topology information from ONOS" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001397 devices = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001398 threads = []
1399 for i in range( numControllers ):
1400 t = main.Thread( target=CLIs[i].devices,
1401 name="devices-" + str( i ),
1402 args=[ ] )
1403 threads.append( t )
1404 t.start()
1405
1406 for t in threads:
1407 t.join()
1408 devices.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001409 hosts = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001410 threads = []
1411 for i in range( numControllers ):
1412 t = main.Thread( target=CLIs[i].hosts,
1413 name="hosts-" + str( i ),
1414 args=[ ] )
1415 threads.append( t )
1416 t.start()
1417
1418 for t in threads:
1419 t.join()
1420 try:
1421 hosts.append( json.loads( t.result ) )
1422 except ( ValueError, TypeError ):
1423 # FIXME: better handling of this, print which node
1424 # Maybe use thread name?
1425 main.log.exception( "Error parsing json output of hosts" )
1426 # FIXME: should this be an empty json object instead?
1427 hosts.append( None )
1428
Jon Hall73cf9cc2014-11-20 22:28:38 -08001429 ports = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001430 threads = []
1431 for i in range( numControllers ):
1432 t = main.Thread( target=CLIs[i].ports,
1433 name="ports-" + str( i ),
1434 args=[ ] )
1435 threads.append( t )
1436 t.start()
1437
1438 for t in threads:
1439 t.join()
1440 ports.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001441 links = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001442 threads = []
1443 for i in range( numControllers ):
1444 t = main.Thread( target=CLIs[i].links,
1445 name="links-" + str( i ),
1446 args=[ ] )
1447 threads.append( t )
1448 t.start()
1449
1450 for t in threads:
1451 t.join()
1452 links.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08001453 clusters = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001454 threads = []
1455 for i in range( numControllers ):
1456 t = main.Thread( target=CLIs[i].clusters,
1457 name="clusters-" + str( i ),
1458 args=[ ] )
1459 threads.append( t )
1460 t.start()
1461
1462 for t in threads:
1463 t.join()
1464 clusters.append( t.result )
Jon Hall529a37f2015-01-28 10:02:00 -08001465 # Compare json objects for hosts and dataplane clusters
Jon Hall94fd0472014-12-08 11:52:42 -08001466
Jon Hall6aec96b2015-01-19 14:49:31 -08001467 # hosts
Jon Hall390696c2015-05-05 17:13:41 -07001468 main.step( "Host view is consistent across ONOS nodes" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001469 consistentHostsResult = main.TRUE
Jon Hall94fd0472014-12-08 11:52:42 -08001470 for controller in range( len( hosts ) ):
Jon Hall8f89dda2015-01-22 16:03:33 -08001471 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08001472 if "Error" not in hosts[ controller ]:
1473 if hosts[ controller ] == hosts[ 0 ]:
Jon Hall94fd0472014-12-08 11:52:42 -08001474 continue
Jon Hall6aec96b2015-01-19 14:49:31 -08001475 else: # hosts not consistent
Jon Hall40d2cbd2015-06-03 16:24:29 -07001476 main.log.error( "hosts from ONOS" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001477 controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001478 " is inconsistent with ONOS1" )
1479 main.log.warn( repr( hosts[ controller ] ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001480 consistentHostsResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08001481
1482 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001483 main.log.error( "Error in getting ONOS hosts from ONOS" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001484 controllerStr )
1485 consistentHostsResult = main.FALSE
1486 main.log.warn( "ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001487 " hosts response: " +
1488 repr( hosts[ controller ] ) )
1489 utilities.assert_equals(
1490 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001491 actual=consistentHostsResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08001492 onpass="Hosts view is consistent across all ONOS nodes",
1493 onfail="ONOS nodes have different views of hosts" )
Jon Hall94fd0472014-12-08 11:52:42 -08001494
Jon Hall390696c2015-05-05 17:13:41 -07001495 main.step( "Each host has an IP address" )
Jon Hall58c76b72015-02-23 11:09:24 -08001496 ipResult = main.TRUE
1497 for controller in range( 0, len( hosts ) ):
1498 controllerStr = str( controller + 1 )
1499 for host in hosts[ controller ]:
Jon Hallfeff3082015-05-19 10:23:26 -07001500 if not host.get( 'ipAddresses', [ ] ):
Jon Hall5cfd23c2015-03-19 11:40:57 -07001501 main.log.error( "DEBUG:Error with host ips on controller" +
1502 controllerStr + ": " + str( host ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001503 ipResult = main.FALSE
1504 utilities.assert_equals(
1505 expect=main.TRUE,
1506 actual=ipResult,
1507 onpass="The ips of the hosts aren't empty",
1508 onfail="The ip of at least one host is missing" )
1509
Jon Hall6aec96b2015-01-19 14:49:31 -08001510 # Strongly connected clusters of devices
Jon Hall390696c2015-05-05 17:13:41 -07001511 main.step( "Cluster view is consistent across ONOS nodes" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001512 consistentClustersResult = main.TRUE
Jon Hall94fd0472014-12-08 11:52:42 -08001513 for controller in range( len( clusters ) ):
Jon Hall5cfd23c2015-03-19 11:40:57 -07001514 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08001515 if "Error" not in clusters[ controller ]:
1516 if clusters[ controller ] == clusters[ 0 ]:
Jon Hall94fd0472014-12-08 11:52:42 -08001517 continue
Jon Hall6aec96b2015-01-19 14:49:31 -08001518 else: # clusters not consistent
Jon Hall40d2cbd2015-06-03 16:24:29 -07001519 main.log.error( "clusters from ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001520 " is inconsistent with ONOS1" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001521 consistentClustersResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08001522
1523 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001524 main.log.error( "Error in getting dataplane clusters " +
Jon Hall8f89dda2015-01-22 16:03:33 -08001525 "from ONOS" + controllerStr )
1526 consistentClustersResult = main.FALSE
1527 main.log.warn( "ONOS" + controllerStr +
Jon Hall6aec96b2015-01-19 14:49:31 -08001528 " clusters response: " +
1529 repr( clusters[ controller ] ) )
1530 utilities.assert_equals(
1531 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001532 actual=consistentClustersResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08001533 onpass="Clusters view is consistent across all ONOS nodes",
1534 onfail="ONOS nodes have different views of clusters" )
1535 # there should always only be one cluster
Jon Hall390696c2015-05-05 17:13:41 -07001536 main.step( "Cluster view correct across ONOS nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001537 try:
1538 numClusters = len( json.loads( clusters[ 0 ] ) )
1539 except ( ValueError, TypeError ):
1540 main.log.exception( "Error parsing clusters[0]: " +
1541 repr( clusters[ 0 ] ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001542 clusterResults = main.FALSE
1543 if numClusters == 1:
1544 clusterResults = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08001545 utilities.assert_equals(
1546 expect=1,
Jon Hall8f89dda2015-01-22 16:03:33 -08001547 actual=numClusters,
Jon Hall6aec96b2015-01-19 14:49:31 -08001548 onpass="ONOS shows 1 SCC",
Jon Hall58c76b72015-02-23 11:09:24 -08001549 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
Jon Hall94fd0472014-12-08 11:52:42 -08001550
Jon Hall6aec96b2015-01-19 14:49:31 -08001551 main.step( "Comparing ONOS topology to MN" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001552 devicesResults = main.TRUE
Jon Hall8f89dda2015-01-22 16:03:33 -08001553 linksResults = main.TRUE
Jon Hallb6a54872015-06-12 14:02:42 -07001554 hostsResults = main.TRUE
1555 mnSwitches = main.Mininet1.getSwitches()
1556 mnLinks = main.Mininet1.getLinks()
1557 mnHosts = main.Mininet1.getHosts()
Jon Hall8f89dda2015-01-22 16:03:33 -08001558 for controller in range( numControllers ):
1559 controllerStr = str( controller + 1 )
Jon Hallb6a54872015-06-12 14:02:42 -07001560 if devices[ controller ] and ports[ controller ] and\
1561 "Error" not in devices[ controller ] and\
1562 "Error" not in ports[ controller ]:
1563
Jon Hall8f89dda2015-01-22 16:03:33 -08001564 currentDevicesResult = main.Mininet1.compareSwitches(
Jon Hallb6a54872015-06-12 14:02:42 -07001565 mnSwitches,
1566 json.loads( devices[ controller ] ),
1567 json.loads( ports[ controller ] ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001568 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08001569 currentDevicesResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001570 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08001571 actual=currentDevicesResult,
1572 onpass="ONOS" + controllerStr +
1573 " Switches view is correct",
1574 onfail="ONOS" + controllerStr +
1575 " Switches view is incorrect" )
Jon Hallb6a54872015-06-12 14:02:42 -07001576 if links[ controller ] and "Error" not in links[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08001577 currentLinksResult = main.Mininet1.compareLinks(
Jon Hallb6a54872015-06-12 14:02:42 -07001578 mnSwitches, mnLinks,
1579 json.loads( links[ controller ] ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001580 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08001581 currentLinksResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001582 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08001583 actual=currentLinksResult,
1584 onpass="ONOS" + controllerStr +
1585 " links view is correct",
1586 onfail="ONOS" + controllerStr +
1587 " links view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001588
Jon Hallb6a54872015-06-12 14:02:42 -07001589 if hosts[ controller ] or "Error" not in hosts[ controller ]:
1590 currentHostsResult = main.Mininet1.compareHosts(
1591 mnHosts,
1592 hosts[ controller ] )
1593 else:
1594 currentHostsResult = main.FALSE
1595 utilities.assert_equals( expect=main.TRUE,
1596 actual=currentHostsResult,
1597 onpass="ONOS" + controllerStr +
1598 " hosts exist in Mininet",
1599 onfail="ONOS" + controllerStr +
1600 " hosts don't match Mininet" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001601
Jon Hallb6a54872015-06-12 14:02:42 -07001602 devicesResults = devicesResults and currentDevicesResult
1603 linksResults = linksResults and currentLinksResult
1604 hostsResults = hostsResults and currentHostsResult
1605
1606 main.step( "Device information is correct" )
1607 utilities.assert_equals(
1608 expect=main.TRUE,
1609 actual=devicesResults,
1610 onpass="Device information is correct",
1611 onfail="Device information is incorrect" )
1612
1613 main.step( "Links are correct" )
1614 utilities.assert_equals(
1615 expect=main.TRUE,
1616 actual=linksResults,
1617 onpass="Link are correct",
1618 onfail="Links are incorrect" )
1619
1620 main.step( "Hosts are correct" )
1621 utilities.assert_equals(
1622 expect=main.TRUE,
1623 actual=hostsResults,
1624 onpass="Hosts are correct",
1625 onfail="Hosts are incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001626
Jon Hall6aec96b2015-01-19 14:49:31 -08001627 def CASE6( self, main ):
1628 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001629 The Failure case.
Jon Hall6aec96b2015-01-19 14:49:31 -08001630 """
Jon Hall94fd0472014-12-08 11:52:42 -08001631 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07001632 assert numControllers, "numControllers not defined"
1633 assert main, "main not defined"
1634 assert utilities.assert_equals, "utilities.assert_equals not defined"
1635 assert CLIs, "CLIs not defined"
1636 assert nodes, "nodes not defined"
Jon Hall5cfd23c2015-03-19 11:40:57 -07001637 main.case( "Restart minority of ONOS nodes" )
Jon Hall390696c2015-05-05 17:13:41 -07001638 main.step( "Killing 3 ONOS nodes" )
Jon Hallfeff3082015-05-19 10:23:26 -07001639 killTime = time.time()
Jon Hall390696c2015-05-05 17:13:41 -07001640 # TODO: Randomize these nodes or base this on partitions
Jon Hall5cfd23c2015-03-19 11:40:57 -07001641 # TODO: use threads in this case
Jon Hall390696c2015-05-05 17:13:41 -07001642 killResults = main.ONOSbench.onosKill( nodes[0].ip_address )
Jon Hall6aec96b2015-01-19 14:49:31 -08001643 time.sleep( 10 )
Jon Hall390696c2015-05-05 17:13:41 -07001644 killResults = killResults and\
1645 main.ONOSbench.onosKill( nodes[1].ip_address )
Jon Hall6aec96b2015-01-19 14:49:31 -08001646 time.sleep( 10 )
Jon Hall390696c2015-05-05 17:13:41 -07001647 killResults = killResults and\
1648 main.ONOSbench.onosKill( nodes[2].ip_address )
1649 utilities.assert_equals( expect=main.TRUE, actual=killResults,
1650 onpass="ONOS Killed successfully",
1651 onfail="ONOS kill NOT successful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001652
Jon Hall6aec96b2015-01-19 14:49:31 -08001653 main.step( "Checking if ONOS is up yet" )
Jon Hallffb386d2014-11-21 13:43:38 -08001654 count = 0
Jon Hall8f89dda2015-01-22 16:03:33 -08001655 onosIsupResult = main.FALSE
1656 while onosIsupResult == main.FALSE and count < 10:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001657 onos1Isup = main.ONOSbench.isup( nodes[0].ip_address )
1658 onos2Isup = main.ONOSbench.isup( nodes[1].ip_address )
1659 onos3Isup = main.ONOSbench.isup( nodes[2].ip_address )
Jon Hall8f89dda2015-01-22 16:03:33 -08001660 onosIsupResult = onos1Isup and onos2Isup and onos3Isup
Jon Hallffb386d2014-11-21 13:43:38 -08001661 count = count + 1
Jon Hall73cf9cc2014-11-20 22:28:38 -08001662 # TODO: if it becomes an issue, we can retry this step a few times
Jon Hall390696c2015-05-05 17:13:41 -07001663 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
1664 onpass="ONOS restarted successfully",
1665 onfail="ONOS restart NOT successful" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001666
Jon Hall390696c2015-05-05 17:13:41 -07001667 main.step( "Restarting ONOS CLIs" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001668 cliResult1 = main.ONOScli1.startOnosCli( nodes[0].ip_address )
1669 cliResult2 = main.ONOScli2.startOnosCli( nodes[1].ip_address )
1670 cliResult3 = main.ONOScli3.startOnosCli( nodes[2].ip_address )
Jon Hall8f89dda2015-01-22 16:03:33 -08001671 cliResults = cliResult1 and cliResult2 and cliResult3
Jon Hall390696c2015-05-05 17:13:41 -07001672 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
1673 onpass="ONOS cli restarted",
1674 onfail="ONOS cli did not restart" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001675
Jon Hall21270ac2015-02-16 17:59:55 -08001676 # Grab the time of restart so we chan check how long the gossip
1677 # protocol has had time to work
Jon Hallfeff3082015-05-19 10:23:26 -07001678 main.restartTime = time.time() - killTime
1679 main.log.debug( "Restart time: " + str( main.restartTime ) )
1680 '''
1681 # FIXME: revisit test plan for election with madan
1682 # Rerun for election on restarted nodes
1683 run1 = CLIs[0].electionTestRun()
1684 run2 = CLIs[1].electionTestRun()
1685 run3 = CLIs[2].electionTestRun()
1686 runResults = run1 and run2 and run3
1687 utilities.assert_equals( expect=main.TRUE, actual=runResults,
1688 onpass="Reran for election",
1689 onfail="Failed to rerun for election" )
1690 '''
1691 # TODO: MAke this configurable. Also, we are breaking the above timer
1692 time.sleep( 60 )
1693 main.log.debug( CLIs[0].nodes( jsonFormat=False ) )
1694 main.log.debug( CLIs[0].leaders( jsonFormat=False ) )
1695 main.log.debug( CLIs[0].partitions( jsonFormat=False ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001696
Jon Hall6aec96b2015-01-19 14:49:31 -08001697 def CASE7( self, main ):
1698 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001699 Check state after ONOS failure
Jon Hall6aec96b2015-01-19 14:49:31 -08001700 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08001701 import json
Jon Hall5cfd23c2015-03-19 11:40:57 -07001702 assert numControllers, "numControllers not defined"
1703 assert main, "main not defined"
1704 assert utilities.assert_equals, "utilities.assert_equals not defined"
1705 assert CLIs, "CLIs not defined"
1706 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08001707 main.case( "Running ONOS Constant State Tests" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001708
Jon Hall5cfd23c2015-03-19 11:40:57 -07001709 main.step( "Check that each switch has a master" )
Jon Hall6aec96b2015-01-19 14:49:31 -08001710 # Assert that each device has a master
Jon Hall5cfd23c2015-03-19 11:40:57 -07001711 rolesNotNull = main.TRUE
1712 threads = []
1713 for i in range( numControllers ):
1714 t = main.Thread( target=CLIs[i].rolesNotNull,
1715 name="rolesNotNull-" + str( i ),
1716 args=[ ] )
1717 threads.append( t )
1718 t.start()
1719
1720 for t in threads:
1721 t.join()
1722 rolesNotNull = rolesNotNull and t.result
Jon Hall6aec96b2015-01-19 14:49:31 -08001723 utilities.assert_equals(
1724 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001725 actual=rolesNotNull,
Jon Hall6aec96b2015-01-19 14:49:31 -08001726 onpass="Each device has a master",
1727 onfail="Some devices don't have a master assigned" )
Jon Hall94fd0472014-12-08 11:52:42 -08001728
Jon Hall390696c2015-05-05 17:13:41 -07001729 main.step( "Read device roles from ONOS" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001730 ONOSMastership = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001731 consistentMastership = True
1732 rolesResults = True
1733 threads = []
1734 for i in range( numControllers ):
1735 t = main.Thread( target=CLIs[i].roles,
1736 name="roles-" + str( i ),
1737 args=[] )
1738 threads.append( t )
1739 t.start()
1740
1741 for t in threads:
1742 t.join()
1743 ONOSMastership.append( t.result )
1744
1745 for i in range( numControllers ):
1746 if not ONOSMastership[i] or "Error" in ONOSMastership[i]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001747 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001748 " roles" )
1749 main.log.warn(
1750 "ONOS" + str( i + 1 ) + " mastership response: " +
1751 repr( ONOSMastership[i] ) )
1752 rolesResults = False
1753 utilities.assert_equals(
1754 expect=True,
1755 actual=rolesResults,
1756 onpass="No error in reading roles output",
1757 onfail="Error in reading roles from ONOS" )
1758
1759 main.step( "Check for consistency in roles from each controller" )
1760 if all([ i == ONOSMastership[ 0 ] for i in ONOSMastership ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001761 main.log.info(
Jon Hall6aec96b2015-01-19 14:49:31 -08001762 "Switch roles are consistent across all ONOS nodes" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001763 else:
Jon Hall5cfd23c2015-03-19 11:40:57 -07001764 consistentMastership = False
Jon Hall6aec96b2015-01-19 14:49:31 -08001765 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001766 expect=True,
Jon Hall8f89dda2015-01-22 16:03:33 -08001767 actual=consistentMastership,
Jon Hall6aec96b2015-01-19 14:49:31 -08001768 onpass="Switch roles are consistent across all ONOS nodes",
1769 onfail="ONOS nodes have different views of switch roles" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001770
Jon Hall5cfd23c2015-03-19 11:40:57 -07001771 if rolesResults and not consistentMastership:
1772 for i in range( numControllers ):
1773 main.log.warn(
1774 "ONOS" + str( i + 1 ) + " roles: ",
1775 json.dumps(
1776 json.loads( ONOSMastership[ i ] ),
1777 sort_keys=True,
1778 indent=4,
1779 separators=( ',', ': ' ) ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001780
Jon Hallfeff3082015-05-19 10:23:26 -07001781 # NOTE: we expect mastership to change on controller failure
1782 '''
Jon Hall73cf9cc2014-11-20 22:28:38 -08001783 description2 = "Compare switch roles from before failure"
Jon Hall6aec96b2015-01-19 14:49:31 -08001784 main.step( description2 )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001785 try:
1786 currentJson = json.loads( ONOSMastership[0] )
1787 oldJson = json.loads( mastershipState )
1788 except ( ValueError, TypeError ):
1789 main.log.exception( "Something is wrong with parsing " +
1790 "ONOSMastership[0] or mastershipState" )
1791 main.log.error( "ONOSMastership[0]: " + repr( ONOSMastership[0] ) )
1792 main.log.error( "mastershipState" + repr( mastershipState ) )
1793 main.cleanup()
1794 main.exit()
Jon Hall8f89dda2015-01-22 16:03:33 -08001795 mastershipCheck = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08001796 for i in range( 1, 29 ):
1797 switchDPID = str(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001798 main.Mininet1.getSwitchDPID( switch="s" + str( i ) ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001799 current = [ switch[ 'master' ] for switch in currentJson
Jon Hall6aec96b2015-01-19 14:49:31 -08001800 if switchDPID in switch[ 'id' ] ]
Jon Hall8f89dda2015-01-22 16:03:33 -08001801 old = [ switch[ 'master' ] for switch in oldJson
Jon Hall6aec96b2015-01-19 14:49:31 -08001802 if switchDPID in switch[ 'id' ] ]
Jon Hall73cf9cc2014-11-20 22:28:38 -08001803 if current == old:
Jon Hall8f89dda2015-01-22 16:03:33 -08001804 mastershipCheck = mastershipCheck and main.TRUE
Jon Hall73cf9cc2014-11-20 22:28:38 -08001805 else:
Jon Hall6aec96b2015-01-19 14:49:31 -08001806 main.log.warn( "Mastership of switch %s changed" % switchDPID )
Jon Hall8f89dda2015-01-22 16:03:33 -08001807 mastershipCheck = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001808 utilities.assert_equals(
1809 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08001810 actual=mastershipCheck,
Jon Hall6aec96b2015-01-19 14:49:31 -08001811 onpass="Mastership of Switches was not changed",
1812 onfail="Mastership of some switches changed" )
Jon Hallfeff3082015-05-19 10:23:26 -07001813 '''
Jon Hall73cf9cc2014-11-20 22:28:38 -08001814
Jon Hall58c76b72015-02-23 11:09:24 -08001815 main.step( "Get the intents and compare across all nodes" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001816 ONOSIntents = []
Jon Hall58c76b72015-02-23 11:09:24 -08001817 intentCheck = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001818 consistentIntents = True
1819 intentsResults = True
1820 threads = []
1821 for i in range( numControllers ):
1822 t = main.Thread( target=CLIs[i].intents,
1823 name="intents-" + str( i ),
1824 args=[],
1825 kwargs={ 'jsonFormat': True } )
1826 threads.append( t )
1827 t.start()
1828
1829 for t in threads:
1830 t.join()
1831 ONOSIntents.append( t.result )
1832
1833 for i in range( numControllers ):
1834 if not ONOSIntents[ i ] or "Error" in ONOSIntents[ i ]:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001835 main.log.error( "Error in getting ONOS" + str( i + 1 ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001836 " intents" )
1837 main.log.warn( "ONOS" + str( i + 1 ) + " intents response: " +
1838 repr( ONOSIntents[ i ] ) )
1839 intentsResults = False
Jon Hall58c76b72015-02-23 11:09:24 -08001840 utilities.assert_equals(
Jon Hall5cfd23c2015-03-19 11:40:57 -07001841 expect=True,
1842 actual=intentsResults,
1843 onpass="No error in reading intents output",
1844 onfail="Error in reading intents from ONOS" )
1845
1846 main.step( "Check for consistency in Intents from each controller" )
1847 if all([ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07001848 main.log.info( "Intents are consistent across all ONOS " +
Jon Hall5cfd23c2015-03-19 11:40:57 -07001849 "nodes" )
1850 else:
1851 consistentIntents = False
Jon Hall390696c2015-05-05 17:13:41 -07001852
1853 # Try to make it easy to figure out what is happening
1854 #
1855 # Intent ONOS1 ONOS2 ...
1856 # 0x01 INSTALLED INSTALLING
1857 # ... ... ...
1858 # ... ... ...
1859 title = " ID"
1860 for n in range( numControllers ):
1861 title += " " * 10 + "ONOS" + str( n + 1 )
1862 main.log.warn( title )
1863 # get all intent keys in the cluster
1864 keys = []
1865 for nodeStr in ONOSIntents:
1866 node = json.loads( nodeStr )
1867 for intent in node:
1868 keys.append( intent.get( 'id' ) )
1869 keys = set( keys )
1870 for key in keys:
1871 row = "%-13s" % key
1872 for nodeStr in ONOSIntents:
1873 node = json.loads( nodeStr )
1874 for intent in node:
1875 if intent.get( 'id' ) == key:
1876 row += "%-15s" % intent.get( 'state' )
1877 main.log.warn( row )
1878 # End table view
1879
Jon Hall5cfd23c2015-03-19 11:40:57 -07001880 utilities.assert_equals(
1881 expect=True,
1882 actual=consistentIntents,
Jon Hall58c76b72015-02-23 11:09:24 -08001883 onpass="Intents are consistent across all ONOS nodes",
1884 onfail="ONOS nodes have different views of intents" )
Jon Hall58c76b72015-02-23 11:09:24 -08001885 intentStates = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07001886 for node in ONOSIntents: # Iter through ONOS nodes
Jon Hall58c76b72015-02-23 11:09:24 -08001887 nodeStates = []
1888 # Iter through intents of a node
Jon Hall5cfd23c2015-03-19 11:40:57 -07001889 try:
1890 for intent in json.loads( node ):
1891 nodeStates.append( intent[ 'state' ] )
1892 except ( ValueError, TypeError ):
1893 main.log.exception( "Error in parsing intents" )
1894 main.log.error( repr( node ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001895 intentStates.append( nodeStates )
1896 out = [ (i, nodeStates.count( i ) ) for i in set( nodeStates ) ]
1897 main.log.info( dict( out ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001898
Jon Hall5cfd23c2015-03-19 11:40:57 -07001899 if intentsResults and not consistentIntents:
1900 for i in range( numControllers ):
1901 main.log.warn( "ONOS" + str( i + 1 ) + " intents: " )
1902 main.log.warn( json.dumps(
1903 json.loads( ONOSIntents[ i ] ),
1904 sort_keys=True,
1905 indent=4,
1906 separators=( ',', ': ' ) ) )
1907 elif intentsResults and consistentIntents:
1908 intentCheck = main.TRUE
1909
Jon Hall58c76b72015-02-23 11:09:24 -08001910 # NOTE: Store has no durability, so intents are lost across system
1911 # restarts
1912 main.step( "Compare current intents with intents before the failure" )
1913 # NOTE: this requires case 5 to pass for intentState to be set.
1914 # maybe we should stop the test if that fails?
Jon Hall40d2cbd2015-06-03 16:24:29 -07001915 sameIntents = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07001916 if intentState and intentState == ONOSIntents[ 0 ]:
Jon Hall21270ac2015-02-16 17:59:55 -08001917 sameIntents = main.TRUE
Jon Hallfeff3082015-05-19 10:23:26 -07001918 main.log.info( "Intents are consistent with before failure" )
Jon Hall58c76b72015-02-23 11:09:24 -08001919 # TODO: possibly the states have changed? we may need to figure out
Jon Hall5cfd23c2015-03-19 11:40:57 -07001920 # what the acceptable states are
Jon Hall40d2cbd2015-06-03 16:24:29 -07001921 elif len( intentState ) == len( ONOSIntents[ 0 ] ):
1922 sameIntents = main.TRUE
Jon Hall58c76b72015-02-23 11:09:24 -08001923 try:
Jon Hall40d2cbd2015-06-03 16:24:29 -07001924 before = json.loads( intentState )
1925 after = json.loads( ONOSIntents[ 0 ] )
1926 for intent in before:
1927 if intent not in after:
1928 sameIntents = main.FALSE
Jon Hallc9eabec2015-06-10 14:33:14 -07001929 main.log.debug( "Intent is not currently in ONOS " +
Jon Hall40d2cbd2015-06-03 16:24:29 -07001930 "(at least in the same form):" )
1931 main.log.debug( json.dumps( intent ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001932 except ( ValueError, TypeError ):
1933 main.log.exception( "Exception printing intents" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001934 main.log.debug( repr( ONOSIntents[0] ) )
1935 main.log.debug( repr( intentState ) )
1936 if sameIntents == main.FALSE:
1937 try:
1938 main.log.debug( "ONOS intents before: " )
1939 main.log.debug( json.dumps( json.loads( intentState ),
1940 sort_keys=True, indent=4,
1941 separators=( ',', ': ' ) ) )
1942 main.log.debug( "Current ONOS intents: " )
1943 main.log.debug( json.dumps( json.loads( ONOSIntents[ 0 ] ),
1944 sort_keys=True, indent=4,
1945 separators=( ',', ': ' ) ) )
1946 except ( ValueError, TypeError ):
1947 main.log.exception( "Exception printing intents" )
1948 main.log.debug( repr( ONOSIntents[0] ) )
1949 main.log.debug( repr( intentState ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001950 utilities.assert_equals(
1951 expect=main.TRUE,
1952 actual=sameIntents,
1953 onpass="Intents are consistent with before failure",
1954 onfail="The Intents changed during failure" )
1955 intentCheck = intentCheck and sameIntents
Jon Hall21270ac2015-02-16 17:59:55 -08001956
Jon Hall58c76b72015-02-23 11:09:24 -08001957 main.step( "Get the OF Table entries and compare to before " +
1958 "component failure" )
1959 FlowTables = main.TRUE
1960 flows2 = []
1961 for i in range( 28 ):
1962 main.log.info( "Checking flow table on s" + str( i + 1 ) )
1963 tmpFlows = main.Mininet2.getFlowTable( 1.3, "s" + str( i + 1 ) )
1964 flows2.append( tmpFlows )
1965 tempResult = main.Mininet2.flowComp(
1966 flow1=flows[ i ],
1967 flow2=tmpFlows )
1968 FlowTables = FlowTables and tempResult
1969 if FlowTables == main.FALSE:
1970 main.log.info( "Differences in flow table for switch: s" +
1971 str( i + 1 ) )
Jon Hall58c76b72015-02-23 11:09:24 -08001972 utilities.assert_equals(
1973 expect=main.TRUE,
1974 actual=FlowTables,
1975 onpass="No changes were found in the flow tables",
1976 onfail="Changes were found in the flow tables" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08001977
Jon Hall6aec96b2015-01-19 14:49:31 -08001978 main.step( "Check the continuous pings to ensure that no packets " +
1979 "were dropped during component failure" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07001980 main.Mininet2.pingKill( main.params[ 'TESTONUSER' ],
1981 main.params[ 'TESTONIP' ] )
Jon Hall8f89dda2015-01-22 16:03:33 -08001982 LossInPings = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08001983 # NOTE: checkForLoss returns main.FALSE with 0% packet loss
1984 for i in range( 8, 18 ):
1985 main.log.info(
1986 "Checking for a loss in pings along flow from s" +
1987 str( i ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08001988 LossInPings = main.Mininet2.checkForLoss(
Jon Hall6aec96b2015-01-19 14:49:31 -08001989 "/tmp/ping.h" +
Jon Hall8f89dda2015-01-22 16:03:33 -08001990 str( i ) ) or LossInPings
1991 if LossInPings == main.TRUE:
Jon Hall6aec96b2015-01-19 14:49:31 -08001992 main.log.info( "Loss in ping detected" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001993 elif LossInPings == main.ERROR:
Jon Hall6aec96b2015-01-19 14:49:31 -08001994 main.log.info( "There are multiple mininet process running" )
Jon Hall8f89dda2015-01-22 16:03:33 -08001995 elif LossInPings == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08001996 main.log.info( "No Loss in the pings" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07001997 main.log.info( "No loss of dataplane connectivity" )
Jon Hall6aec96b2015-01-19 14:49:31 -08001998 utilities.assert_equals(
1999 expect=main.FALSE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002000 actual=LossInPings,
Jon Hall6aec96b2015-01-19 14:49:31 -08002001 onpass="No Loss of connectivity",
2002 onfail="Loss of dataplane connectivity detected" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002003
Jon Hall390696c2015-05-05 17:13:41 -07002004 main.step( "Leadership Election is still functional" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002005 # Test of LeadershipElection
Jon Hall8f89dda2015-01-22 16:03:33 -08002006 leaderList = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002007 # FIXME: make sure this matches nodes that were restarted
2008 restarted = [ nodes[0].ip_address, nodes[1].ip_address,
2009 nodes[2].ip_address ]
Jon Hall390696c2015-05-05 17:13:41 -07002010
Jon Hall8f89dda2015-01-22 16:03:33 -08002011 leaderResult = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002012 for cli in CLIs:
2013 leaderN = cli.electionTestLeader()
Jon Hall8f89dda2015-01-22 16:03:33 -08002014 leaderList.append( leaderN )
Jon Hall669173b2014-12-17 11:36:30 -08002015 if leaderN == main.FALSE:
Jon Hallfeff3082015-05-19 10:23:26 -07002016 # error in response
Jon Hall40d2cbd2015-06-03 16:24:29 -07002017 main.log.error( "Something is wrong with " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002018 "electionTestLeader function, check the" +
Jon Hall6aec96b2015-01-19 14:49:31 -08002019 " error logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002020 leaderResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002021 elif leaderN is None:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002022 main.log.error( cli.name +
Jon Hall6aec96b2015-01-19 14:49:31 -08002023 " shows no leader for the election-app was" +
2024 " elected after the old one died" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002025 leaderResult = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002026 elif leaderN in restarted:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002027 main.log.error( cli.name + " shows " + str( leaderN ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002028 " as leader for the election-app, but it " +
2029 "was restarted" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002030 leaderResult = main.FALSE
2031 if len( set( leaderList ) ) != 1:
2032 leaderResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002033 main.log.error(
2034 "Inconsistent view of leader for the election test app" )
2035 # TODO: print the list
Jon Hall6aec96b2015-01-19 14:49:31 -08002036 utilities.assert_equals(
2037 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002038 actual=leaderResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002039 onpass="Leadership election passed",
2040 onfail="Something went wrong with Leadership election" )
Jon Hall669173b2014-12-17 11:36:30 -08002041
Jon Hall6aec96b2015-01-19 14:49:31 -08002042 def CASE8( self, main ):
2043 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002044 Compare topo
Jon Hall6aec96b2015-01-19 14:49:31 -08002045 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002046 import json
2047 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002048 assert numControllers, "numControllers not defined"
2049 assert main, "main not defined"
2050 assert utilities.assert_equals, "utilities.assert_equals not defined"
2051 assert CLIs, "CLIs not defined"
2052 assert nodes, "nodes not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002053
Jon Hallfeff3082015-05-19 10:23:26 -07002054 main.case( "Compare ONOS Topology view to Mininet topology" )
2055 main.caseExplaination = "Compare topology objects between Mininet" +\
2056 " and ONOS"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002057
Jon Hallfeff3082015-05-19 10:23:26 -07002058 main.step( "Comparing ONOS topology to MN" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002059 devicesResults = main.TRUE
Jon Hall8f89dda2015-01-22 16:03:33 -08002060 linksResults = main.TRUE
Jon Hall58c76b72015-02-23 11:09:24 -08002061 hostsResults = main.TRUE
Jon Hallc9eabec2015-06-10 14:33:14 -07002062 hostAttachmentResults = True
Jon Hall8f89dda2015-01-22 16:03:33 -08002063 topoResult = main.FALSE
Jon Hall73cf9cc2014-11-20 22:28:38 -08002064 elapsed = 0
Jon Hallffb386d2014-11-21 13:43:38 -08002065 count = 0
Jon Hall6aec96b2015-01-19 14:49:31 -08002066 main.step( "Collecting topology information from ONOS" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002067 startTime = time.time()
Jon Hall21270ac2015-02-16 17:59:55 -08002068 # Give time for Gossip to work
Jon Hall8f89dda2015-01-22 16:03:33 -08002069 while topoResult == main.FALSE and elapsed < 60:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002070 count += 1
Jon Hall8f89dda2015-01-22 16:03:33 -08002071 cliStart = time.time()
Jon Hall94fd0472014-12-08 11:52:42 -08002072 devices = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002073 threads = []
2074 for i in range( numControllers ):
2075 t = main.Thread( target=CLIs[i].devices,
2076 name="devices-" + str( i ),
2077 args=[ ] )
2078 threads.append( t )
2079 t.start()
2080
2081 for t in threads:
2082 t.join()
2083 devices.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002084 hosts = []
Jon Hall58c76b72015-02-23 11:09:24 -08002085 ipResult = main.TRUE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002086 threads = []
2087 for i in range( numControllers ):
2088 t = main.Thread( target=CLIs[i].hosts,
2089 name="hosts-" + str( i ),
2090 args=[ ] )
2091 threads.append( t )
2092 t.start()
2093
2094 for t in threads:
2095 t.join()
2096 try:
2097 hosts.append( json.loads( t.result ) )
2098 except ( ValueError, TypeError ):
2099 main.log.exception( "Error parsing hosts results" )
2100 main.log.error( repr( t.result ) )
Jon Hall6aec96b2015-01-19 14:49:31 -08002101 for controller in range( 0, len( hosts ) ):
Jon Hall8f89dda2015-01-22 16:03:33 -08002102 controllerStr = str( controller + 1 )
Jon Hall6aec96b2015-01-19 14:49:31 -08002103 for host in hosts[ controller ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002104 if host is None or host.get( 'ipAddresses', [] ) == []:
Jon Hall6aec96b2015-01-19 14:49:31 -08002105 main.log.error(
Jon Hall40d2cbd2015-06-03 16:24:29 -07002106 "DEBUG:Error with host ipAddresses on controller" +
Jon Hall8f89dda2015-01-22 16:03:33 -08002107 controllerStr + ": " + str( host ) )
Jon Hall58c76b72015-02-23 11:09:24 -08002108 ipResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002109 ports = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002110 threads = []
2111 for i in range( numControllers ):
2112 t = main.Thread( target=CLIs[i].ports,
2113 name="ports-" + str( i ),
2114 args=[ ] )
2115 threads.append( t )
2116 t.start()
2117
2118 for t in threads:
2119 t.join()
2120 ports.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002121 links = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002122 threads = []
2123 for i in range( numControllers ):
2124 t = main.Thread( target=CLIs[i].links,
2125 name="links-" + str( i ),
2126 args=[ ] )
2127 threads.append( t )
2128 t.start()
2129
2130 for t in threads:
2131 t.join()
2132 links.append( t.result )
Jon Hall94fd0472014-12-08 11:52:42 -08002133 clusters = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002134 threads = []
2135 for i in range( numControllers ):
2136 t = main.Thread( target=CLIs[i].clusters,
2137 name="clusters-" + str( i ),
2138 args=[ ] )
2139 threads.append( t )
2140 t.start()
2141
2142 for t in threads:
2143 t.join()
2144 clusters.append( t.result )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002145
Jon Hall8f89dda2015-01-22 16:03:33 -08002146 elapsed = time.time() - startTime
2147 cliTime = time.time() - cliStart
Jon Hallc9eabec2015-06-10 14:33:14 -07002148 print "Elapsed time: " + str( elapsed )
Jon Hall8f89dda2015-01-22 16:03:33 -08002149 print "CLI time: " + str( cliTime )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002150
Jon Hallb6a54872015-06-12 14:02:42 -07002151 mnSwitches = main.Mininet1.getSwitches()
2152 mnLinks = main.Mininet1.getLinks()
2153 mnHosts = main.Mininet1.getHosts()
Jon Hall8f89dda2015-01-22 16:03:33 -08002154 for controller in range( numControllers ):
2155 controllerStr = str( controller + 1 )
Jon Hallb6a54872015-06-12 14:02:42 -07002156 if devices[ controller ] and ports[ controller ] and\
2157 "Error" not in devices[ controller ] and\
2158 "Error" not in ports[ controller ]:
2159
Jon Hall8f89dda2015-01-22 16:03:33 -08002160 currentDevicesResult = main.Mininet1.compareSwitches(
Jon Hallb6a54872015-06-12 14:02:42 -07002161 mnSwitches,
2162 json.loads( devices[ controller ] ),
2163 json.loads( ports[ controller ] ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002164 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08002165 currentDevicesResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002166 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08002167 actual=currentDevicesResult,
2168 onpass="ONOS" + controllerStr +
2169 " Switches view is correct",
2170 onfail="ONOS" + controllerStr +
2171 " Switches view is incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002172
Jon Hallb6a54872015-06-12 14:02:42 -07002173 if links[ controller ] and "Error" not in links[ controller ]:
Jon Hall8f89dda2015-01-22 16:03:33 -08002174 currentLinksResult = main.Mininet1.compareLinks(
Jon Hallb6a54872015-06-12 14:02:42 -07002175 mnSwitches, mnLinks,
2176 json.loads( links[ controller ] ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002177 else:
Jon Hall8f89dda2015-01-22 16:03:33 -08002178 currentLinksResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002179 utilities.assert_equals( expect=main.TRUE,
Jon Hall58c76b72015-02-23 11:09:24 -08002180 actual=currentLinksResult,
2181 onpass="ONOS" + controllerStr +
2182 " links view is correct",
2183 onfail="ONOS" + controllerStr +
2184 " links view is incorrect" )
2185
2186 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2187 currentHostsResult = main.Mininet1.compareHosts(
Jon Hallb6a54872015-06-12 14:02:42 -07002188 mnHosts,
2189 hosts[ controller ] )
Jon Hall58c76b72015-02-23 11:09:24 -08002190 else:
2191 currentHostsResult = main.FALSE
2192 utilities.assert_equals( expect=main.TRUE,
2193 actual=currentHostsResult,
2194 onpass="ONOS" + controllerStr +
2195 " hosts exist in Mininet",
2196 onfail="ONOS" + controllerStr +
2197 " hosts don't match Mininet" )
Jon Hallc9eabec2015-06-10 14:33:14 -07002198 # CHECKING HOST ATTACHMENT POINTS
2199 hostAttachment = True
Jon Hallb6a54872015-06-12 14:02:42 -07002200 zeroHosts = False
Jon Hallc9eabec2015-06-10 14:33:14 -07002201 # FIXME: topo-HA/obelisk specific mappings:
2202 # key is mac and value is dpid
2203 mappings = {}
2204 for i in range( 1, 29 ): # hosts 1 through 28
2205 # set up correct variables:
2206 macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
2207 if i == 1:
2208 deviceId = "1000".zfill(16)
2209 elif i == 2:
2210 deviceId = "2000".zfill(16)
2211 elif i == 3:
2212 deviceId = "3000".zfill(16)
2213 elif i == 4:
2214 deviceId = "3004".zfill(16)
2215 elif i == 5:
2216 deviceId = "5000".zfill(16)
2217 elif i == 6:
2218 deviceId = "6000".zfill(16)
2219 elif i == 7:
2220 deviceId = "6007".zfill(16)
2221 elif i >= 8 and i <= 17:
2222 dpid = '3' + str( i ).zfill( 3 )
2223 deviceId = dpid.zfill(16)
2224 elif i >= 18 and i <= 27:
2225 dpid = '6' + str( i ).zfill( 3 )
2226 deviceId = dpid.zfill(16)
2227 elif i == 28:
2228 deviceId = "2800".zfill(16)
2229 mappings[ macId ] = deviceId
2230 if hosts[ controller ] or "Error" not in hosts[ controller ]:
2231 if hosts[ controller ] == []:
2232 main.log.warn( "There are no hosts discovered" )
Jon Hallb6a54872015-06-12 14:02:42 -07002233 zeroHosts = True
Jon Hallc9eabec2015-06-10 14:33:14 -07002234 else:
2235 for host in hosts[ controller ]:
2236 mac = None
2237 location = None
2238 device = None
2239 port = None
2240 try:
2241 mac = host.get( 'mac' )
2242 assert mac, "mac field could not be found for this host object"
Jon Hall58c76b72015-02-23 11:09:24 -08002243
Jon Hallc9eabec2015-06-10 14:33:14 -07002244 location = host.get( 'location' )
2245 assert location, "location field could not be found for this host object"
2246
2247 # Trim the protocol identifier off deviceId
2248 device = str( location.get( 'elementId' ) ).split(':')[1]
2249 assert device, "elementId field could not be found for this host location object"
2250
2251 port = location.get( 'port' )
2252 assert port, "port field could not be found for this host location object"
2253
2254 # Now check if this matches where they should be
2255 if mac and device and port:
2256 if str( port ) != "1":
2257 main.log.error( "The attachment port is incorrect for " +
2258 "host " + str( mac ) +
2259 ". Expected: 1 Actual: " + str( port) )
2260 hostAttachment = False
2261 if device != mappings[ str( mac ) ]:
2262 main.log.error( "The attachment device is incorrect for " +
2263 "host " + str( mac ) +
2264 ". Expected: " + mappings[ str( mac ) ] +
2265 " Actual: " + device )
2266 hostAttachment = False
2267 else:
2268 hostAttachment = False
2269 except AssertionError:
2270 main.log.exception( "Json object not as expected" )
2271 main.log.error( repr( host ) )
2272 hostAttachment = False
2273 else:
2274 main.log.error( "No hosts json output or \"Error\"" +
2275 " in output. hosts = " +
2276 repr( hosts[ controller ] ) )
Jon Hallb6a54872015-06-12 14:02:42 -07002277 if zeroHosts is False:
Jon Hallc9eabec2015-06-10 14:33:14 -07002278 hostAttachment = True
2279
2280 # END CHECKING HOST ATTACHMENT POINTS
Jon Hall58c76b72015-02-23 11:09:24 -08002281 devicesResults = devicesResults and currentDevicesResult
Jon Hall58c76b72015-02-23 11:09:24 -08002282 linksResults = linksResults and currentLinksResult
2283 hostsResults = hostsResults and currentHostsResult
Jon Hallb6a54872015-06-12 14:02:42 -07002284 hostAttachmentResults = hostAttachmentResults and\
2285 hostAttachment
Jon Hall94fd0472014-12-08 11:52:42 -08002286
Jon Hallc9eabec2015-06-10 14:33:14 -07002287 # Compare json objects for hosts and dataplane clusters
Jon Hall94fd0472014-12-08 11:52:42 -08002288
Jon Hallc9eabec2015-06-10 14:33:14 -07002289 # hosts
2290 main.step( "Hosts view is consistent across all ONOS nodes" )
2291 consistentHostsResult = main.TRUE
2292 for controller in range( len( hosts ) ):
2293 controllerStr = str( controller + 1 )
2294 if "Error" not in hosts[ controller ]:
2295 if hosts[ controller ] == hosts[ 0 ]:
2296 continue
2297 else: # hosts not consistent
2298 main.log.error( "hosts from ONOS" + controllerStr +
2299 " is inconsistent with ONOS1" )
2300 main.log.warn( repr( hosts[ controller ] ) )
Jon Hall8f89dda2015-01-22 16:03:33 -08002301 consistentHostsResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002302
Jon Hallc9eabec2015-06-10 14:33:14 -07002303 else:
2304 main.log.error( "Error in getting ONOS hosts from ONOS" +
2305 controllerStr )
2306 consistentHostsResult = main.FALSE
2307 main.log.warn( "ONOS" + controllerStr +
2308 " hosts response: " +
2309 repr( hosts[ controller ] ) )
2310 utilities.assert_equals(
2311 expect=main.TRUE,
2312 actual=consistentHostsResult,
2313 onpass="Hosts view is consistent across all ONOS nodes",
2314 onfail="ONOS nodes have different views of hosts" )
Jon Hall94fd0472014-12-08 11:52:42 -08002315
Jon Hallc9eabec2015-06-10 14:33:14 -07002316 main.step( "Hosts information is correct" )
2317 hostsResults = hostsResults and ipResult
2318 utilities.assert_equals(
2319 expect=main.TRUE,
2320 actual=hostsResults,
2321 onpass="Host information is correct",
2322 onfail="Host information is incorrect" )
2323
2324 main.step( "Host attachment points to the network" )
2325 utilities.assert_equals(
2326 expect=True,
2327 actual=hostAttachmentResults,
2328 onpass="Hosts are correctly attached to the network",
2329 onfail="ONOS did not correctly attach hosts to the network" )
2330
2331 # Strongly connected clusters of devices
2332 main.step( "Clusters view is consistent across all ONOS nodes" )
2333 consistentClustersResult = main.TRUE
2334 for controller in range( len( clusters ) ):
2335 controllerStr = str( controller + 1 )
2336 if "Error" not in clusters[ controller ]:
2337 if clusters[ controller ] == clusters[ 0 ]:
2338 continue
2339 else: # clusters not consistent
2340 main.log.error( "clusters from ONOS" +
2341 controllerStr +
2342 " is inconsistent with ONOS1" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002343 consistentClustersResult = main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08002344
Jon Hallc9eabec2015-06-10 14:33:14 -07002345 else:
2346 main.log.error( "Error in getting dataplane clusters " +
2347 "from ONOS" + controllerStr )
2348 consistentClustersResult = main.FALSE
2349 main.log.warn( "ONOS" + controllerStr +
2350 " clusters response: " +
2351 repr( clusters[ controller ] ) )
2352 utilities.assert_equals(
2353 expect=main.TRUE,
2354 actual=consistentClustersResult,
2355 onpass="Clusters view is consistent across all ONOS nodes",
2356 onfail="ONOS nodes have different views of clusters" )
2357
2358 main.step( "There is only one SCC" )
2359 # there should always only be one cluster
2360 try:
2361 numClusters = len( json.loads( clusters[ 0 ] ) )
2362 except ( ValueError, TypeError ):
2363 main.log.exception( "Error parsing clusters[0]: " +
2364 repr( clusters[0] ) )
2365 clusterResults = main.FALSE
2366 if numClusters == 1:
2367 clusterResults = main.TRUE
2368 utilities.assert_equals(
2369 expect=1,
2370 actual=numClusters,
2371 onpass="ONOS shows 1 SCC",
2372 onfail="ONOS shows " + str( numClusters ) + " SCCs" )
2373
Jon Hallb6a54872015-06-12 14:02:42 -07002374 topoResult = ( devicesResults and linksResults
Jon Hallc9eabec2015-06-10 14:33:14 -07002375 and hostsResults and consistentHostsResult
2376 and consistentClustersResult and clusterResults
2377 and ipResult and hostAttachmentResults )
Jon Hall94fd0472014-12-08 11:52:42 -08002378
Jon Hall8f89dda2015-01-22 16:03:33 -08002379 topoResult = topoResult and int( count <= 2 )
2380 note = "note it takes about " + str( int( cliTime ) ) + \
2381 " seconds for the test to make all the cli calls to fetch " +\
2382 "the topology from each ONOS instance"
Jon Hall1b8f54a2015-02-04 13:24:20 -08002383 main.log.info(
Jon Hall8f89dda2015-01-22 16:03:33 -08002384 "Very crass estimate for topology discovery/convergence( " +
2385 str( note ) + " ): " + str( elapsed ) + " seconds, " +
Jon Hall6aec96b2015-01-19 14:49:31 -08002386 str( count ) + " tries" )
Jon Hallc9eabec2015-06-10 14:33:14 -07002387
2388 main.step( "Device information is correct" )
2389 utilities.assert_equals(
2390 expect=main.TRUE,
2391 actual=devicesResults,
2392 onpass="Device information is correct",
2393 onfail="Device information is incorrect" )
2394
Jon Hallc9eabec2015-06-10 14:33:14 -07002395 main.step( "Links are correct" )
2396 utilities.assert_equals(
2397 expect=main.TRUE,
2398 actual=linksResults,
2399 onpass="Link are correct",
2400 onfail="Links are incorrect" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002401
Jon Halla9d26da2015-03-30 16:45:32 -07002402 # FIXME: move this to an ONOS state case
2403 main.step( "Checking ONOS nodes" )
2404 nodesOutput = []
Jon Hall390696c2015-05-05 17:13:41 -07002405 nodeResults = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002406 threads = []
2407 for i in range( numControllers ):
2408 t = main.Thread( target=CLIs[i].nodes,
2409 name="nodes-" + str( i ),
2410 args=[ ] )
2411 threads.append( t )
2412 t.start()
2413
2414 for t in threads:
2415 t.join()
2416 nodesOutput.append( t.result )
2417 ips = [ node.ip_address for node in nodes ]
2418 for i in nodesOutput:
2419 try:
2420 current = json.loads( i )
2421 for node in current:
Jon Hall390696c2015-05-05 17:13:41 -07002422 currentResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002423 if node['ip'] in ips: # node in nodes() output is in cell
2424 if node['state'] == 'ACTIVE':
Jon Hall390696c2015-05-05 17:13:41 -07002425 currentResult = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002426 else:
2427 main.log.error( "Error in ONOS node availability" )
2428 main.log.error(
2429 json.dumps( current,
2430 sort_keys=True,
2431 indent=4,
2432 separators=( ',', ': ' ) ) )
2433 break
Jon Hall390696c2015-05-05 17:13:41 -07002434 nodeResults = nodeResults and currentResult
Jon Halla9d26da2015-03-30 16:45:32 -07002435 except ( ValueError, TypeError ):
2436 main.log.error( "Error parsing nodes output" )
2437 main.log.warn( repr( i ) )
Jon Hall390696c2015-05-05 17:13:41 -07002438 utilities.assert_equals( expect=main.TRUE, actual=nodeResults,
2439 onpass="Nodes check successful",
2440 onfail="Nodes check NOT successful" )
Jon Halla9d26da2015-03-30 16:45:32 -07002441
Jon Hall6aec96b2015-01-19 14:49:31 -08002442 def CASE9( self, main ):
2443 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002444 Link s3-s28 down
Jon Hall6aec96b2015-01-19 14:49:31 -08002445 """
2446 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002447 assert numControllers, "numControllers not defined"
2448 assert main, "main not defined"
2449 assert utilities.assert_equals, "utilities.assert_equals not defined"
2450 assert CLIs, "CLIs not defined"
2451 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002452 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002453
Jon Hall8f89dda2015-01-22 16:03:33 -08002454 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002455
Jon Hall6aec96b2015-01-19 14:49:31 -08002456 description = "Turn off a link to ensure that Link Discovery " +\
Jon Hall58c76b72015-02-23 11:09:24 -08002457 "is working properly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002458 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002459
Jon Hall6aec96b2015-01-19 14:49:31 -08002460 main.step( "Kill Link between s3 and s28" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002461 LinkDown = main.Mininet1.link( END1="s3", END2="s28", OPTION="down" )
Jon Hall58c76b72015-02-23 11:09:24 -08002462 main.log.info( "Waiting " + str( linkSleep ) +
2463 " seconds for link down to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002464 time.sleep( linkSleep )
2465 utilities.assert_equals( expect=main.TRUE, actual=LinkDown,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002466 onpass="Link down successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002467 onfail="Failed to bring link down" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002468 # TODO do some sort of check here
Jon Hall73cf9cc2014-11-20 22:28:38 -08002469
Jon Hall6aec96b2015-01-19 14:49:31 -08002470 def CASE10( self, main ):
2471 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002472 Link s3-s28 up
Jon Hall6aec96b2015-01-19 14:49:31 -08002473 """
2474 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002475 assert numControllers, "numControllers not defined"
2476 assert main, "main not defined"
2477 assert utilities.assert_equals, "utilities.assert_equals not defined"
2478 assert CLIs, "CLIs not defined"
2479 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002480 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002481
Jon Hall8f89dda2015-01-22 16:03:33 -08002482 linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002483
Jon Hall6aec96b2015-01-19 14:49:31 -08002484 description = "Restore a link to ensure that Link Discovery is " + \
Jon Hall63604932015-02-26 17:09:50 -08002485 "working properly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002486 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002487
Jon Hall6aec96b2015-01-19 14:49:31 -08002488 main.step( "Bring link between s3 and s28 back up" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002489 LinkUp = main.Mininet1.link( END1="s3", END2="s28", OPTION="up" )
Jon Hall58c76b72015-02-23 11:09:24 -08002490 main.log.info( "Waiting " + str( linkSleep ) +
2491 " seconds for link up to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002492 time.sleep( linkSleep )
2493 utilities.assert_equals( expect=main.TRUE, actual=LinkUp,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002494 onpass="Link up successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002495 onfail="Failed to bring link up" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002496 # TODO do some sort of check here
Jon Hall73cf9cc2014-11-20 22:28:38 -08002497
Jon Hall6aec96b2015-01-19 14:49:31 -08002498 def CASE11( self, main ):
2499 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002500 Switch Down
Jon Hall6aec96b2015-01-19 14:49:31 -08002501 """
2502 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002503 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002504 assert numControllers, "numControllers not defined"
2505 assert main, "main not defined"
2506 assert utilities.assert_equals, "utilities.assert_equals not defined"
2507 assert CLIs, "CLIs not defined"
2508 assert nodes, "nodes not defined"
Jon Hall73cf9cc2014-11-20 22:28:38 -08002509
Jon Hall8f89dda2015-01-22 16:03:33 -08002510 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002511
2512 description = "Killing a switch to ensure it is discovered correctly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002513 main.case( description )
2514 switch = main.params[ 'kill' ][ 'switch' ]
2515 switchDPID = main.params[ 'kill' ][ 'dpid' ]
Jon Hall73cf9cc2014-11-20 22:28:38 -08002516
Jon Hall6aec96b2015-01-19 14:49:31 -08002517 # TODO: Make this switch parameterizable
2518 main.step( "Kill " + switch )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002519 main.log.info( "Deleting " + switch )
Jon Hall8f89dda2015-01-22 16:03:33 -08002520 main.Mininet1.delSwitch( switch )
2521 main.log.info( "Waiting " + str( switchSleep ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002522 " seconds for switch down to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002523 time.sleep( switchSleep )
2524 device = main.ONOScli1.getDevice( dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002525 # Peek at the deleted switch
2526 main.log.warn( str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002527 result = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002528 if device and device[ 'available' ] is False:
Jon Hall94fd0472014-12-08 11:52:42 -08002529 result = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002530 utilities.assert_equals( expect=main.TRUE, actual=result,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002531 onpass="Kill switch successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002532 onfail="Failed to kill switch?" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002533
Jon Hall6aec96b2015-01-19 14:49:31 -08002534 def CASE12( self, main ):
2535 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002536 Switch Up
Jon Hall6aec96b2015-01-19 14:49:31 -08002537 """
2538 # NOTE: You should probably run a topology check after this
Jon Hall73cf9cc2014-11-20 22:28:38 -08002539 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002540 assert numControllers, "numControllers not defined"
2541 assert main, "main not defined"
2542 assert utilities.assert_equals, "utilities.assert_equals not defined"
2543 assert CLIs, "CLIs not defined"
2544 assert nodes, "nodes not defined"
2545 assert ONOS1Port, "ONOS1Port not defined"
2546 assert ONOS2Port, "ONOS2Port not defined"
2547 assert ONOS3Port, "ONOS3Port not defined"
2548 assert ONOS4Port, "ONOS4Port not defined"
2549 assert ONOS5Port, "ONOS5Port not defined"
2550 assert ONOS6Port, "ONOS6Port not defined"
2551 assert ONOS7Port, "ONOS7Port not defined"
Jon Hall669173b2014-12-17 11:36:30 -08002552
Jon Hall8f89dda2015-01-22 16:03:33 -08002553 switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
Jon Hall6aec96b2015-01-19 14:49:31 -08002554 switch = main.params[ 'kill' ][ 'switch' ]
2555 switchDPID = main.params[ 'kill' ][ 'dpid' ]
2556 links = main.params[ 'kill' ][ 'links' ].split()
Jon Hall73cf9cc2014-11-20 22:28:38 -08002557 description = "Adding a switch to ensure it is discovered correctly"
Jon Hall6aec96b2015-01-19 14:49:31 -08002558 main.case( description )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002559
Jon Hall6aec96b2015-01-19 14:49:31 -08002560 main.step( "Add back " + switch )
Jon Hall8f89dda2015-01-22 16:03:33 -08002561 main.Mininet1.addSwitch( switch, dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002562 for peer in links:
Jon Hall8f89dda2015-01-22 16:03:33 -08002563 main.Mininet1.addLink( switch, peer )
Jon Hall58c76b72015-02-23 11:09:24 -08002564 main.Mininet1.assignSwController( sw=switch.split( 's' )[ 1 ],
2565 count=numControllers,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002566 ip1=nodes[ 0 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002567 port1=ONOS1Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002568 ip2=nodes[ 1 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002569 port2=ONOS2Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002570 ip3=nodes[ 2 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002571 port3=ONOS3Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002572 ip4=nodes[ 3 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002573 port4=ONOS4Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002574 ip5=nodes[ 4 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002575 port5=ONOS5Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002576 ip6=nodes[ 5 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002577 port6=ONOS6Port,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002578 ip7=nodes[ 6 ].ip_address,
Jon Hall58c76b72015-02-23 11:09:24 -08002579 port7=ONOS7Port )
2580 main.log.info( "Waiting " + str( switchSleep ) +
2581 " seconds for switch up to be discovered" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002582 time.sleep( switchSleep )
2583 device = main.ONOScli1.getDevice( dpid=switchDPID )
Jon Hall6aec96b2015-01-19 14:49:31 -08002584 # Peek at the deleted switch
2585 main.log.warn( str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08002586 result = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002587 if device and device[ 'available' ]:
Jon Hall94fd0472014-12-08 11:52:42 -08002588 result = main.TRUE
Jon Hall6aec96b2015-01-19 14:49:31 -08002589 utilities.assert_equals( expect=main.TRUE, actual=result,
Jon Hall5cfd23c2015-03-19 11:40:57 -07002590 onpass="add switch successful",
Jon Hall58c76b72015-02-23 11:09:24 -08002591 onfail="Failed to add switch?" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002592
Jon Hall6aec96b2015-01-19 14:49:31 -08002593 def CASE13( self, main ):
2594 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002595 Clean up
Jon Hall6aec96b2015-01-19 14:49:31 -08002596 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08002597 import os
2598 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002599 assert numControllers, "numControllers not defined"
2600 assert main, "main not defined"
2601 assert utilities.assert_equals, "utilities.assert_equals not defined"
2602 assert CLIs, "CLIs not defined"
2603 assert nodes, "nodes not defined"
Jon Hall6aec96b2015-01-19 14:49:31 -08002604
2605 # printing colors to terminal
Jon Hall5cfd23c2015-03-19 11:40:57 -07002606 colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
2607 'blue': '\033[94m', 'green': '\033[92m',
2608 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
Jon Hall40d2cbd2015-06-03 16:24:29 -07002609 main.case( "Test Cleanup" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002610 main.step( "Killing tcpdumps" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002611 main.Mininet2.stopTcpdump()
Jon Hall73cf9cc2014-11-20 22:28:38 -08002612
Jon Hall6aec96b2015-01-19 14:49:31 -08002613 main.step( "Copying MN pcap and ONOS log files to test station" )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002614 testname = main.TEST
Jon Hall8f89dda2015-01-22 16:03:33 -08002615 teststationUser = main.params[ 'TESTONUSER' ]
2616 teststationIP = main.params[ 'TESTONIP' ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002617 # NOTE: MN Pcap file is being saved to ~/packet_captures
Jon Hall73cf9cc2014-11-20 22:28:38 -08002618 # scp this file as MN and TestON aren't necessarily the same vm
Jon Hall6aec96b2015-01-19 14:49:31 -08002619 # FIXME: scp
2620 # mn files
2621 # TODO: Load these from params
2622 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002623 logFolder = "/opt/onos/log/"
2624 logFiles = [ "karaf.log", "karaf.log.1" ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002625 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002626 dstDir = "~/packet_captures/"
2627 for f in logFiles:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002628 for node in nodes:
2629 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2630 ":" + logFolder + f + " " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002631 teststationUser + "@" +
2632 teststationIP + ":" +
2633 dstDir + str( testname ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002634 "-" + node.name + "-" + f )
Jon Hall58c76b72015-02-23 11:09:24 -08002635 main.ONOSbench.handle.expect( "\$" )
2636
Jon Hall6aec96b2015-01-19 14:49:31 -08002637 # std*.log's
2638 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002639 logFolder = "/opt/onos/var/"
2640 logFiles = [ "stderr.log", "stdout.log" ]
Jon Hall6aec96b2015-01-19 14:49:31 -08002641 # NOTE: must end in /
Jon Hall8f89dda2015-01-22 16:03:33 -08002642 dstDir = "~/packet_captures/"
2643 for f in logFiles:
Jon Hall5cfd23c2015-03-19 11:40:57 -07002644 for node in nodes:
2645 main.ONOSbench.handle.sendline( "scp sdn@" + node.ip_address +
2646 ":" + logFolder + f + " " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002647 teststationUser + "@" +
2648 teststationIP + ":" +
2649 dstDir + str( testname ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002650 "-" + node.name + "-" + f )
Jon Hall58c76b72015-02-23 11:09:24 -08002651 main.ONOSbench.handle.expect( "\$" )
Jon Hall6aec96b2015-01-19 14:49:31 -08002652 # sleep so scp can finish
2653 time.sleep( 10 )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002654
2655 main.step( "Stopping Mininet" )
Jon Hall390696c2015-05-05 17:13:41 -07002656 mnResult = main.Mininet1.stopNet()
2657 utilities.assert_equals( expect=main.TRUE, actual=mnResult,
2658 onpass="Mininet stopped",
2659 onfail="MN cleanup NOT successful" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002660
2661 main.step( "Checking ONOS Logs for errors" )
2662 for node in nodes:
2663 print colors[ 'purple' ] + "Checking logs for errors on " + \
2664 node.name + ":" + colors[ 'end' ]
Jon Hall40d2cbd2015-06-03 16:24:29 -07002665 print main.ONOSbench.checkLogs( node.ip_address, restart=True )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002666
Jon Hall6aec96b2015-01-19 14:49:31 -08002667 main.step( "Packing and rotating pcap archives" )
2668 os.system( "~/TestON/dependencies/rotate.sh " + str( testname ) )
Jon Hall73cf9cc2014-11-20 22:28:38 -08002669
Jon Hallfeff3082015-05-19 10:23:26 -07002670 try:
2671 timerLog = open( main.logdir + "/Timers.csv", 'w')
2672 # Overwrite with empty line and close
Jon Hall40d2cbd2015-06-03 16:24:29 -07002673 labels = "Gossip Intents, Restart"
2674 data = str( gossipTime ) + ", " + str( main.restartTime )
2675 timerLog.write( labels + "\n" + data )
Jon Hallfeff3082015-05-19 10:23:26 -07002676 timerLog.close()
2677 except NameError, e:
2678 main.log.exception(e)
2679
Jon Hall6aec96b2015-01-19 14:49:31 -08002680 def CASE14( self, main ):
2681 """
Jon Hall669173b2014-12-17 11:36:30 -08002682 start election app on all onos nodes
Jon Hall6aec96b2015-01-19 14:49:31 -08002683 """
Jon Hall5cfd23c2015-03-19 11:40:57 -07002684 assert numControllers, "numControllers not defined"
2685 assert main, "main not defined"
2686 assert utilities.assert_equals, "utilities.assert_equals not defined"
2687 assert CLIs, "CLIs not defined"
2688 assert nodes, "nodes not defined"
2689
Jon Hall390696c2015-05-05 17:13:41 -07002690 main.case("Start Leadership Election app")
2691 main.step( "Install leadership election app" )
Jon Hallfeff3082015-05-19 10:23:26 -07002692 appResult = main.ONOScli1.activateApp( "org.onosproject.election" )
2693 utilities.assert_equals(
2694 expect=main.TRUE,
2695 actual=appResult,
2696 onpass="Election app installed",
2697 onfail="Something went wrong with installing Leadership election" )
2698
2699 main.step( "Run for election on each node" )
2700 leaderResult = main.TRUE
Jon Halla9d26da2015-03-30 16:45:32 -07002701 leaders = []
2702 for cli in CLIs:
Jon Hall390696c2015-05-05 17:13:41 -07002703 cli.electionTestRun()
2704 for cli in CLIs:
Jon Halla9d26da2015-03-30 16:45:32 -07002705 leader = cli.electionTestLeader()
2706 if leader is None or leader == main.FALSE:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002707 main.log.error( cli.name + ": Leader for the election app " +
Jon Halla9d26da2015-03-30 16:45:32 -07002708 "should be an ONOS node, instead got '" +
2709 str( leader ) + "'" )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002710 leaderResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002711 leaders.append( leader )
Jon Hall6aec96b2015-01-19 14:49:31 -08002712 utilities.assert_equals(
2713 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002714 actual=leaderResult,
Jon Hallfeff3082015-05-19 10:23:26 -07002715 onpass="Successfully ran for leadership",
2716 onfail="Failed to run for leadership" )
2717
2718 main.step( "Check that each node shows the same leader" )
2719 sameLeader = main.TRUE
2720 if len( set( leaders ) ) != 1:
2721 sameLeader = main.FALSE
2722 main.log.error( "Results of electionTestLeader is order of CLIs:" +
2723 str( leaders ) )
2724 utilities.assert_equals(
2725 expect=main.TRUE,
2726 actual=sameLeader,
2727 onpass="Leadership is consistent for the election topic",
2728 onfail="Nodes have different leaders" )
Jon Hall669173b2014-12-17 11:36:30 -08002729
Jon Hall6aec96b2015-01-19 14:49:31 -08002730 def CASE15( self, main ):
2731 """
Jon Hall669173b2014-12-17 11:36:30 -08002732 Check that Leadership Election is still functional
Jon Hall6aec96b2015-01-19 14:49:31 -08002733 """
Jon Hall390696c2015-05-05 17:13:41 -07002734 import time
Jon Hall5cfd23c2015-03-19 11:40:57 -07002735 assert numControllers, "numControllers not defined"
2736 assert main, "main not defined"
2737 assert utilities.assert_equals, "utilities.assert_equals not defined"
2738 assert CLIs, "CLIs not defined"
2739 assert nodes, "nodes not defined"
2740
Jon Hall8f89dda2015-01-22 16:03:33 -08002741 leaderResult = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08002742 description = "Check that Leadership Election is still functional"
Jon Hall6aec96b2015-01-19 14:49:31 -08002743 main.case( description )
Jon Hallfeff3082015-05-19 10:23:26 -07002744
2745 main.step( "Check that each node shows the same leader" )
2746 sameLeader = main.TRUE
2747 leaders = []
2748 for cli in CLIs:
2749 leader = cli.electionTestLeader()
2750 leaders.append( leader )
2751 if len( set( leaders ) ) != 1:
2752 sameLeader = main.FALSE
2753 main.log.error( "Results of electionTestLeader is order of CLIs:" +
2754 str( leaders ) )
2755 utilities.assert_equals(
2756 expect=main.TRUE,
2757 actual=sameLeader,
2758 onpass="Leadership is consistent for the election topic",
2759 onfail="Nodes have different leaders" )
2760
Jon Hall6aec96b2015-01-19 14:49:31 -08002761 main.step( "Find current leader and withdraw" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002762 leader = main.ONOScli1.electionTestLeader()
Jon Halla9d26da2015-03-30 16:45:32 -07002763 # do some sanity checking on leader before using it
Jon Hall8f89dda2015-01-22 16:03:33 -08002764 withdrawResult = main.FALSE
Jon Hall5cfd23c2015-03-19 11:40:57 -07002765 if leader is None or leader == main.FALSE:
Jon Hallfeff3082015-05-19 10:23:26 -07002766 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -08002767 "Leader for the election app should be an ONOS node," +
Jon Hall58c76b72015-02-23 11:09:24 -08002768 "instead got '" + str( leader ) + "'" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002769 leaderResult = main.FALSE
Jon Hall63604932015-02-26 17:09:50 -08002770 oldLeader = None
Jon Hall5cfd23c2015-03-19 11:40:57 -07002771 for i in range( len( CLIs ) ):
2772 if leader == nodes[ i ].ip_address:
2773 oldLeader = CLIs[ i ]
2774 break
Jon Halla9d26da2015-03-30 16:45:32 -07002775 else: # FOR/ELSE statement
Jon Hall5cfd23c2015-03-19 11:40:57 -07002776 main.log.error( "Leader election, could not find current leader" )
Jon Hall63604932015-02-26 17:09:50 -08002777 if oldLeader:
2778 withdrawResult = oldLeader.electionTestWithdraw()
Jon Hall6aec96b2015-01-19 14:49:31 -08002779 utilities.assert_equals(
2780 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002781 actual=withdrawResult,
Jon Hallfeff3082015-05-19 10:23:26 -07002782 onpass="Node was withdrawn from election",
2783 onfail="Node was not withdrawn from election" )
Jon Hall669173b2014-12-17 11:36:30 -08002784
Jon Hall6aec96b2015-01-19 14:49:31 -08002785 main.step( "Make sure new leader is elected" )
Jon Halla9d26da2015-03-30 16:45:32 -07002786 # FIXME: use threads
Jon Hall8f89dda2015-01-22 16:03:33 -08002787 leaderList = []
Jon Hall5cfd23c2015-03-19 11:40:57 -07002788 for cli in CLIs:
2789 leaderN = cli.electionTestLeader()
2790 leaderList.append( leaderN )
Jon Hall669173b2014-12-17 11:36:30 -08002791 if leaderN == leader:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002792 main.log.error( cli.name + " still sees " + str( leader ) +
Jon Hall5cfd23c2015-03-19 11:40:57 -07002793 " as leader after they withdrew" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002794 leaderResult = main.FALSE
Jon Hall669173b2014-12-17 11:36:30 -08002795 elif leaderN == main.FALSE:
Jon Hall6aec96b2015-01-19 14:49:31 -08002796 # error in response
2797 # TODO: add check for "Command not found:" in the driver, this
Jon Hall5cfd23c2015-03-19 11:40:57 -07002798 # means the app isn't loaded
Jon Hall40d2cbd2015-06-03 16:24:29 -07002799 main.log.error( "Something is wrong with " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002800 "electionTestLeader function, " +
Jon Hall6aec96b2015-01-19 14:49:31 -08002801 "check the error logs" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002802 leaderResult = main.FALSE
Jon Halla9d26da2015-03-30 16:45:32 -07002803 elif leaderN is None:
2804 # node may not have recieved the event yet
Jon Hall390696c2015-05-05 17:13:41 -07002805 time.sleep(7)
Jon Halla9d26da2015-03-30 16:45:32 -07002806 leaderN = cli.electionTestLeader()
2807 leaderList.pop()
2808 leaderList.append( leaderN )
Jon Hall8f89dda2015-01-22 16:03:33 -08002809 consistentLeader = main.FALSE
2810 if len( set( leaderList ) ) == 1:
Jon Hall6aec96b2015-01-19 14:49:31 -08002811 main.log.info( "Each Election-app sees '" +
Jon Hall8f89dda2015-01-22 16:03:33 -08002812 str( leaderList[ 0 ] ) +
Jon Hall6aec96b2015-01-19 14:49:31 -08002813 "' as the leader" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002814 consistentLeader = main.TRUE
Jon Hall669173b2014-12-17 11:36:30 -08002815 else:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002816 main.log.error(
Jon Hall6aec96b2015-01-19 14:49:31 -08002817 "Inconsistent responses for leader of Election-app:" )
Jon Hall8f89dda2015-01-22 16:03:33 -08002818 for n in range( len( leaderList ) ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07002819 main.log.error( "ONOS" + str( n + 1 ) + " response: " +
Jon Hall8f89dda2015-01-22 16:03:33 -08002820 str( leaderList[ n ] ) )
Jon Hall5cfd23c2015-03-19 11:40:57 -07002821 leaderResult = leaderResult and consistentLeader
Jon Hall6aec96b2015-01-19 14:49:31 -08002822 utilities.assert_equals(
2823 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002824 actual=leaderResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002825 onpass="Leadership election passed",
2826 onfail="Something went wrong with Leadership election" )
Jon Hall669173b2014-12-17 11:36:30 -08002827
Jon Hall58c76b72015-02-23 11:09:24 -08002828 main.step( "Run for election on old leader( just so everyone " +
2829 "is in the hat )" )
Jon Hall63604932015-02-26 17:09:50 -08002830 if oldLeader:
2831 runResult = oldLeader.electionTestRun()
2832 else:
2833 runResult = main.FALSE
Jon Hall6aec96b2015-01-19 14:49:31 -08002834 utilities.assert_equals(
2835 expect=main.TRUE,
Jon Hall8f89dda2015-01-22 16:03:33 -08002836 actual=runResult,
Jon Hall6aec96b2015-01-19 14:49:31 -08002837 onpass="App re-ran for election",
2838 onfail="App failed to run for election" )
Jon Hall390696c2015-05-05 17:13:41 -07002839
Jon Hallfeff3082015-05-19 10:23:26 -07002840 main.step( "Leader did not change when old leader re-ran" )
Jon Hall390696c2015-05-05 17:13:41 -07002841 afterRun = main.ONOScli1.electionTestLeader()
2842 # verify leader didn't just change
2843 if afterRun == leaderList[ 0 ]:
2844 afterResult = main.TRUE
2845 else:
2846 afterResult = main.FALSE
Jon Hall669173b2014-12-17 11:36:30 -08002847
Jon Hall6aec96b2015-01-19 14:49:31 -08002848 utilities.assert_equals(
2849 expect=main.TRUE,
Jon Hall390696c2015-05-05 17:13:41 -07002850 actual=afterResult,
2851 onpass="Old leader successfully re-ran for election",
Jon Hall6aec96b2015-01-19 14:49:31 -08002852 onfail="Something went wrong with Leadership election after " +
2853 "the old leader re-ran for election" )
Jon Hall390696c2015-05-05 17:13:41 -07002854
Jon Hall390696c2015-05-05 17:13:41 -07002855 def CASE16( self, main ):
2856 """
2857 Install Distributed Primitives app
2858 """
Jon Hall40d2cbd2015-06-03 16:24:29 -07002859 import time
Jon Hall390696c2015-05-05 17:13:41 -07002860 assert numControllers, "numControllers not defined"
2861 assert main, "main not defined"
2862 assert utilities.assert_equals, "utilities.assert_equals not defined"
2863 assert CLIs, "CLIs not defined"
2864 assert nodes, "nodes not defined"
2865
2866 # Variables for the distributed primitives tests
2867 global pCounterName
2868 global iCounterName
2869 global pCounterValue
2870 global iCounterValue
2871 global onosSet
2872 global onosSetName
2873 pCounterName = "TestON-Partitions"
2874 iCounterName = "TestON-inMemory"
2875 pCounterValue = 0
2876 iCounterValue = 0
2877 onosSet = set([])
2878 onosSetName = "TestON-set"
2879
2880 description = "Install Primitives app"
2881 main.case( description )
2882 main.step( "Install Primitives app" )
2883 appName = "org.onosproject.distributedprimitives"
2884 appResults = CLIs[0].activateApp( appName )
2885 utilities.assert_equals( expect=main.TRUE,
2886 actual=appResults,
2887 onpass="Primitives app activated",
2888 onfail="Primitives app not activated" )
Jon Hall40d2cbd2015-06-03 16:24:29 -07002889 time.sleep( 5 ) # To allow all nodes to activate
Jon Hall390696c2015-05-05 17:13:41 -07002890
2891 def CASE17( self, main ):
2892 """
2893 Check for basic functionality with distributed primitives
2894 """
Jon Hallc9eabec2015-06-10 14:33:14 -07002895 import json
Jon Hall390696c2015-05-05 17:13:41 -07002896 # Make sure variables are defined/set
2897 assert numControllers, "numControllers not defined"
2898 assert main, "main not defined"
2899 assert utilities.assert_equals, "utilities.assert_equals not defined"
2900 assert CLIs, "CLIs not defined"
2901 assert nodes, "nodes not defined"
2902 assert pCounterName, "pCounterName not defined"
2903 assert iCounterName, "iCounterName not defined"
2904 assert onosSetName, "onosSetName not defined"
2905 # NOTE: assert fails if value is 0/None/Empty/False
2906 try:
2907 pCounterValue
2908 except NameError:
2909 main.log.error( "pCounterValue not defined, setting to 0" )
2910 pCounterValue = 0
2911 try:
2912 iCounterValue
2913 except NameError:
2914 main.log.error( "iCounterValue not defined, setting to 0" )
2915 iCounterValue = 0
2916 try:
2917 onosSet
2918 except NameError:
2919 main.log.error( "onosSet not defined, setting to empty Set" )
2920 onosSet = set([])
2921 # Variables for the distributed primitives tests. These are local only
2922 addValue = "a"
2923 addAllValue = "a b c d e f"
2924 retainValue = "c d e f"
2925
2926 description = "Check for basic functionality with distributed " +\
2927 "primitives"
2928 main.case( description )
2929 main.caseExplaination = "Test the methods of the distributed primitives (counters and sets) throught the cli"
2930 # DISTRIBUTED ATOMIC COUNTERS
2931 main.step( "Increment and get a default counter on each node" )
2932 pCounters = []
2933 threads = []
Jon Hallfeff3082015-05-19 10:23:26 -07002934 addedPValues = []
Jon Hall390696c2015-05-05 17:13:41 -07002935 for i in range( numControllers ):
2936 t = main.Thread( target=CLIs[i].counterTestIncrement,
2937 name="counterIncrement-" + str( i ),
2938 args=[ pCounterName ] )
2939 pCounterValue += 1
Jon Hallfeff3082015-05-19 10:23:26 -07002940 addedPValues.append( pCounterValue )
Jon Hall390696c2015-05-05 17:13:41 -07002941 threads.append( t )
2942 t.start()
2943
2944 for t in threads:
2945 t.join()
2946 pCounters.append( t.result )
2947 # Check that counter incremented numController times
2948 pCounterResults = True
Jon Hallfeff3082015-05-19 10:23:26 -07002949 for i in addedPValues:
Jon Hall40d2cbd2015-06-03 16:24:29 -07002950 tmpResult = i in pCounters
Jon Hallfeff3082015-05-19 10:23:26 -07002951 pCounterResults = pCounterResults and tmpResult
2952 if not tmpResult:
2953 main.log.error( str( i ) + " is not in partitioned "
2954 "counter incremented results" )
Jon Hall390696c2015-05-05 17:13:41 -07002955 utilities.assert_equals( expect=True,
2956 actual=pCounterResults,
2957 onpass="Default counter incremented",
2958 onfail="Error incrementing default" +
2959 " counter" )
2960
2961 main.step( "Increment and get an in memory counter on each node" )
2962 iCounters = []
Jon Hallfeff3082015-05-19 10:23:26 -07002963 addedIValues = []
Jon Hall390696c2015-05-05 17:13:41 -07002964 threads = []
2965 for i in range( numControllers ):
2966 t = main.Thread( target=CLIs[i].counterTestIncrement,
2967 name="icounterIncrement-" + str( i ),
2968 args=[ iCounterName ],
2969 kwargs={ "inMemory": True } )
2970 iCounterValue += 1
Jon Hallfeff3082015-05-19 10:23:26 -07002971 addedIValues.append( iCounterValue )
Jon Hall390696c2015-05-05 17:13:41 -07002972 threads.append( t )
2973 t.start()
2974
2975 for t in threads:
2976 t.join()
2977 iCounters.append( t.result )
2978 # Check that counter incremented numController times
2979 iCounterResults = True
Jon Hallfeff3082015-05-19 10:23:26 -07002980 for i in addedIValues:
2981 tmpResult = i in iCounters
2982 iCounterResults = iCounterResults and tmpResult
2983 if not tmpResult:
2984 main.log.error( str( i ) + " is not in the in-memory "
2985 "counter incremented results" )
Jon Hall390696c2015-05-05 17:13:41 -07002986 utilities.assert_equals( expect=True,
2987 actual=iCounterResults,
2988 onpass="In memory counter incremented",
2989 onfail="Error incrementing in memory" +
2990 " counter" )
2991
2992 main.step( "Check counters are consistant across nodes" )
2993 onosCounters = []
2994 threads = []
2995 for i in range( numControllers ):
2996 t = main.Thread( target=CLIs[i].counters,
2997 name="counters-" + str( i ) )
2998 threads.append( t )
2999 t.start()
3000 for t in threads:
3001 t.join()
3002 onosCounters.append( t.result )
3003 tmp = [ i == onosCounters[ 0 ] for i in onosCounters ]
3004 if all( tmp ):
3005 main.log.info( "Counters are consistent across all nodes" )
3006 consistentCounterResults = main.TRUE
3007 else:
3008 main.log.error( "Counters are not consistent across all nodes" )
3009 consistentCounterResults = main.FALSE
3010 utilities.assert_equals( expect=main.TRUE,
3011 actual=consistentCounterResults,
3012 onpass="ONOS counters are consistent " +
3013 "across nodes",
3014 onfail="ONOS Counters are inconsistent " +
3015 "across nodes" )
3016
3017 main.step( "Counters we added have the correct values" )
3018 correctResults = main.TRUE
3019 for i in range( numControllers ):
Jon Hall40d2cbd2015-06-03 16:24:29 -07003020 current = json.loads( onosCounters[i] )
3021 pValue = None
3022 iValue = None
Jon Hall390696c2015-05-05 17:13:41 -07003023 try:
Jon Hall40d2cbd2015-06-03 16:24:29 -07003024 for database in current:
3025 partitioned = database.get( 'partitionedDatabaseCounters' )
3026 if partitioned:
3027 for value in partitioned:
3028 if value.get( 'name' ) == pCounterName:
3029 pValue = value.get( 'value' )
3030 break
3031 inMemory = database.get( 'inMemoryDatabaseCounters' )
3032 if inMemory:
3033 for value in inMemory:
3034 if value.get( 'name' ) == iCounterName:
3035 iValue = value.get( 'value' )
3036 break
Jon Hall390696c2015-05-05 17:13:41 -07003037 except AttributeError, e:
3038 main.log.error( "ONOS" + str( i + 1 ) + " counters result " +
3039 "is not as expected" )
3040 correctResults = main.FALSE
Jon Hall40d2cbd2015-06-03 16:24:29 -07003041 if pValue == pCounterValue:
3042 main.log.info( "Partitioned counter value is correct" )
3043 else:
3044 main.log.error( "Partitioned counter value is incorrect," +
3045 " expected value: " + str( pCounterValue )
3046 + " current value: " + str( pValue ) )
3047 correctResults = main.FALSE
3048 if iValue == iCounterValue:
3049 main.log.info( "In memory counter value is correct" )
3050 else:
3051 main.log.error( "In memory counter value is incorrect, " +
3052 "expected value: " + str( iCounterValue ) +
3053 " current value: " + str( iValue ) )
3054 correctResults = main.FALSE
Jon Hall390696c2015-05-05 17:13:41 -07003055 utilities.assert_equals( expect=main.TRUE,
3056 actual=correctResults,
3057 onpass="Added counters are correct",
3058 onfail="Added counters are incorrect" )
3059 # DISTRIBUTED SETS
3060 main.step( "Distributed Set get" )
3061 size = len( onosSet )
3062 getResponses = []
3063 threads = []
3064 for i in range( numControllers ):
3065 t = main.Thread( target=CLIs[i].setTestGet,
3066 name="setTestGet-" + str( i ),
3067 args=[ onosSetName ] )
3068 threads.append( t )
3069 t.start()
3070 for t in threads:
3071 t.join()
3072 getResponses.append( t.result )
3073
3074 getResults = main.TRUE
3075 for i in range( numControllers ):
3076 if isinstance( getResponses[ i ], list):
3077 current = set( getResponses[ i ] )
3078 if len( current ) == len( getResponses[ i ] ):
3079 # no repeats
3080 if onosSet != current:
3081 main.log.error( "ONOS" + str( i + 1 ) +
3082 " has incorrect view" +
3083 " of set " + onosSetName + ":\n" +
3084 str( getResponses[ i ] ) )
3085 main.log.debug( "Expected: " + str( onosSet ) )
3086 main.log.debug( "Actual: " + str( current ) )
3087 getResults = main.FALSE
3088 else:
3089 # error, set is not a set
3090 main.log.error( "ONOS" + str( i + 1 ) +
3091 " has repeat elements in" +
3092 " set " + onosSetName + ":\n" +
3093 str( getResponses[ i ] ) )
3094 getResults = main.FALSE
3095 elif getResponses[ i ] == main.ERROR:
3096 getResults = main.FALSE
3097 utilities.assert_equals( expect=main.TRUE,
3098 actual=getResults,
3099 onpass="Set elements are correct",
3100 onfail="Set elements are incorrect" )
3101
3102 main.step( "Distributed Set size" )
3103 sizeResponses = []
3104 threads = []
3105 for i in range( numControllers ):
3106 t = main.Thread( target=CLIs[i].setTestSize,
3107 name="setTestSize-" + str( i ),
3108 args=[ onosSetName ] )
3109 threads.append( t )
3110 t.start()
3111 for t in threads:
3112 t.join()
3113 sizeResponses.append( t.result )
3114
3115 sizeResults = main.TRUE
3116 for i in range( numControllers ):
3117 if size != sizeResponses[ i ]:
3118 sizeResults = main.FALSE
3119 main.log.error( "ONOS" + str( i + 1 ) +
3120 " expected a size of " + str( size ) +
3121 " for set " + onosSetName +
3122 " but got " + str( sizeResponses[ i ] ) )
3123 utilities.assert_equals( expect=main.TRUE,
3124 actual=sizeResults,
3125 onpass="Set sizes are correct",
3126 onfail="Set sizes are incorrect" )
3127
3128 main.step( "Distributed Set add()" )
3129 onosSet.add( addValue )
3130 addResponses = []
3131 threads = []
3132 for i in range( numControllers ):
3133 t = main.Thread( target=CLIs[i].setTestAdd,
3134 name="setTestAdd-" + str( i ),
3135 args=[ onosSetName, addValue ] )
3136 threads.append( t )
3137 t.start()
3138 for t in threads:
3139 t.join()
3140 addResponses.append( t.result )
3141
3142 # main.TRUE = successfully changed the set
3143 # main.FALSE = action resulted in no change in set
3144 # main.ERROR - Some error in executing the function
3145 addResults = main.TRUE
3146 for i in range( numControllers ):
3147 if addResponses[ i ] == main.TRUE:
3148 # All is well
3149 pass
3150 elif addResponses[ i ] == main.FALSE:
3151 # Already in set, probably fine
3152 pass
3153 elif addResponses[ i ] == main.ERROR:
3154 # Error in execution
3155 addResults = main.FALSE
3156 else:
3157 # unexpected result
3158 addResults = main.FALSE
3159 if addResults != main.TRUE:
3160 main.log.error( "Error executing set add" )
3161
3162 # Check if set is still correct
3163 size = len( onosSet )
3164 getResponses = []
3165 threads = []
3166 for i in range( numControllers ):
3167 t = main.Thread( target=CLIs[i].setTestGet,
3168 name="setTestGet-" + str( i ),
3169 args=[ onosSetName ] )
3170 threads.append( t )
3171 t.start()
3172 for t in threads:
3173 t.join()
3174 getResponses.append( t.result )
3175 getResults = main.TRUE
3176 for i in range( numControllers ):
3177 if isinstance( getResponses[ i ], list):
3178 current = set( getResponses[ i ] )
3179 if len( current ) == len( getResponses[ i ] ):
3180 # no repeats
3181 if onosSet != current:
3182 main.log.error( "ONOS" + str( i + 1 ) +
3183 " has incorrect view" +
3184 " of set " + onosSetName + ":\n" +
3185 str( getResponses[ i ] ) )
3186 main.log.debug( "Expected: " + str( onosSet ) )
3187 main.log.debug( "Actual: " + str( current ) )
3188 getResults = main.FALSE
3189 else:
3190 # error, set is not a set
3191 main.log.error( "ONOS" + str( i + 1 ) +
3192 " has repeat elements in" +
3193 " set " + onosSetName + ":\n" +
3194 str( getResponses[ i ] ) )
3195 getResults = main.FALSE
3196 elif getResponses[ i ] == main.ERROR:
3197 getResults = main.FALSE
3198 sizeResponses = []
3199 threads = []
3200 for i in range( numControllers ):
3201 t = main.Thread( target=CLIs[i].setTestSize,
3202 name="setTestSize-" + str( i ),
3203 args=[ onosSetName ] )
3204 threads.append( t )
3205 t.start()
3206 for t in threads:
3207 t.join()
3208 sizeResponses.append( t.result )
3209 sizeResults = main.TRUE
3210 for i in range( numControllers ):
3211 if size != sizeResponses[ i ]:
3212 sizeResults = main.FALSE
3213 main.log.error( "ONOS" + str( i + 1 ) +
3214 " expected a size of " + str( size ) +
3215 " for set " + onosSetName +
3216 " but got " + str( sizeResponses[ i ] ) )
3217 addResults = addResults and getResults and sizeResults
3218 utilities.assert_equals( expect=main.TRUE,
3219 actual=addResults,
3220 onpass="Set add correct",
3221 onfail="Set add was incorrect" )
3222
3223 main.step( "Distributed Set addAll()" )
3224 onosSet.update( addAllValue.split() )
3225 addResponses = []
3226 threads = []
3227 for i in range( numControllers ):
3228 t = main.Thread( target=CLIs[i].setTestAdd,
3229 name="setTestAddAll-" + str( i ),
3230 args=[ onosSetName, addAllValue ] )
3231 threads.append( t )
3232 t.start()
3233 for t in threads:
3234 t.join()
3235 addResponses.append( t.result )
3236
3237 # main.TRUE = successfully changed the set
3238 # main.FALSE = action resulted in no change in set
3239 # main.ERROR - Some error in executing the function
3240 addAllResults = main.TRUE
3241 for i in range( numControllers ):
3242 if addResponses[ i ] == main.TRUE:
3243 # All is well
3244 pass
3245 elif addResponses[ i ] == main.FALSE:
3246 # Already in set, probably fine
3247 pass
3248 elif addResponses[ i ] == main.ERROR:
3249 # Error in execution
3250 addAllResults = main.FALSE
3251 else:
3252 # unexpected result
3253 addAllResults = main.FALSE
3254 if addAllResults != main.TRUE:
3255 main.log.error( "Error executing set addAll" )
3256
3257 # Check if set is still correct
3258 size = len( onosSet )
3259 getResponses = []
3260 threads = []
3261 for i in range( numControllers ):
3262 t = main.Thread( target=CLIs[i].setTestGet,
3263 name="setTestGet-" + str( i ),
3264 args=[ onosSetName ] )
3265 threads.append( t )
3266 t.start()
3267 for t in threads:
3268 t.join()
3269 getResponses.append( t.result )
3270 getResults = main.TRUE
3271 for i in range( numControllers ):
3272 if isinstance( getResponses[ i ], list):
3273 current = set( getResponses[ i ] )
3274 if len( current ) == len( getResponses[ i ] ):
3275 # no repeats
3276 if onosSet != current:
3277 main.log.error( "ONOS" + str( i + 1 ) +
3278 " has incorrect view" +
3279 " of set " + onosSetName + ":\n" +
3280 str( getResponses[ i ] ) )
3281 main.log.debug( "Expected: " + str( onosSet ) )
3282 main.log.debug( "Actual: " + str( current ) )
3283 getResults = main.FALSE
3284 else:
3285 # error, set is not a set
3286 main.log.error( "ONOS" + str( i + 1 ) +
3287 " has repeat elements in" +
3288 " set " + onosSetName + ":\n" +
3289 str( getResponses[ i ] ) )
3290 getResults = main.FALSE
3291 elif getResponses[ i ] == main.ERROR:
3292 getResults = main.FALSE
3293 sizeResponses = []
3294 threads = []
3295 for i in range( numControllers ):
3296 t = main.Thread( target=CLIs[i].setTestSize,
3297 name="setTestSize-" + str( i ),
3298 args=[ onosSetName ] )
3299 threads.append( t )
3300 t.start()
3301 for t in threads:
3302 t.join()
3303 sizeResponses.append( t.result )
3304 sizeResults = main.TRUE
3305 for i in range( numControllers ):
3306 if size != sizeResponses[ i ]:
3307 sizeResults = main.FALSE
3308 main.log.error( "ONOS" + str( i + 1 ) +
3309 " expected a size of " + str( size ) +
3310 " for set " + onosSetName +
3311 " but got " + str( sizeResponses[ i ] ) )
3312 addAllResults = addAllResults and getResults and sizeResults
3313 utilities.assert_equals( expect=main.TRUE,
3314 actual=addAllResults,
3315 onpass="Set addAll correct",
3316 onfail="Set addAll was incorrect" )
3317
3318 main.step( "Distributed Set contains()" )
3319 containsResponses = []
3320 threads = []
3321 for i in range( numControllers ):
3322 t = main.Thread( target=CLIs[i].setTestGet,
3323 name="setContains-" + str( i ),
3324 args=[ onosSetName ],
3325 kwargs={ "values": addValue } )
3326 threads.append( t )
3327 t.start()
3328 for t in threads:
3329 t.join()
3330 # NOTE: This is the tuple
3331 containsResponses.append( t.result )
3332
3333 containsResults = main.TRUE
3334 for i in range( numControllers ):
3335 if containsResponses[ i ] == main.ERROR:
3336 containsResults = main.FALSE
3337 else:
3338 containsResults = containsResults and\
3339 containsResponses[ i ][ 1 ]
3340 utilities.assert_equals( expect=main.TRUE,
3341 actual=containsResults,
3342 onpass="Set contains is functional",
3343 onfail="Set contains failed" )
3344
3345 main.step( "Distributed Set containsAll()" )
3346 containsAllResponses = []
3347 threads = []
3348 for i in range( numControllers ):
3349 t = main.Thread( target=CLIs[i].setTestGet,
3350 name="setContainsAll-" + str( i ),
3351 args=[ onosSetName ],
3352 kwargs={ "values": addAllValue } )
3353 threads.append( t )
3354 t.start()
3355 for t in threads:
3356 t.join()
3357 # NOTE: This is the tuple
3358 containsAllResponses.append( t.result )
3359
3360 containsAllResults = main.TRUE
3361 for i in range( numControllers ):
3362 if containsResponses[ i ] == main.ERROR:
3363 containsResults = main.FALSE
3364 else:
3365 containsResults = containsResults and\
3366 containsResponses[ i ][ 1 ]
3367 utilities.assert_equals( expect=main.TRUE,
3368 actual=containsAllResults,
3369 onpass="Set containsAll is functional",
3370 onfail="Set containsAll failed" )
3371
3372 main.step( "Distributed Set remove()" )
3373 onosSet.remove( addValue )
3374 removeResponses = []
3375 threads = []
3376 for i in range( numControllers ):
3377 t = main.Thread( target=CLIs[i].setTestRemove,
3378 name="setTestRemove-" + str( i ),
3379 args=[ onosSetName, addValue ] )
3380 threads.append( t )
3381 t.start()
3382 for t in threads:
3383 t.join()
3384 removeResponses.append( t.result )
3385
3386 # main.TRUE = successfully changed the set
3387 # main.FALSE = action resulted in no change in set
3388 # main.ERROR - Some error in executing the function
3389 removeResults = main.TRUE
3390 for i in range( numControllers ):
3391 if removeResponses[ i ] == main.TRUE:
3392 # All is well
3393 pass
3394 elif removeResponses[ i ] == main.FALSE:
3395 # not in set, probably fine
3396 pass
3397 elif removeResponses[ i ] == main.ERROR:
3398 # Error in execution
3399 removeResults = main.FALSE
3400 else:
3401 # unexpected result
3402 removeResults = main.FALSE
3403 if removeResults != main.TRUE:
3404 main.log.error( "Error executing set remove" )
3405
3406 # Check if set is still correct
3407 size = len( onosSet )
3408 getResponses = []
3409 threads = []
3410 for i in range( numControllers ):
3411 t = main.Thread( target=CLIs[i].setTestGet,
3412 name="setTestGet-" + str( i ),
3413 args=[ onosSetName ] )
3414 threads.append( t )
3415 t.start()
3416 for t in threads:
3417 t.join()
3418 getResponses.append( t.result )
3419 getResults = main.TRUE
3420 for i in range( numControllers ):
3421 if isinstance( getResponses[ i ], list):
3422 current = set( getResponses[ i ] )
3423 if len( current ) == len( getResponses[ i ] ):
3424 # no repeats
3425 if onosSet != current:
3426 main.log.error( "ONOS" + str( i + 1 ) +
3427 " has incorrect view" +
3428 " of set " + onosSetName + ":\n" +
3429 str( getResponses[ i ] ) )
3430 main.log.debug( "Expected: " + str( onosSet ) )
3431 main.log.debug( "Actual: " + str( current ) )
3432 getResults = main.FALSE
3433 else:
3434 # error, set is not a set
3435 main.log.error( "ONOS" + str( i + 1 ) +
3436 " has repeat elements in" +
3437 " set " + onosSetName + ":\n" +
3438 str( getResponses[ i ] ) )
3439 getResults = main.FALSE
3440 elif getResponses[ i ] == main.ERROR:
3441 getResults = main.FALSE
3442 sizeResponses = []
3443 threads = []
3444 for i in range( numControllers ):
3445 t = main.Thread( target=CLIs[i].setTestSize,
3446 name="setTestSize-" + str( i ),
3447 args=[ onosSetName ] )
3448 threads.append( t )
3449 t.start()
3450 for t in threads:
3451 t.join()
3452 sizeResponses.append( t.result )
3453 sizeResults = main.TRUE
3454 for i in range( numControllers ):
3455 if size != sizeResponses[ i ]:
3456 sizeResults = main.FALSE
3457 main.log.error( "ONOS" + str( i + 1 ) +
3458 " expected a size of " + str( size ) +
3459 " for set " + onosSetName +
3460 " but got " + str( sizeResponses[ i ] ) )
3461 removeResults = removeResults and getResults and sizeResults
3462 utilities.assert_equals( expect=main.TRUE,
3463 actual=removeResults,
3464 onpass="Set remove correct",
3465 onfail="Set remove was incorrect" )
3466
3467 main.step( "Distributed Set removeAll()" )
3468 onosSet.difference_update( addAllValue.split() )
3469 removeAllResponses = []
3470 threads = []
3471 try:
3472 for i in range( numControllers ):
3473 t = main.Thread( target=CLIs[i].setTestRemove,
3474 name="setTestRemoveAll-" + str( i ),
3475 args=[ onosSetName, addAllValue ] )
3476 threads.append( t )
3477 t.start()
3478 for t in threads:
3479 t.join()
3480 removeAllResponses.append( t.result )
3481 except Exception, e:
3482 main.log.exception(e)
3483
3484 # main.TRUE = successfully changed the set
3485 # main.FALSE = action resulted in no change in set
3486 # main.ERROR - Some error in executing the function
3487 removeAllResults = main.TRUE
3488 for i in range( numControllers ):
3489 if removeAllResponses[ i ] == main.TRUE:
3490 # All is well
3491 pass
3492 elif removeAllResponses[ i ] == main.FALSE:
3493 # not in set, probably fine
3494 pass
3495 elif removeAllResponses[ i ] == main.ERROR:
3496 # Error in execution
3497 removeAllResults = main.FALSE
3498 else:
3499 # unexpected result
3500 removeAllResults = main.FALSE
3501 if removeAllResults != main.TRUE:
3502 main.log.error( "Error executing set removeAll" )
3503
3504 # Check if set is still correct
3505 size = len( onosSet )
3506 getResponses = []
3507 threads = []
3508 for i in range( numControllers ):
3509 t = main.Thread( target=CLIs[i].setTestGet,
3510 name="setTestGet-" + str( i ),
3511 args=[ onosSetName ] )
3512 threads.append( t )
3513 t.start()
3514 for t in threads:
3515 t.join()
3516 getResponses.append( t.result )
3517 getResults = main.TRUE
3518 for i in range( numControllers ):
3519 if isinstance( getResponses[ i ], list):
3520 current = set( getResponses[ i ] )
3521 if len( current ) == len( getResponses[ i ] ):
3522 # no repeats
3523 if onosSet != current:
3524 main.log.error( "ONOS" + str( i + 1 ) +
3525 " has incorrect view" +
3526 " of set " + onosSetName + ":\n" +
3527 str( getResponses[ i ] ) )
3528 main.log.debug( "Expected: " + str( onosSet ) )
3529 main.log.debug( "Actual: " + str( current ) )
3530 getResults = main.FALSE
3531 else:
3532 # error, set is not a set
3533 main.log.error( "ONOS" + str( i + 1 ) +
3534 " has repeat elements in" +
3535 " set " + onosSetName + ":\n" +
3536 str( getResponses[ i ] ) )
3537 getResults = main.FALSE
3538 elif getResponses[ i ] == main.ERROR:
3539 getResults = main.FALSE
3540 sizeResponses = []
3541 threads = []
3542 for i in range( numControllers ):
3543 t = main.Thread( target=CLIs[i].setTestSize,
3544 name="setTestSize-" + str( i ),
3545 args=[ onosSetName ] )
3546 threads.append( t )
3547 t.start()
3548 for t in threads:
3549 t.join()
3550 sizeResponses.append( t.result )
3551 sizeResults = main.TRUE
3552 for i in range( numControllers ):
3553 if size != sizeResponses[ i ]:
3554 sizeResults = main.FALSE
3555 main.log.error( "ONOS" + str( i + 1 ) +
3556 " expected a size of " + str( size ) +
3557 " for set " + onosSetName +
3558 " but got " + str( sizeResponses[ i ] ) )
3559 removeAllResults = removeAllResults and getResults and sizeResults
3560 utilities.assert_equals( expect=main.TRUE,
3561 actual=removeAllResults,
3562 onpass="Set removeAll correct",
3563 onfail="Set removeAll was incorrect" )
3564
3565 main.step( "Distributed Set addAll()" )
3566 onosSet.update( addAllValue.split() )
3567 addResponses = []
3568 threads = []
3569 for i in range( numControllers ):
3570 t = main.Thread( target=CLIs[i].setTestAdd,
3571 name="setTestAddAll-" + str( i ),
3572 args=[ onosSetName, addAllValue ] )
3573 threads.append( t )
3574 t.start()
3575 for t in threads:
3576 t.join()
3577 addResponses.append( t.result )
3578
3579 # main.TRUE = successfully changed the set
3580 # main.FALSE = action resulted in no change in set
3581 # main.ERROR - Some error in executing the function
3582 addAllResults = main.TRUE
3583 for i in range( numControllers ):
3584 if addResponses[ i ] == main.TRUE:
3585 # All is well
3586 pass
3587 elif addResponses[ i ] == main.FALSE:
3588 # Already in set, probably fine
3589 pass
3590 elif addResponses[ i ] == main.ERROR:
3591 # Error in execution
3592 addAllResults = main.FALSE
3593 else:
3594 # unexpected result
3595 addAllResults = main.FALSE
3596 if addAllResults != main.TRUE:
3597 main.log.error( "Error executing set addAll" )
3598
3599 # Check if set is still correct
3600 size = len( onosSet )
3601 getResponses = []
3602 threads = []
3603 for i in range( numControllers ):
3604 t = main.Thread( target=CLIs[i].setTestGet,
3605 name="setTestGet-" + str( i ),
3606 args=[ onosSetName ] )
3607 threads.append( t )
3608 t.start()
3609 for t in threads:
3610 t.join()
3611 getResponses.append( t.result )
3612 getResults = main.TRUE
3613 for i in range( numControllers ):
3614 if isinstance( getResponses[ i ], list):
3615 current = set( getResponses[ i ] )
3616 if len( current ) == len( getResponses[ i ] ):
3617 # no repeats
3618 if onosSet != current:
3619 main.log.error( "ONOS" + str( i + 1 ) +
3620 " has incorrect view" +
3621 " of set " + onosSetName + ":\n" +
3622 str( getResponses[ i ] ) )
3623 main.log.debug( "Expected: " + str( onosSet ) )
3624 main.log.debug( "Actual: " + str( current ) )
3625 getResults = main.FALSE
3626 else:
3627 # error, set is not a set
3628 main.log.error( "ONOS" + str( i + 1 ) +
3629 " has repeat elements in" +
3630 " set " + onosSetName + ":\n" +
3631 str( getResponses[ i ] ) )
3632 getResults = main.FALSE
3633 elif getResponses[ i ] == main.ERROR:
3634 getResults = main.FALSE
3635 sizeResponses = []
3636 threads = []
3637 for i in range( numControllers ):
3638 t = main.Thread( target=CLIs[i].setTestSize,
3639 name="setTestSize-" + str( i ),
3640 args=[ onosSetName ] )
3641 threads.append( t )
3642 t.start()
3643 for t in threads:
3644 t.join()
3645 sizeResponses.append( t.result )
3646 sizeResults = main.TRUE
3647 for i in range( numControllers ):
3648 if size != sizeResponses[ i ]:
3649 sizeResults = main.FALSE
3650 main.log.error( "ONOS" + str( i + 1 ) +
3651 " expected a size of " + str( size ) +
3652 " for set " + onosSetName +
3653 " but got " + str( sizeResponses[ i ] ) )
3654 addAllResults = addAllResults and getResults and sizeResults
3655 utilities.assert_equals( expect=main.TRUE,
3656 actual=addAllResults,
3657 onpass="Set addAll correct",
3658 onfail="Set addAll was incorrect" )
3659
3660 main.step( "Distributed Set clear()" )
3661 onosSet.clear()
3662 clearResponses = []
3663 threads = []
3664 for i in range( numControllers ):
3665 t = main.Thread( target=CLIs[i].setTestRemove,
3666 name="setTestClear-" + str( i ),
3667 args=[ onosSetName, " "], # Values doesn't matter
3668 kwargs={ "clear": True } )
3669 threads.append( t )
3670 t.start()
3671 for t in threads:
3672 t.join()
3673 clearResponses.append( t.result )
3674
3675 # main.TRUE = successfully changed the set
3676 # main.FALSE = action resulted in no change in set
3677 # main.ERROR - Some error in executing the function
3678 clearResults = main.TRUE
3679 for i in range( numControllers ):
3680 if clearResponses[ i ] == main.TRUE:
3681 # All is well
3682 pass
3683 elif clearResponses[ i ] == main.FALSE:
3684 # Nothing set, probably fine
3685 pass
3686 elif clearResponses[ i ] == main.ERROR:
3687 # Error in execution
3688 clearResults = main.FALSE
3689 else:
3690 # unexpected result
3691 clearResults = main.FALSE
3692 if clearResults != main.TRUE:
3693 main.log.error( "Error executing set clear" )
3694
3695 # Check if set is still correct
3696 size = len( onosSet )
3697 getResponses = []
3698 threads = []
3699 for i in range( numControllers ):
3700 t = main.Thread( target=CLIs[i].setTestGet,
3701 name="setTestGet-" + str( i ),
3702 args=[ onosSetName ] )
3703 threads.append( t )
3704 t.start()
3705 for t in threads:
3706 t.join()
3707 getResponses.append( t.result )
3708 getResults = main.TRUE
3709 for i in range( numControllers ):
3710 if isinstance( getResponses[ i ], list):
3711 current = set( getResponses[ i ] )
3712 if len( current ) == len( getResponses[ i ] ):
3713 # no repeats
3714 if onosSet != current:
3715 main.log.error( "ONOS" + str( i + 1 ) +
3716 " has incorrect view" +
3717 " of set " + onosSetName + ":\n" +
3718 str( getResponses[ i ] ) )
3719 main.log.debug( "Expected: " + str( onosSet ) )
3720 main.log.debug( "Actual: " + str( current ) )
3721 getResults = main.FALSE
3722 else:
3723 # error, set is not a set
3724 main.log.error( "ONOS" + str( i + 1 ) +
3725 " has repeat elements in" +
3726 " set " + onosSetName + ":\n" +
3727 str( getResponses[ i ] ) )
3728 getResults = main.FALSE
3729 elif getResponses[ i ] == main.ERROR:
3730 getResults = main.FALSE
3731 sizeResponses = []
3732 threads = []
3733 for i in range( numControllers ):
3734 t = main.Thread( target=CLIs[i].setTestSize,
3735 name="setTestSize-" + str( i ),
3736 args=[ onosSetName ] )
3737 threads.append( t )
3738 t.start()
3739 for t in threads:
3740 t.join()
3741 sizeResponses.append( t.result )
3742 sizeResults = main.TRUE
3743 for i in range( numControllers ):
3744 if size != sizeResponses[ i ]:
3745 sizeResults = main.FALSE
3746 main.log.error( "ONOS" + str( i + 1 ) +
3747 " expected a size of " + str( size ) +
3748 " for set " + onosSetName +
3749 " but got " + str( sizeResponses[ i ] ) )
3750 clearResults = clearResults and getResults and sizeResults
3751 utilities.assert_equals( expect=main.TRUE,
3752 actual=clearResults,
3753 onpass="Set clear correct",
3754 onfail="Set clear was incorrect" )
3755
3756 main.step( "Distributed Set addAll()" )
3757 onosSet.update( addAllValue.split() )
3758 addResponses = []
3759 threads = []
3760 for i in range( numControllers ):
3761 t = main.Thread( target=CLIs[i].setTestAdd,
3762 name="setTestAddAll-" + str( i ),
3763 args=[ onosSetName, addAllValue ] )
3764 threads.append( t )
3765 t.start()
3766 for t in threads:
3767 t.join()
3768 addResponses.append( t.result )
3769
3770 # main.TRUE = successfully changed the set
3771 # main.FALSE = action resulted in no change in set
3772 # main.ERROR - Some error in executing the function
3773 addAllResults = main.TRUE
3774 for i in range( numControllers ):
3775 if addResponses[ i ] == main.TRUE:
3776 # All is well
3777 pass
3778 elif addResponses[ i ] == main.FALSE:
3779 # Already in set, probably fine
3780 pass
3781 elif addResponses[ i ] == main.ERROR:
3782 # Error in execution
3783 addAllResults = main.FALSE
3784 else:
3785 # unexpected result
3786 addAllResults = main.FALSE
3787 if addAllResults != main.TRUE:
3788 main.log.error( "Error executing set addAll" )
3789
3790 # Check if set is still correct
3791 size = len( onosSet )
3792 getResponses = []
3793 threads = []
3794 for i in range( numControllers ):
3795 t = main.Thread( target=CLIs[i].setTestGet,
3796 name="setTestGet-" + str( i ),
3797 args=[ onosSetName ] )
3798 threads.append( t )
3799 t.start()
3800 for t in threads:
3801 t.join()
3802 getResponses.append( t.result )
3803 getResults = main.TRUE
3804 for i in range( numControllers ):
3805 if isinstance( getResponses[ i ], list):
3806 current = set( getResponses[ i ] )
3807 if len( current ) == len( getResponses[ i ] ):
3808 # no repeats
3809 if onosSet != current:
3810 main.log.error( "ONOS" + str( i + 1 ) +
3811 " has incorrect view" +
3812 " of set " + onosSetName + ":\n" +
3813 str( getResponses[ i ] ) )
3814 main.log.debug( "Expected: " + str( onosSet ) )
3815 main.log.debug( "Actual: " + str( current ) )
3816 getResults = main.FALSE
3817 else:
3818 # error, set is not a set
3819 main.log.error( "ONOS" + str( i + 1 ) +
3820 " has repeat elements in" +
3821 " set " + onosSetName + ":\n" +
3822 str( getResponses[ i ] ) )
3823 getResults = main.FALSE
3824 elif getResponses[ i ] == main.ERROR:
3825 getResults = main.FALSE
3826 sizeResponses = []
3827 threads = []
3828 for i in range( numControllers ):
3829 t = main.Thread( target=CLIs[i].setTestSize,
3830 name="setTestSize-" + str( i ),
3831 args=[ onosSetName ] )
3832 threads.append( t )
3833 t.start()
3834 for t in threads:
3835 t.join()
3836 sizeResponses.append( t.result )
3837 sizeResults = main.TRUE
3838 for i in range( numControllers ):
3839 if size != sizeResponses[ i ]:
3840 sizeResults = main.FALSE
3841 main.log.error( "ONOS" + str( i + 1 ) +
3842 " expected a size of " + str( size ) +
3843 " for set " + onosSetName +
3844 " but got " + str( sizeResponses[ i ] ) )
3845 addAllResults = addAllResults and getResults and sizeResults
3846 utilities.assert_equals( expect=main.TRUE,
3847 actual=addAllResults,
3848 onpass="Set addAll correct",
3849 onfail="Set addAll was incorrect" )
3850
3851 main.step( "Distributed Set retain()" )
3852 onosSet.intersection_update( retainValue.split() )
3853 retainResponses = []
3854 threads = []
3855 for i in range( numControllers ):
3856 t = main.Thread( target=CLIs[i].setTestRemove,
3857 name="setTestRetain-" + str( i ),
3858 args=[ onosSetName, retainValue ],
3859 kwargs={ "retain": True } )
3860 threads.append( t )
3861 t.start()
3862 for t in threads:
3863 t.join()
3864 retainResponses.append( t.result )
3865
3866 # main.TRUE = successfully changed the set
3867 # main.FALSE = action resulted in no change in set
3868 # main.ERROR - Some error in executing the function
3869 retainResults = main.TRUE
3870 for i in range( numControllers ):
3871 if retainResponses[ i ] == main.TRUE:
3872 # All is well
3873 pass
3874 elif retainResponses[ i ] == main.FALSE:
3875 # Already in set, probably fine
3876 pass
3877 elif retainResponses[ i ] == main.ERROR:
3878 # Error in execution
3879 retainResults = main.FALSE
3880 else:
3881 # unexpected result
3882 retainResults = main.FALSE
3883 if retainResults != main.TRUE:
3884 main.log.error( "Error executing set retain" )
3885
3886 # Check if set is still correct
3887 size = len( onosSet )
3888 getResponses = []
3889 threads = []
3890 for i in range( numControllers ):
3891 t = main.Thread( target=CLIs[i].setTestGet,
3892 name="setTestGet-" + str( i ),
3893 args=[ onosSetName ] )
3894 threads.append( t )
3895 t.start()
3896 for t in threads:
3897 t.join()
3898 getResponses.append( t.result )
3899 getResults = main.TRUE
3900 for i in range( numControllers ):
3901 if isinstance( getResponses[ i ], list):
3902 current = set( getResponses[ i ] )
3903 if len( current ) == len( getResponses[ i ] ):
3904 # no repeats
3905 if onosSet != current:
3906 main.log.error( "ONOS" + str( i + 1 ) +
3907 " has incorrect view" +
3908 " of set " + onosSetName + ":\n" +
3909 str( getResponses[ i ] ) )
3910 main.log.debug( "Expected: " + str( onosSet ) )
3911 main.log.debug( "Actual: " + str( current ) )
3912 getResults = main.FALSE
3913 else:
3914 # error, set is not a set
3915 main.log.error( "ONOS" + str( i + 1 ) +
3916 " has repeat elements in" +
3917 " set " + onosSetName + ":\n" +
3918 str( getResponses[ i ] ) )
3919 getResults = main.FALSE
3920 elif getResponses[ i ] == main.ERROR:
3921 getResults = main.FALSE
3922 sizeResponses = []
3923 threads = []
3924 for i in range( numControllers ):
3925 t = main.Thread( target=CLIs[i].setTestSize,
3926 name="setTestSize-" + str( i ),
3927 args=[ onosSetName ] )
3928 threads.append( t )
3929 t.start()
3930 for t in threads:
3931 t.join()
3932 sizeResponses.append( t.result )
3933 sizeResults = main.TRUE
3934 for i in range( numControllers ):
3935 if size != sizeResponses[ i ]:
3936 sizeResults = main.FALSE
3937 main.log.error( "ONOS" + str( i + 1 ) +
3938 " expected a size of " +
3939 str( size ) + " for set " + onosSetName +
3940 " but got " + str( sizeResponses[ i ] ) )
3941 retainResults = retainResults and getResults and sizeResults
3942 utilities.assert_equals( expect=main.TRUE,
3943 actual=retainResults,
3944 onpass="Set retain correct",
3945 onfail="Set retain was incorrect" )
3946