blob: d4b7b32a8a5ac53c7cfce818331047a217e4f934 [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 """
68 import time
69 import os
70 import re
71 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
72 "initialization" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070073 # set global variables
74 # These are for csv plotting in jenkins
Devin Lim58046fa2017-07-05 16:55:00 -070075 main.HAlabels = []
76 main.HAdata = []
77 try:
78 from tests.dependencies.ONOSSetup import ONOSSetup
79 main.testSetUp = ONOSSetup()
80 except ImportError:
Jon Hall4f360bc2017-09-07 10:19:52 -070081 main.log.error( "ONOSSetup not found. exiting the test" )
Devin Lim44075962017-08-11 10:56:37 -070082 main.cleanAndExit()
Devin Lim58046fa2017-07-05 16:55:00 -070083 main.testSetUp.envSetupDescription()
Jon Hall9ebd1bd2016-04-19 01:37:17 -070084 try:
85 from tests.HA.dependencies.HA import HA
86 main.HA = HA()
Devin Lim58046fa2017-07-05 16:55:00 -070087 from tests.HA.HAswapNodes.dependencies.Server import Server
Jon Hall9ebd1bd2016-04-19 01:37:17 -070088 main.Server = Server()
Devin Lim58046fa2017-07-05 16:55:00 -070089
90 # load some variables from the params file
91 cellName = main.params[ 'ENV' ][ 'cellName' ]
92 main.apps = main.params[ 'ENV' ][ 'appString' ]
Devin Lim142b5342017-07-20 15:22:39 -070093 stepResult = main.testSetUp.envSetup()
Jon Hall9ebd1bd2016-04-19 01:37:17 -070094 except Exception as e:
Devin Lim58046fa2017-07-05 16:55:00 -070095 main.testSetUp.envSetupException( e )
96 main.testSetUp.evnSetupConclusion( stepResult )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070097
Devin Lim142b5342017-07-20 15:22:39 -070098 main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster, cellName=cellName, removeLog=True,
Jon Hall4f360bc2017-09-07 10:19:52 -070099 extraApply=[ main.HA.setServerForCluster,
100 main.HA.scalingMetadata,
101 main.HA.startingMininet,
102 main.HA.copyBackupConfig,
103 main.HA.setMetadataUrl ],
104 extraClean=main.HA.cleanUpOnosService,
105 installMax=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700106
Jon Hall4f360bc2017-09-07 10:19:52 -0700107 main.HA.initialSetUp( serviceClean=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700108
109 def CASE2( self, main ):
110 """
111 Assign devices to controllers
112 """
Devin Lim58046fa2017-07-05 16:55:00 -0700113 main.HA.assignDevices( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700114
115 def CASE21( self, main ):
116 """
117 Assign mastership to controllers
118 """
Devin Lim58046fa2017-07-05 16:55:00 -0700119 main.HA.assignMastership( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700120
121 def CASE3( self, main ):
122 """
123 Assign intents
124 """
Devin Lim58046fa2017-07-05 16:55:00 -0700125 main.HA.assignIntents( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700126
127 def CASE4( self, main ):
128 """
129 Ping across added host intents
130 """
Jon Hallca319892017-06-15 15:25:22 -0700131 main.HA.pingAcrossHostIntent( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700132
133 def CASE5( self, main ):
134 """
135 Reading state of ONOS
136 """
Devin Lim58046fa2017-07-05 16:55:00 -0700137 main.HA.readingState( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700138
139 def CASE6( self, main ):
140 """
141 The Scaling case.
142 """
143 import time
144 import re
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700145 assert main, "main not defined"
146 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700147 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700148 main.HAlabels
149 except ( NameError, AttributeError ):
150 main.log.error( "main.HAlabels not defined, setting to []" )
151 main.HAlabels = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700152 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700153 main.HAdata
154 except ( NameError, AttributeError ):
155 main.log.error( "main.HAdata not defined, setting to []" )
156 main.HAdata = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700157
Jon Hall69b2b982016-05-11 12:04:59 -0700158 main.case( "Scale the number of nodes in the ONOS cluster" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700159
160 main.step( "Checking ONOS Logs for errors" )
Devin Lim142b5342017-07-20 15:22:39 -0700161 for ctrl in main.Cluster.active():
162 main.log.debug( "Checking logs for errors on " + ctrl.name + ":" )
163 main.log.warn( main.ONOSbench.checkLogs( ctrl.ipAddress ) )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700164
165 """
166 pop # of nodes from a list, might look like 1,3b,3,5b,5,7b,7,7b,5,5b,3...
167 modify cluster.json file appropriately
168 install/deactivate node as needed
169 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700170 try:
Devin Lim142b5342017-07-20 15:22:39 -0700171 prevNodes = main.Cluster.active()
Jon Hallf37d44d2017-05-24 10:37:30 -0700172 scale = main.scaling.pop( 0 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700173 if "e" in scale:
174 equal = True
175 else:
176 equal = False
Devin Lim142b5342017-07-20 15:22:39 -0700177 main.Cluster.setRunningNode( int( re.search( "\d+", scale ).group( 0 ) ) )
178 main.log.info( "Scaling to {} nodes".format( main.Cluster.numCtrls ) )
179 genResult = main.Server.generateFile( main.Cluster.numCtrls, equal=equal )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700180 utilities.assert_equals( expect=main.TRUE, actual=genResult,
181 onpass="New cluster metadata file generated",
182 onfail="Failled to generate new metadata file" )
183 time.sleep( 5 ) # Give time for nodes to read new file
184 except IndexError:
Devin Lim44075962017-08-11 10:56:37 -0700185 main.cleanAndExit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700186
Devin Lim142b5342017-07-20 15:22:39 -0700187 activeNodes = [ i for i in range( 0, main.Cluster.numCtrls ) ]
188 newNodes = [ x for x in activeNodes if x not in prevNodes ]
189 main.Cluster.resetActive()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700190 main.step( "Start new nodes" ) # OR stop old nodes?
191 started = main.TRUE
192 for i in newNodes:
Devin Lim142b5342017-07-20 15:22:39 -0700193 started = main.ONOSbench.onosStart( main.Cluster.runningNodes[ i ].ipAddress ) and main.TRUE
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700194 utilities.assert_equals( expect=main.TRUE, actual=started,
195 onpass="ONOS started",
196 onfail="ONOS start NOT successful" )
197
Devin Lim142b5342017-07-20 15:22:39 -0700198 main.testSetUp.setupSsh( main.Cluster )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700199
Devin Lim142b5342017-07-20 15:22:39 -0700200 main.testSetUp.checkOnosService( main.Cluster )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700201
Devin Lim142b5342017-07-20 15:22:39 -0700202 main.Cluster.startCLIs()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700203
204 main.step( "Checking ONOS nodes" )
Devin Lim3ebd5e72017-11-14 10:38:00 -0800205 nodeResults = utilities.retry( main.Cluster.nodesCheck,
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700206 False,
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700207 attempts=5 )
208 utilities.assert_equals( expect=True, actual=nodeResults,
209 onpass="Nodes check successful",
210 onfail="Nodes check NOT successful" )
211
212 for i in range( 10 ):
213 ready = True
Devin Lim142b5342017-07-20 15:22:39 -0700214 for ctrl in main.Cluster.active():
215 output = ctrl.CLI.summary()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700216 if not output:
217 ready = False
218 if ready:
219 break
220 time.sleep( 30 )
221 utilities.assert_equals( expect=True, actual=ready,
222 onpass="ONOS summary command succeded",
223 onfail="ONOS summary command failed" )
224 if not ready:
Devin Lim44075962017-08-11 10:56:37 -0700225 main.cleanAndExit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700226
227 # Rerun for election on new nodes
228 runResults = main.TRUE
Devin Lim142b5342017-07-20 15:22:39 -0700229 for ctrl in main.Cluster.active():
230 run = ctrl.CLI.electionTestRun()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700231 if run != main.TRUE:
Devin Lim142b5342017-07-20 15:22:39 -0700232 main.log.error( "Error running for election on " + ctrl.name )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700233 runResults = runResults and run
234 utilities.assert_equals( expect=main.TRUE, actual=runResults,
235 onpass="Reran for election",
236 onfail="Failed to rerun for election" )
237
238 # TODO: Make this configurable
239 time.sleep( 60 )
Devin Lim142b5342017-07-20 15:22:39 -0700240 main.HA.commonChecks()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700241
242 def CASE7( self, main ):
243 """
244 Check state after ONOS scaling
245 """
Devin Lim142b5342017-07-20 15:22:39 -0700246 main.HA.checkStateAfterEvent( main, afterWhich=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700247
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700248 main.step( "Leadership Election is still functional" )
249 # Test of LeadershipElection
250 leaderList = []
251 leaderResult = main.TRUE
252
Devin Lim142b5342017-07-20 15:22:39 -0700253 for ctrl in main.Cluster.active():
254 leaderN = ctrl.CLI.electionTestLeader()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700255 leaderList.append( leaderN )
256 if leaderN == main.FALSE:
257 # error in response
258 main.log.error( "Something is wrong with " +
259 "electionTestLeader function, check the" +
260 " error logs" )
261 leaderResult = main.FALSE
262 elif leaderN is None:
263 main.log.error( cli.name +
264 " shows no leader for the election-app." )
265 leaderResult = main.FALSE
266 if len( set( leaderList ) ) != 1:
267 leaderResult = main.FALSE
268 main.log.error(
269 "Inconsistent view of leader for the election test app" )
270 # TODO: print the list
271 utilities.assert_equals(
272 expect=main.TRUE,
273 actual=leaderResult,
274 onpass="Leadership election passed",
275 onfail="Something went wrong with Leadership election" )
276
277 def CASE8( self, main ):
278 """
279 Compare topo
280 """
Devin Lim58046fa2017-07-05 16:55:00 -0700281 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700282
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700283 def CASE9( self, main ):
284 """
285 Link s3-s28 down
286 """
Devin Lim58046fa2017-07-05 16:55:00 -0700287 main.HA.linkDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700288
289 def CASE10( self, main ):
290 """
291 Link s3-s28 up
292 """
Devin Lim58046fa2017-07-05 16:55:00 -0700293 main.HA.linkUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700294
295 def CASE11( self, main ):
296 """
297 Switch Down
298 """
299 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700300 main.HA.switchDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700301
302 def CASE12( self, main ):
303 """
304 Switch Up
305 """
306 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700307 main.HA.switchUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700308
309 def CASE13( self, main ):
310 """
311 Clean up
312 """
Devin Lim58046fa2017-07-05 16:55:00 -0700313 main.HA.cleanUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700314
315 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700316 status = main.Server.stop()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700317 utilities.assert_equals( expect=main.TRUE, actual=status,
318 onpass="Stop Server",
319 onfail="Failled to stop SimpleHTTPServer" )
320 del main.Server
321
322 def CASE14( self, main ):
323 """
324 start election app on all onos nodes
325 """
Devin Lim58046fa2017-07-05 16:55:00 -0700326 main.HA.startElectionApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700327
328 def CASE15( self, main ):
329 """
330 Check that Leadership Election is still functional
331 15.1 Run election on each node
332 15.2 Check that each node has the same leaders and candidates
333 15.3 Find current leader and withdraw
334 15.4 Check that a new node was elected leader
335 15.5 Check that that new leader was the candidate of old leader
336 15.6 Run for election on old leader
337 15.7 Check that oldLeader is a candidate, and leader if only 1 node
338 15.8 Make sure that the old leader was added to the candidate list
339
340 old and new variable prefixes refer to data from before vs after
341 withdrawl and later before withdrawl vs after re-election
342 """
Devin Lim58046fa2017-07-05 16:55:00 -0700343 main.HA.isElectionFunctional( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700344
345 def CASE16( self, main ):
346 """
347 Install Distributed Primitives app
348 """
Devin Lim58046fa2017-07-05 16:55:00 -0700349 main.HA.installDistributedPrimitiveApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700350
351 def CASE17( self, main ):
352 """
353 Check for basic functionality with distributed primitives
354 """
Devin Lim58046fa2017-07-05 16:55:00 -0700355 main.HA.checkDistPrimitivesFunc( main )