blob: ab63b5dc188649ad44682b6d186abcee24ad3221 [file] [log] [blame]
Jon Hall9ebd1bd2016-04-19 01:37:17 -07001"""
2Description: This test is to determine if ONOS can handle
3 dynamic scaling of the cluster size.
4
5List of test cases:
6CASE1: Compile ONOS and push it to the test machines
7CASE2: Assign devices to controllers
8CASE21: Assign mastership to controllers
9CASE3: Assign intents
10CASE4: Ping across added host intents
11CASE5: Reading state of ONOS
12CASE6: The scaling 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
20CASE14: start election app on all onos nodes
21CASE15: Check that Leadership Election is still functional
22CASE16: Install Distributed Primitives app
23CASE17: Check for basic functionality with distributed primitives
24"""
Jon Hall9ebd1bd2016-04-19 01:37:17 -070025class HAscaling:
26
27 def __init__( self ):
28 self.default = ''
29
30 def CASE1( self, main ):
31 """
32 CASE1 is to compile ONOS and push it to the test machines
33
34 Startup sequence:
35 cell <name>
36 onos-verify-cell
37 NOTE: temporary - onos-remove-raft-logs
38 onos-uninstall
39 start mininet
40 git pull
41 mvn clean install
42 onos-package
43 onos-install -f
44 onos-wait-for-start
45 start cli sessions
46 start tcpdump
47 """
48 import time
49 import os
50 import re
51 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
52 "initialization" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070053 # set global variables
54 # These are for csv plotting in jenkins
Devin Lim58046fa2017-07-05 16:55:00 -070055 main.HAlabels = []
56 main.HAdata = []
57 try:
58 from tests.dependencies.ONOSSetup import ONOSSetup
59 main.testSetUp = ONOSSetup()
60 except ImportError:
61 main.log.error( "ONOSSetup not found exiting the test" )
62 main.exit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -070063
Devin Lim58046fa2017-07-05 16:55:00 -070064 main.testSetUp.envSetupDescription()
Jon Hall9ebd1bd2016-04-19 01:37:17 -070065 try:
66 from tests.HA.dependencies.HA import HA
67 main.HA = HA()
Devin Lim58046fa2017-07-05 16:55:00 -070068 from tests.HA.HAswapNodes.dependencies.Server import Server
Jon Hall9ebd1bd2016-04-19 01:37:17 -070069 main.Server = Server()
Devin Lim58046fa2017-07-05 16:55:00 -070070
71 # load some variables from the params file
72 cellName = main.params[ 'ENV' ][ 'cellName' ]
73 main.apps = main.params[ 'ENV' ][ 'appString' ]
74 main.numCtrls = int( main.params[ 'num_controllers' ] )
75 if main.ONOSbench.maxNodes and\
76 main.ONOSbench.maxNodes < main.numCtrls:
77 main.numCtrls = int( main.ONOSbench.maxNodes )
78 main.maxNodes = main.numCtrls
79 stepResult = main.testSetUp.envSetup( hasNode=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070080 except Exception as e:
Devin Lim58046fa2017-07-05 16:55:00 -070081 main.testSetUp.envSetupException( e )
82 main.testSetUp.evnSetupConclusion( stepResult )
83 main.HA.generateGraph( "HAscaling", index=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070084
Devin Lim58046fa2017-07-05 16:55:00 -070085 main.testSetUp.ONOSSetUp( main.Mininet1, cellName=cellName, removeLog=True,
86 extraApply=main.HA.customizeOnosService,
87 arg=main.HA.scalingMetadata,
88 extraClean=main.HA.cleanUpOnosService,
89 installMax=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070090
Devin Lim58046fa2017-07-05 16:55:00 -070091 main.HA.initialSetUp( True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070092
93 def CASE2( self, main ):
94 """
95 Assign devices to controllers
96 """
Devin Lim58046fa2017-07-05 16:55:00 -070097 main.HA.assignDevices( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070098
99 def CASE21( self, main ):
100 """
101 Assign mastership to controllers
102 """
Devin Lim58046fa2017-07-05 16:55:00 -0700103 main.HA.assignMastership( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700104
105 def CASE3( self, main ):
106 """
107 Assign intents
108 """
Devin Lim58046fa2017-07-05 16:55:00 -0700109 main.HA.assignIntents( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700110
111 def CASE4( self, main ):
112 """
113 Ping across added host intents
114 """
Devin Lim58046fa2017-07-05 16:55:00 -0700115 main.HA.pingAcrossHostIntent( main, True, True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700116
117 def CASE5( self, main ):
118 """
119 Reading state of ONOS
120 """
Devin Lim58046fa2017-07-05 16:55:00 -0700121 main.HA.readingState( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700122
123 def CASE6( self, main ):
124 """
125 The Scaling case.
126 """
127 import time
128 import re
129 assert main.numCtrls, "main.numCtrls not defined"
130 assert main, "main not defined"
131 assert utilities.assert_equals, "utilities.assert_equals not defined"
132 assert main.CLIs, "main.CLIs not defined"
133 assert main.nodes, "main.nodes not defined"
134 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700135 main.HAlabels
136 except ( NameError, AttributeError ):
137 main.log.error( "main.HAlabels not defined, setting to []" )
138 main.HAlabels = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700139 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700140 main.HAdata
141 except ( NameError, AttributeError ):
142 main.log.error( "main.HAdata not defined, setting to []" )
143 main.HAdata = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700144
Jon Hall69b2b982016-05-11 12:04:59 -0700145 main.case( "Scale the number of nodes in the ONOS cluster" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700146
147 main.step( "Checking ONOS Logs for errors" )
148 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700149 node = main.nodes[ i ]
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700150 main.log.debug( "Checking logs for errors on " + node.name + ":" )
151 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
152
153 """
154 pop # of nodes from a list, might look like 1,3b,3,5b,5,7b,7,7b,5,5b,3...
155 modify cluster.json file appropriately
156 install/deactivate node as needed
157 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700158 try:
159 prevNodes = main.activeNodes
Jon Hallf37d44d2017-05-24 10:37:30 -0700160 scale = main.scaling.pop( 0 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700161 if "e" in scale:
162 equal = True
163 else:
164 equal = False
Jon Hallf37d44d2017-05-24 10:37:30 -0700165 main.numCtrls = int( re.search( "\d+", scale ).group( 0 ) )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700166 main.log.info( "Scaling to {} nodes".format( main.numCtrls ) )
167 genResult = main.Server.generateFile( main.numCtrls, equal=equal )
168 utilities.assert_equals( expect=main.TRUE, actual=genResult,
169 onpass="New cluster metadata file generated",
170 onfail="Failled to generate new metadata file" )
171 time.sleep( 5 ) # Give time for nodes to read new file
172 except IndexError:
173 main.cleanup()
174 main.exit()
175
176 main.activeNodes = [ i for i in range( 0, main.numCtrls ) ]
177 newNodes = [ x for x in main.activeNodes if x not in prevNodes ]
178
179 main.step( "Start new nodes" ) # OR stop old nodes?
180 started = main.TRUE
181 for i in newNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700182 started = main.ONOSbench.onosStart( main.nodes[ i ].ip_address ) and main.TRUE
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700183 utilities.assert_equals( expect=main.TRUE, actual=started,
184 onpass="ONOS started",
185 onfail="ONOS start NOT successful" )
186
187 main.step( "Checking if ONOS is up yet" )
188 for i in range( 2 ):
189 onosIsupResult = main.TRUE
190 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700191 node = main.nodes[ i ]
Jon Hall168c1862017-01-31 17:35:34 -0800192 main.ONOSbench.onosSecureSSH( node=node.ip_address )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700193 started = main.ONOSbench.isup( node.ip_address )
194 if not started:
195 main.log.error( node.name + " didn't start!" )
196 onosIsupResult = onosIsupResult and started
197 if onosIsupResult == main.TRUE:
198 break
199 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
200 onpass="ONOS started",
201 onfail="ONOS start NOT successful" )
202
Jon Hall6509dbf2016-06-21 17:01:17 -0700203 main.step( "Starting ONOS CLI sessions" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700204 cliResults = main.TRUE
205 threads = []
206 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700207 t = main.Thread( target=main.CLIs[ i ].startOnosCli,
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700208 name="startOnosCli-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -0700209 args=[ main.nodes[ i ].ip_address ] )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700210 threads.append( t )
211 t.start()
212
213 for t in threads:
214 t.join()
215 cliResults = cliResults and t.result
216 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
217 onpass="ONOS cli started",
218 onfail="ONOS clis did not start" )
219
220 main.step( "Checking ONOS nodes" )
221 nodeResults = utilities.retry( main.HA.nodesCheck,
222 False,
Jon Hallf37d44d2017-05-24 10:37:30 -0700223 args=[ main.activeNodes ],
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700224 attempts=5 )
225 utilities.assert_equals( expect=True, actual=nodeResults,
226 onpass="Nodes check successful",
227 onfail="Nodes check NOT successful" )
228
229 for i in range( 10 ):
230 ready = True
231 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700232 cli = main.CLIs[ i ]
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700233 output = cli.summary()
234 if not output:
235 ready = False
236 if ready:
237 break
238 time.sleep( 30 )
239 utilities.assert_equals( expect=True, actual=ready,
240 onpass="ONOS summary command succeded",
241 onfail="ONOS summary command failed" )
242 if not ready:
243 main.cleanup()
244 main.exit()
245
246 # Rerun for election on new nodes
247 runResults = main.TRUE
248 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700249 cli = main.CLIs[ i ]
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700250 run = cli.electionTestRun()
251 if run != main.TRUE:
252 main.log.error( "Error running for election on " + cli.name )
253 runResults = runResults and run
254 utilities.assert_equals( expect=main.TRUE, actual=runResults,
255 onpass="Reran for election",
256 onfail="Failed to rerun for election" )
257
258 # TODO: Make this configurable
259 time.sleep( 60 )
260 for node in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700261 main.log.warn( "\n****************** {} **************".format( main.nodes[ node ].ip_address ) )
262 main.log.debug( main.CLIs[ node ].nodes( jsonFormat=False ) )
263 main.log.debug( main.CLIs[ node ].leaders( jsonFormat=False ) )
264 main.log.debug( main.CLIs[ node ].partitions( jsonFormat=False ) )
265 main.log.debug( main.CLIs[ node ].apps( jsonFormat=False ) )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700266
267 def CASE7( self, main ):
268 """
269 Check state after ONOS scaling
270 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700271
Devin Lim58046fa2017-07-05 16:55:00 -0700272 main.HA.checkStateAfterONOS( main, afterWhich=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700273
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700274 main.step( "Leadership Election is still functional" )
275 # Test of LeadershipElection
276 leaderList = []
277 leaderResult = main.TRUE
278
279 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700280 cli = main.CLIs[ i ]
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700281 leaderN = cli.electionTestLeader()
282 leaderList.append( leaderN )
283 if leaderN == main.FALSE:
284 # error in response
285 main.log.error( "Something is wrong with " +
286 "electionTestLeader function, check the" +
287 " error logs" )
288 leaderResult = main.FALSE
289 elif leaderN is None:
290 main.log.error( cli.name +
291 " shows no leader for the election-app." )
292 leaderResult = main.FALSE
293 if len( set( leaderList ) ) != 1:
294 leaderResult = main.FALSE
295 main.log.error(
296 "Inconsistent view of leader for the election test app" )
297 # TODO: print the list
298 utilities.assert_equals(
299 expect=main.TRUE,
300 actual=leaderResult,
301 onpass="Leadership election passed",
302 onfail="Something went wrong with Leadership election" )
303
304 def CASE8( self, main ):
305 """
306 Compare topo
307 """
Devin Lim58046fa2017-07-05 16:55:00 -0700308 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700309
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700310 def CASE9( self, main ):
311 """
312 Link s3-s28 down
313 """
Devin Lim58046fa2017-07-05 16:55:00 -0700314 main.HA.linkDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700315
316 def CASE10( self, main ):
317 """
318 Link s3-s28 up
319 """
Devin Lim58046fa2017-07-05 16:55:00 -0700320 main.HA.linkUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700321
322 def CASE11( self, main ):
323 """
324 Switch Down
325 """
326 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700327 main.HA.switchDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700328
329 def CASE12( self, main ):
330 """
331 Switch Up
332 """
333 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700334 main.HA.switchUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700335
336 def CASE13( self, main ):
337 """
338 Clean up
339 """
Devin Lim58046fa2017-07-05 16:55:00 -0700340 main.HA.cleanUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700341
342 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700343 status = main.Server.stop()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700344 utilities.assert_equals( expect=main.TRUE, actual=status,
345 onpass="Stop Server",
346 onfail="Failled to stop SimpleHTTPServer" )
347 del main.Server
348
349 def CASE14( self, main ):
350 """
351 start election app on all onos nodes
352 """
Devin Lim58046fa2017-07-05 16:55:00 -0700353 main.HA.startElectionApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700354
355 def CASE15( self, main ):
356 """
357 Check that Leadership Election is still functional
358 15.1 Run election on each node
359 15.2 Check that each node has the same leaders and candidates
360 15.3 Find current leader and withdraw
361 15.4 Check that a new node was elected leader
362 15.5 Check that that new leader was the candidate of old leader
363 15.6 Run for election on old leader
364 15.7 Check that oldLeader is a candidate, and leader if only 1 node
365 15.8 Make sure that the old leader was added to the candidate list
366
367 old and new variable prefixes refer to data from before vs after
368 withdrawl and later before withdrawl vs after re-election
369 """
Devin Lim58046fa2017-07-05 16:55:00 -0700370 main.HA.isElectionFunctional( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700371
372 def CASE16( self, main ):
373 """
374 Install Distributed Primitives app
375 """
Devin Lim58046fa2017-07-05 16:55:00 -0700376 main.HA.installDistributedPrimitiveApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700377
378 def CASE17( self, main ):
379 """
380 Check for basic functionality with distributed primitives
381 """
Devin Lim58046fa2017-07-05 16:55:00 -0700382 main.HA.checkDistPrimitivesFunc( main )