blob: f35fa570ccaf8988ad47b3f029b6e6583cbb78f4 [file] [log] [blame]
Jon Hall9ebd1bd2016-04-19 01:37:17 -07001"""
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07002Copyright 2016 Open Networking Foundation (ONF)
3
4Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
5the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
6or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
12
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with TestON. If not, see <http://www.gnu.org/licenses/>.
20"""
21
22"""
Jon Hall9ebd1bd2016-04-19 01:37:17 -070023Description: This test is to determine if ONOS can handle
24 dynamic scaling of the cluster size.
25
26List of test cases:
27CASE1: Compile ONOS and push it to the test machines
28CASE2: Assign devices to controllers
29CASE21: Assign mastership to controllers
30CASE3: Assign intents
31CASE4: Ping across added host intents
32CASE5: Reading state of ONOS
33CASE6: The scaling case.
34CASE7: Check state after control plane failure
35CASE8: Compare topo
36CASE9: Link s3-s28 down
37CASE10: Link s3-s28 up
38CASE11: Switch down
39CASE12: Switch up
40CASE13: Clean up
41CASE14: start election app on all onos nodes
42CASE15: Check that Leadership Election is still functional
43CASE16: Install Distributed Primitives app
44CASE17: Check for basic functionality with distributed primitives
45"""
Jon Hall9ebd1bd2016-04-19 01:37:17 -070046class HAscaling:
47
48 def __init__( self ):
49 self.default = ''
50
51 def CASE1( self, main ):
52 """
53 CASE1 is to compile ONOS and push it to the test machines
54
55 Startup sequence:
56 cell <name>
57 onos-verify-cell
58 NOTE: temporary - onos-remove-raft-logs
59 onos-uninstall
60 start mininet
61 git pull
62 mvn clean install
63 onos-package
64 onos-install -f
65 onos-wait-for-start
66 start cli sessions
67 start tcpdump
68 """
69 import time
70 import os
71 import re
72 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
73 "initialization" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070074 # set global variables
75 # These are for csv plotting in jenkins
Devin Lim58046fa2017-07-05 16:55:00 -070076 main.HAlabels = []
77 main.HAdata = []
78 try:
79 from tests.dependencies.ONOSSetup import ONOSSetup
80 main.testSetUp = ONOSSetup()
81 except ImportError:
82 main.log.error( "ONOSSetup not found exiting the test" )
83 main.exit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -070084
Devin Lim58046fa2017-07-05 16:55:00 -070085 main.testSetUp.envSetupDescription()
Jon Hall9ebd1bd2016-04-19 01:37:17 -070086 try:
87 from tests.HA.dependencies.HA import HA
88 main.HA = HA()
Devin Lim58046fa2017-07-05 16:55:00 -070089 from tests.HA.HAswapNodes.dependencies.Server import Server
Jon Hall9ebd1bd2016-04-19 01:37:17 -070090 main.Server = Server()
Devin Lim58046fa2017-07-05 16:55:00 -070091
92 # load some variables from the params file
93 cellName = main.params[ 'ENV' ][ 'cellName' ]
94 main.apps = main.params[ 'ENV' ][ 'appString' ]
95 main.numCtrls = int( main.params[ 'num_controllers' ] )
96 if main.ONOSbench.maxNodes and\
97 main.ONOSbench.maxNodes < main.numCtrls:
98 main.numCtrls = int( main.ONOSbench.maxNodes )
99 main.maxNodes = main.numCtrls
100 stepResult = main.testSetUp.envSetup( hasNode=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700101 except Exception as e:
Devin Lim58046fa2017-07-05 16:55:00 -0700102 main.testSetUp.envSetupException( e )
103 main.testSetUp.evnSetupConclusion( stepResult )
104 main.HA.generateGraph( "HAscaling", index=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700105
Devin Lim58046fa2017-07-05 16:55:00 -0700106 main.testSetUp.ONOSSetUp( main.Mininet1, cellName=cellName, removeLog=True,
107 extraApply=main.HA.customizeOnosService,
108 arg=main.HA.scalingMetadata,
109 extraClean=main.HA.cleanUpOnosService,
110 installMax=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700111
Devin Lim58046fa2017-07-05 16:55:00 -0700112 main.HA.initialSetUp( True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700113
114 def CASE2( self, main ):
115 """
116 Assign devices to controllers
117 """
Devin Lim58046fa2017-07-05 16:55:00 -0700118 main.HA.assignDevices( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700119
120 def CASE21( self, main ):
121 """
122 Assign mastership to controllers
123 """
Devin Lim58046fa2017-07-05 16:55:00 -0700124 main.HA.assignMastership( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700125
126 def CASE3( self, main ):
127 """
128 Assign intents
129 """
Devin Lim58046fa2017-07-05 16:55:00 -0700130 main.HA.assignIntents( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700131
132 def CASE4( self, main ):
133 """
134 Ping across added host intents
135 """
Jon Hallca319892017-06-15 15:25:22 -0700136 main.HA.pingAcrossHostIntent( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700137
138 def CASE5( self, main ):
139 """
140 Reading state of ONOS
141 """
Devin Lim58046fa2017-07-05 16:55:00 -0700142 main.HA.readingState( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700143
144 def CASE6( self, main ):
145 """
146 The Scaling case.
147 """
148 import time
149 import re
150 assert main.numCtrls, "main.numCtrls not defined"
151 assert main, "main not defined"
152 assert utilities.assert_equals, "utilities.assert_equals not defined"
153 assert main.CLIs, "main.CLIs not defined"
154 assert main.nodes, "main.nodes not defined"
155 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700156 main.HAlabels
157 except ( NameError, AttributeError ):
158 main.log.error( "main.HAlabels not defined, setting to []" )
159 main.HAlabels = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700160 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700161 main.HAdata
162 except ( NameError, AttributeError ):
163 main.log.error( "main.HAdata not defined, setting to []" )
164 main.HAdata = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700165
Jon Hall69b2b982016-05-11 12:04:59 -0700166 main.case( "Scale the number of nodes in the ONOS cluster" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700167
168 main.step( "Checking ONOS Logs for errors" )
169 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700170 node = main.nodes[ i ]
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700171 main.log.debug( "Checking logs for errors on " + node.name + ":" )
172 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
173
174 """
175 pop # of nodes from a list, might look like 1,3b,3,5b,5,7b,7,7b,5,5b,3...
176 modify cluster.json file appropriately
177 install/deactivate node as needed
178 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700179 try:
180 prevNodes = main.activeNodes
Jon Hallf37d44d2017-05-24 10:37:30 -0700181 scale = main.scaling.pop( 0 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700182 if "e" in scale:
183 equal = True
184 else:
185 equal = False
Jon Hallf37d44d2017-05-24 10:37:30 -0700186 main.numCtrls = int( re.search( "\d+", scale ).group( 0 ) )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700187 main.log.info( "Scaling to {} nodes".format( main.numCtrls ) )
188 genResult = main.Server.generateFile( main.numCtrls, equal=equal )
189 utilities.assert_equals( expect=main.TRUE, actual=genResult,
190 onpass="New cluster metadata file generated",
191 onfail="Failled to generate new metadata file" )
192 time.sleep( 5 ) # Give time for nodes to read new file
193 except IndexError:
194 main.cleanup()
195 main.exit()
196
197 main.activeNodes = [ i for i in range( 0, main.numCtrls ) ]
198 newNodes = [ x for x in main.activeNodes if x not in prevNodes ]
199
200 main.step( "Start new nodes" ) # OR stop old nodes?
201 started = main.TRUE
202 for i in newNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700203 started = main.ONOSbench.onosStart( main.nodes[ i ].ip_address ) and main.TRUE
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700204 utilities.assert_equals( expect=main.TRUE, actual=started,
205 onpass="ONOS started",
206 onfail="ONOS start NOT successful" )
207
208 main.step( "Checking if ONOS is up yet" )
209 for i in range( 2 ):
210 onosIsupResult = main.TRUE
211 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700212 node = main.nodes[ i ]
Jon Hall168c1862017-01-31 17:35:34 -0800213 main.ONOSbench.onosSecureSSH( node=node.ip_address )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700214 started = main.ONOSbench.isup( node.ip_address )
215 if not started:
216 main.log.error( node.name + " didn't start!" )
217 onosIsupResult = onosIsupResult and started
218 if onosIsupResult == main.TRUE:
219 break
220 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
221 onpass="ONOS started",
222 onfail="ONOS start NOT successful" )
223
Jon Hall6509dbf2016-06-21 17:01:17 -0700224 main.step( "Starting ONOS CLI sessions" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700225 cliResults = main.TRUE
226 threads = []
227 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700228 t = main.Thread( target=main.CLIs[ i ].startOnosCli,
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700229 name="startOnosCli-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -0700230 args=[ main.nodes[ i ].ip_address ] )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700231 threads.append( t )
232 t.start()
233
234 for t in threads:
235 t.join()
236 cliResults = cliResults and t.result
237 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
238 onpass="ONOS cli started",
239 onfail="ONOS clis did not start" )
240
241 main.step( "Checking ONOS nodes" )
242 nodeResults = utilities.retry( main.HA.nodesCheck,
243 False,
Jon Hallf37d44d2017-05-24 10:37:30 -0700244 args=[ main.activeNodes ],
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700245 attempts=5 )
246 utilities.assert_equals( expect=True, actual=nodeResults,
247 onpass="Nodes check successful",
248 onfail="Nodes check NOT successful" )
249
250 for i in range( 10 ):
251 ready = True
252 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700253 cli = main.CLIs[ i ]
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700254 output = cli.summary()
255 if not output:
256 ready = False
257 if ready:
258 break
259 time.sleep( 30 )
260 utilities.assert_equals( expect=True, actual=ready,
261 onpass="ONOS summary command succeded",
262 onfail="ONOS summary command failed" )
263 if not ready:
264 main.cleanup()
265 main.exit()
266
267 # Rerun for election on new nodes
268 runResults = main.TRUE
269 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700270 cli = main.CLIs[ i ]
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700271 run = cli.electionTestRun()
272 if run != main.TRUE:
273 main.log.error( "Error running for election on " + cli.name )
274 runResults = runResults and run
275 utilities.assert_equals( expect=main.TRUE, actual=runResults,
276 onpass="Reran for election",
277 onfail="Failed to rerun for election" )
278
279 # TODO: Make this configurable
280 time.sleep( 60 )
281 for node in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700282 main.log.warn( "\n****************** {} **************".format( main.nodes[ node ].ip_address ) )
283 main.log.debug( main.CLIs[ node ].nodes( jsonFormat=False ) )
284 main.log.debug( main.CLIs[ node ].leaders( jsonFormat=False ) )
285 main.log.debug( main.CLIs[ node ].partitions( jsonFormat=False ) )
286 main.log.debug( main.CLIs[ node ].apps( jsonFormat=False ) )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700287
288 def CASE7( self, main ):
289 """
290 Check state after ONOS scaling
291 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700292
Devin Lim58046fa2017-07-05 16:55:00 -0700293 main.HA.checkStateAfterONOS( main, afterWhich=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700294
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700295 main.step( "Leadership Election is still functional" )
296 # Test of LeadershipElection
297 leaderList = []
298 leaderResult = main.TRUE
299
300 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700301 cli = main.CLIs[ i ]
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700302 leaderN = cli.electionTestLeader()
303 leaderList.append( leaderN )
304 if leaderN == main.FALSE:
305 # error in response
306 main.log.error( "Something is wrong with " +
307 "electionTestLeader function, check the" +
308 " error logs" )
309 leaderResult = main.FALSE
310 elif leaderN is None:
311 main.log.error( cli.name +
312 " shows no leader for the election-app." )
313 leaderResult = main.FALSE
314 if len( set( leaderList ) ) != 1:
315 leaderResult = main.FALSE
316 main.log.error(
317 "Inconsistent view of leader for the election test app" )
318 # TODO: print the list
319 utilities.assert_equals(
320 expect=main.TRUE,
321 actual=leaderResult,
322 onpass="Leadership election passed",
323 onfail="Something went wrong with Leadership election" )
324
325 def CASE8( self, main ):
326 """
327 Compare topo
328 """
Devin Lim58046fa2017-07-05 16:55:00 -0700329 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700330
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700331 def CASE9( self, main ):
332 """
333 Link s3-s28 down
334 """
Devin Lim58046fa2017-07-05 16:55:00 -0700335 main.HA.linkDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700336
337 def CASE10( self, main ):
338 """
339 Link s3-s28 up
340 """
Devin Lim58046fa2017-07-05 16:55:00 -0700341 main.HA.linkUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700342
343 def CASE11( self, main ):
344 """
345 Switch Down
346 """
347 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700348 main.HA.switchDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700349
350 def CASE12( self, main ):
351 """
352 Switch Up
353 """
354 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700355 main.HA.switchUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700356
357 def CASE13( self, main ):
358 """
359 Clean up
360 """
Devin Lim58046fa2017-07-05 16:55:00 -0700361 main.HA.cleanUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700362
363 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700364 status = main.Server.stop()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700365 utilities.assert_equals( expect=main.TRUE, actual=status,
366 onpass="Stop Server",
367 onfail="Failled to stop SimpleHTTPServer" )
368 del main.Server
369
370 def CASE14( self, main ):
371 """
372 start election app on all onos nodes
373 """
Devin Lim58046fa2017-07-05 16:55:00 -0700374 main.HA.startElectionApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700375
376 def CASE15( self, main ):
377 """
378 Check that Leadership Election is still functional
379 15.1 Run election on each node
380 15.2 Check that each node has the same leaders and candidates
381 15.3 Find current leader and withdraw
382 15.4 Check that a new node was elected leader
383 15.5 Check that that new leader was the candidate of old leader
384 15.6 Run for election on old leader
385 15.7 Check that oldLeader is a candidate, and leader if only 1 node
386 15.8 Make sure that the old leader was added to the candidate list
387
388 old and new variable prefixes refer to data from before vs after
389 withdrawl and later before withdrawl vs after re-election
390 """
Devin Lim58046fa2017-07-05 16:55:00 -0700391 main.HA.isElectionFunctional( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700392
393 def CASE16( self, main ):
394 """
395 Install Distributed Primitives app
396 """
Devin Lim58046fa2017-07-05 16:55:00 -0700397 main.HA.installDistributedPrimitiveApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700398
399 def CASE17( self, main ):
400 """
401 Check for basic functionality with distributed primitives
402 """
Devin Lim58046fa2017-07-05 16:55:00 -0700403 main.HA.checkDistPrimitivesFunc( main )