blob: e46271dc1efe27e896e3be6bf85bcb66efd0779f [file] [log] [blame]
Jon Hall9ebd1bd2016-04-19 01:37:17 -07001"""
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07002Copyright 2016 Open Networking Foundation ( ONF )
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07003
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
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070011 ( at your option ) any later version.
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -070012
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"""
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -070021"""
Jon Hall9ebd1bd2016-04-19 01:37:17 -070022Description: This test is to determine if ONOS can handle
23 dynamic scaling of the cluster size.
24
25List of test cases:
26CASE1: Compile ONOS and push it to the test machines
27CASE2: Assign devices to controllers
28CASE21: Assign mastership to controllers
29CASE3: Assign intents
30CASE4: Ping across added host intents
31CASE5: Reading state of ONOS
32CASE6: The scaling case.
33CASE7: Check state after control plane failure
34CASE8: Compare topo
35CASE9: Link s3-s28 down
36CASE10: Link s3-s28 up
37CASE11: Switch down
38CASE12: Switch up
39CASE13: Clean up
40CASE14: start election app on all onos nodes
41CASE15: Check that Leadership Election is still functional
42CASE16: Install Distributed Primitives app
43CASE17: Check for basic functionality with distributed primitives
44"""
Jon Hall9ebd1bd2016-04-19 01:37:17 -070045class HAscaling:
46
47 def __init__( self ):
48 self.default = ''
49
50 def CASE1( self, main ):
51 """
52 CASE1 is to compile ONOS and push it to the test machines
53
54 Startup sequence:
55 cell <name>
56 onos-verify-cell
57 NOTE: temporary - onos-remove-raft-logs
58 onos-uninstall
59 start mininet
60 git pull
61 mvn clean install
62 onos-package
63 onos-install -f
64 onos-wait-for-start
65 start cli sessions
66 start tcpdump
67 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -070068 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
69 "initialization" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070070 # set global variables
71 # These are for csv plotting in jenkins
Devin Lim58046fa2017-07-05 16:55:00 -070072 main.HAlabels = []
73 main.HAdata = []
74 try:
75 from tests.dependencies.ONOSSetup import ONOSSetup
76 main.testSetUp = ONOSSetup()
77 except ImportError:
Jon Hall4f360bc2017-09-07 10:19:52 -070078 main.log.error( "ONOSSetup not found. exiting the test" )
Devin Lim44075962017-08-11 10:56:37 -070079 main.cleanAndExit()
Devin Lim58046fa2017-07-05 16:55:00 -070080 main.testSetUp.envSetupDescription()
Jon Halla478b852017-12-04 15:00:15 -080081 main.Cluster.numCtrls = 1
Jon Hall9ebd1bd2016-04-19 01:37:17 -070082 try:
83 from tests.HA.dependencies.HA import HA
84 main.HA = HA()
Devin Lim58046fa2017-07-05 16:55:00 -070085 from tests.HA.HAswapNodes.dependencies.Server import Server
Jon Hall9ebd1bd2016-04-19 01:37:17 -070086 main.Server = Server()
Devin Lim58046fa2017-07-05 16:55:00 -070087 # load some variables from the params file
88 cellName = main.params[ 'ENV' ][ 'cellName' ]
89 main.apps = main.params[ 'ENV' ][ 'appString' ]
Jon Hallab611372018-02-21 15:26:05 -080090 stepResult = main.testSetUp.envSetup( includeCaseDesc=False )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070091 except Exception as e:
Devin Lim58046fa2017-07-05 16:55:00 -070092 main.testSetUp.envSetupException( e )
93 main.testSetUp.evnSetupConclusion( stepResult )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070094
Jon Hallab611372018-02-21 15:26:05 -080095 applyFuncs = [ main.HA.setServerForCluster,
96 main.HA.scalingMetadata,
97 main.HA.copyBackupConfig,
98 main.HA.setMetadataUrl ]
99 applyArgs = [ None, None, None, None ]
100 try:
101 if main.params[ 'topology' ][ 'topoFile' ]:
102 main.log.info( 'Skipping start of Mininet in this case, make sure you start it elsewhere' )
103 else:
104 applyFuncs.append( main.HA.startingMininet )
105 applyArgs.append( None )
106 except (KeyError, IndexError):
107 applyFuncs.append( main.HA.startingMininet )
108 applyArgs.append( None )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700109
Jon Hallab611372018-02-21 15:26:05 -0800110 main.testSetUp.ONOSSetUp( main.Cluster, cellName=cellName, removeLog=True,
111 extraApply=applyFuncs,
112 applyArgs=applyArgs,
113 extraClean=main.HA.cleanUpOnosService,
114 installMax=True,
115 includeCaseDesc=False )
Jon Hall4f360bc2017-09-07 10:19:52 -0700116 main.HA.initialSetUp( serviceClean=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700117
Jon Hallab611372018-02-21 15:26:05 -0800118 main.step( 'Set logging levels' )
119 logging = True
120 try:
121 logs = main.params.get( 'ONOS_Logging', False )
122 if logs:
123 for namespace, level in logs.items():
124 for ctrl in main.Cluster.active():
125 ctrl.CLI.logSet( level, namespace )
126 except AttributeError:
127 logging = False
128 utilities.assert_equals( expect=True, actual=logging,
129 onpass="Set log levels",
130 onfail="Failed to set log levels" )
131
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700132 def CASE2( self, main ):
133 """
134 Assign devices to controllers
135 """
Devin Lim58046fa2017-07-05 16:55:00 -0700136 main.HA.assignDevices( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700137
Jon Hallab611372018-02-21 15:26:05 -0800138 def CASE102( self, main ):
139 """
140 Set up Spine-Leaf fabric topology in Mininet
141 """
142 main.HA.startTopology( main )
143
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700144 def CASE21( self, main ):
145 """
146 Assign mastership to controllers
147 """
Devin Lim58046fa2017-07-05 16:55:00 -0700148 main.HA.assignMastership( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700149
150 def CASE3( self, main ):
151 """
152 Assign intents
153 """
Devin Lim58046fa2017-07-05 16:55:00 -0700154 main.HA.assignIntents( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700155
156 def CASE4( self, main ):
157 """
158 Ping across added host intents
159 """
Jon Hallca319892017-06-15 15:25:22 -0700160 main.HA.pingAcrossHostIntent( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700161
Jon Hallab611372018-02-21 15:26:05 -0800162 def CASE104( self, main ):
163 """
164 Ping Hosts
165 """
166 main.case( "Check connectivity" )
167 main.step( "Ping between all hosts" )
168 pingResult = main.Mininet1.pingall()
169 utilities.assert_equals( expect=main.TRUE, actual=pingResult,
170 onpass="All Pings Passed",
171 onfail="Failed to ping between all hosts" )
172
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700173 def CASE5( self, main ):
174 """
175 Reading state of ONOS
176 """
Devin Lim58046fa2017-07-05 16:55:00 -0700177 main.HA.readingState( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700178
179 def CASE6( self, main ):
180 """
181 The Scaling case.
182 """
183 import time
184 import re
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700185 assert main, "main not defined"
186 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700187 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700188 main.HAlabels
189 except ( NameError, AttributeError ):
190 main.log.error( "main.HAlabels not defined, setting to []" )
191 main.HAlabels = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700192 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700193 main.HAdata
194 except ( NameError, AttributeError ):
195 main.log.error( "main.HAdata not defined, setting to []" )
196 main.HAdata = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700197
Jon Hall69b2b982016-05-11 12:04:59 -0700198 main.case( "Scale the number of nodes in the ONOS cluster" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700199
200 main.step( "Checking ONOS Logs for errors" )
Devin Lim142b5342017-07-20 15:22:39 -0700201 for ctrl in main.Cluster.active():
202 main.log.debug( "Checking logs for errors on " + ctrl.name + ":" )
203 main.log.warn( main.ONOSbench.checkLogs( ctrl.ipAddress ) )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700204
205 """
206 pop # of nodes from a list, might look like 1,3b,3,5b,5,7b,7,7b,5,5b,3...
207 modify cluster.json file appropriately
208 install/deactivate node as needed
209 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700210 try:
Devin Lim142b5342017-07-20 15:22:39 -0700211 prevNodes = main.Cluster.active()
Jon Hallf37d44d2017-05-24 10:37:30 -0700212 scale = main.scaling.pop( 0 )
Jon Hallab611372018-02-21 15:26:05 -0800213 if "b" in scale:
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700214 equal = True
215 else:
216 equal = False
Devin Lim142b5342017-07-20 15:22:39 -0700217 main.Cluster.setRunningNode( int( re.search( "\d+", scale ).group( 0 ) ) )
Jon Hallab611372018-02-21 15:26:05 -0800218 main.step( "Scaling to {} nodes; Equal partitions: {}".format( main.Cluster.numCtrls, equal ) )
Devin Lim142b5342017-07-20 15:22:39 -0700219 genResult = main.Server.generateFile( main.Cluster.numCtrls, equal=equal )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700220 utilities.assert_equals( expect=main.TRUE, actual=genResult,
221 onpass="New cluster metadata file generated",
222 onfail="Failled to generate new metadata file" )
223 time.sleep( 5 ) # Give time for nodes to read new file
224 except IndexError:
Devin Lim44075962017-08-11 10:56:37 -0700225 main.cleanAndExit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700226
Jon Hallab611372018-02-21 15:26:05 -0800227 activeNodes = range( 0, main.Cluster.numCtrls )
Devin Lim142b5342017-07-20 15:22:39 -0700228 newNodes = [ x for x in activeNodes if x not in prevNodes ]
229 main.Cluster.resetActive()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700230 main.step( "Start new nodes" ) # OR stop old nodes?
231 started = main.TRUE
232 for i in newNodes:
Devin Lim142b5342017-07-20 15:22:39 -0700233 started = main.ONOSbench.onosStart( main.Cluster.runningNodes[ i ].ipAddress ) and main.TRUE
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700234 utilities.assert_equals( expect=main.TRUE, actual=started,
235 onpass="ONOS started",
236 onfail="ONOS start NOT successful" )
237
Devin Lim142b5342017-07-20 15:22:39 -0700238 main.testSetUp.setupSsh( main.Cluster )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700239
Devin Lim142b5342017-07-20 15:22:39 -0700240 main.testSetUp.checkOnosService( main.Cluster )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700241
Devin Lim142b5342017-07-20 15:22:39 -0700242 main.Cluster.startCLIs()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700243
244 main.step( "Checking ONOS nodes" )
Devin Lim3ebd5e72017-11-14 10:38:00 -0800245 nodeResults = utilities.retry( main.Cluster.nodesCheck,
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700246 False,
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700247 attempts=5 )
248 utilities.assert_equals( expect=True, actual=nodeResults,
249 onpass="Nodes check successful",
250 onfail="Nodes check NOT successful" )
251
252 for i in range( 10 ):
253 ready = True
Devin Lim142b5342017-07-20 15:22:39 -0700254 for ctrl in main.Cluster.active():
255 output = ctrl.CLI.summary()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700256 if not output:
257 ready = False
258 if ready:
259 break
260 time.sleep( 30 )
261 utilities.assert_equals( expect=True, actual=ready,
262 onpass="ONOS summary command succeded",
263 onfail="ONOS summary command failed" )
264 if not ready:
Devin Lim44075962017-08-11 10:56:37 -0700265 main.cleanAndExit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700266
267 # Rerun for election on new nodes
268 runResults = main.TRUE
Devin Lim142b5342017-07-20 15:22:39 -0700269 for ctrl in main.Cluster.active():
270 run = ctrl.CLI.electionTestRun()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700271 if run != main.TRUE:
Devin Lim142b5342017-07-20 15:22:39 -0700272 main.log.error( "Error running for election on " + ctrl.name )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700273 runResults = runResults and run
274 utilities.assert_equals( expect=main.TRUE, actual=runResults,
275 onpass="Reran for election",
276 onfail="Failed to rerun for election" )
277
278 # TODO: Make this configurable
279 time.sleep( 60 )
Devin Lim142b5342017-07-20 15:22:39 -0700280 main.HA.commonChecks()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700281
282 def CASE7( self, main ):
283 """
284 Check state after ONOS scaling
285 """
Devin Lim142b5342017-07-20 15:22:39 -0700286 main.HA.checkStateAfterEvent( main, afterWhich=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700287
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700288 main.step( "Leadership Election is still functional" )
289 # Test of LeadershipElection
290 leaderList = []
291 leaderResult = main.TRUE
292
Devin Lim142b5342017-07-20 15:22:39 -0700293 for ctrl in main.Cluster.active():
294 leaderN = ctrl.CLI.electionTestLeader()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700295 leaderList.append( leaderN )
296 if leaderN == main.FALSE:
297 # error in response
298 main.log.error( "Something is wrong with " +
299 "electionTestLeader function, check the" +
300 " error logs" )
301 leaderResult = main.FALSE
302 elif leaderN is None:
Jon Halla478b852017-12-04 15:00:15 -0800303 main.log.error( ctrl.name +
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700304 " shows no leader for the election-app." )
305 leaderResult = main.FALSE
306 if len( set( leaderList ) ) != 1:
307 leaderResult = main.FALSE
308 main.log.error(
309 "Inconsistent view of leader for the election test app" )
Jon Hallab611372018-02-21 15:26:05 -0800310 main.log.debug( leaderList )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700311 utilities.assert_equals(
312 expect=main.TRUE,
313 actual=leaderResult,
314 onpass="Leadership election passed",
315 onfail="Something went wrong with Leadership election" )
316
317 def CASE8( self, main ):
318 """
319 Compare topo
320 """
Devin Lim58046fa2017-07-05 16:55:00 -0700321 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700322
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700323 def CASE9( self, main ):
324 """
Jon Hallab611372018-02-21 15:26:05 -0800325 Link down
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700326 """
Jon Hallab611372018-02-21 15:26:05 -0800327 src = main.params['kill']['linkSrc']
328 dst = main.params['kill']['linkDst']
329 main.HA.linkDown( main, src, dst )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700330
331 def CASE10( self, main ):
332 """
Jon Hallab611372018-02-21 15:26:05 -0800333 Link up
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700334 """
Jon Hallab611372018-02-21 15:26:05 -0800335 src = main.params['kill']['linkSrc']
336 dst = main.params['kill']['linkDst']
337 main.HA.linkUp( main, src, dst )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700338
339 def CASE11( self, main ):
340 """
341 Switch Down
342 """
343 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700344 main.HA.switchDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700345
346 def CASE12( self, main ):
347 """
348 Switch Up
349 """
350 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700351 main.HA.switchUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700352
353 def CASE13( self, main ):
354 """
355 Clean up
356 """
Devin Lim58046fa2017-07-05 16:55:00 -0700357 main.HA.cleanUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700358
359 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700360 status = main.Server.stop()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700361 utilities.assert_equals( expect=main.TRUE, actual=status,
362 onpass="Stop Server",
363 onfail="Failled to stop SimpleHTTPServer" )
364 del main.Server
365
366 def CASE14( self, main ):
367 """
Jon Hallab611372018-02-21 15:26:05 -0800368 Start election app on all onos nodes
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700369 """
Devin Lim58046fa2017-07-05 16:55:00 -0700370 main.HA.startElectionApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700371
372 def CASE15( self, main ):
373 """
374 Check that Leadership Election is still functional
375 15.1 Run election on each node
376 15.2 Check that each node has the same leaders and candidates
377 15.3 Find current leader and withdraw
378 15.4 Check that a new node was elected leader
379 15.5 Check that that new leader was the candidate of old leader
380 15.6 Run for election on old leader
381 15.7 Check that oldLeader is a candidate, and leader if only 1 node
382 15.8 Make sure that the old leader was added to the candidate list
383
384 old and new variable prefixes refer to data from before vs after
385 withdrawl and later before withdrawl vs after re-election
386 """
Devin Lim58046fa2017-07-05 16:55:00 -0700387 main.HA.isElectionFunctional( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700388
389 def CASE16( self, main ):
390 """
391 Install Distributed Primitives app
392 """
Devin Lim58046fa2017-07-05 16:55:00 -0700393 main.HA.installDistributedPrimitiveApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700394
395 def CASE17( self, main ):
396 """
397 Check for basic functionality with distributed primitives
398 """
Devin Lim58046fa2017-07-05 16:55:00 -0700399 main.HA.checkDistPrimitivesFunc( main )