blob: 63aa1e5529b9806c740d92c0523ba457bca28688 [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 )
97 main.HA.generateGraph( "HAscaling", index=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -070098
Devin Lim142b5342017-07-20 15:22:39 -070099 main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster, cellName=cellName, removeLog=True,
Jon Hall4f360bc2017-09-07 10:19:52 -0700100 extraApply=[ main.HA.setServerForCluster,
101 main.HA.scalingMetadata,
102 main.HA.startingMininet,
103 main.HA.copyBackupConfig,
104 main.HA.setMetadataUrl ],
105 extraClean=main.HA.cleanUpOnosService,
106 installMax=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700107
Jon Hall4f360bc2017-09-07 10:19:52 -0700108 main.HA.initialSetUp( serviceClean=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700109
110 def CASE2( self, main ):
111 """
112 Assign devices to controllers
113 """
Devin Lim58046fa2017-07-05 16:55:00 -0700114 main.HA.assignDevices( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700115
116 def CASE21( self, main ):
117 """
118 Assign mastership to controllers
119 """
Devin Lim58046fa2017-07-05 16:55:00 -0700120 main.HA.assignMastership( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700121
122 def CASE3( self, main ):
123 """
124 Assign intents
125 """
Devin Lim58046fa2017-07-05 16:55:00 -0700126 main.HA.assignIntents( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700127
128 def CASE4( self, main ):
129 """
130 Ping across added host intents
131 """
Jon Hallca319892017-06-15 15:25:22 -0700132 main.HA.pingAcrossHostIntent( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700133
134 def CASE5( self, main ):
135 """
136 Reading state of ONOS
137 """
Devin Lim58046fa2017-07-05 16:55:00 -0700138 main.HA.readingState( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700139
140 def CASE6( self, main ):
141 """
142 The Scaling case.
143 """
144 import time
145 import re
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700146 assert main, "main not defined"
147 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700148 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700149 main.HAlabels
150 except ( NameError, AttributeError ):
151 main.log.error( "main.HAlabels not defined, setting to []" )
152 main.HAlabels = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700153 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700154 main.HAdata
155 except ( NameError, AttributeError ):
156 main.log.error( "main.HAdata not defined, setting to []" )
157 main.HAdata = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700158
Jon Hall69b2b982016-05-11 12:04:59 -0700159 main.case( "Scale the number of nodes in the ONOS cluster" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700160
161 main.step( "Checking ONOS Logs for errors" )
Devin Lim142b5342017-07-20 15:22:39 -0700162 for ctrl in main.Cluster.active():
163 main.log.debug( "Checking logs for errors on " + ctrl.name + ":" )
164 main.log.warn( main.ONOSbench.checkLogs( ctrl.ipAddress ) )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700165
166 """
167 pop # of nodes from a list, might look like 1,3b,3,5b,5,7b,7,7b,5,5b,3...
168 modify cluster.json file appropriately
169 install/deactivate node as needed
170 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700171 try:
Devin Lim142b5342017-07-20 15:22:39 -0700172 prevNodes = main.Cluster.active()
Jon Hallf37d44d2017-05-24 10:37:30 -0700173 scale = main.scaling.pop( 0 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700174 if "e" in scale:
175 equal = True
176 else:
177 equal = False
Devin Lim142b5342017-07-20 15:22:39 -0700178 main.Cluster.setRunningNode( int( re.search( "\d+", scale ).group( 0 ) ) )
179 main.log.info( "Scaling to {} nodes".format( main.Cluster.numCtrls ) )
180 genResult = main.Server.generateFile( main.Cluster.numCtrls, equal=equal )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700181 utilities.assert_equals( expect=main.TRUE, actual=genResult,
182 onpass="New cluster metadata file generated",
183 onfail="Failled to generate new metadata file" )
184 time.sleep( 5 ) # Give time for nodes to read new file
185 except IndexError:
Devin Lim44075962017-08-11 10:56:37 -0700186 main.cleanAndExit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700187
Devin Lim142b5342017-07-20 15:22:39 -0700188 activeNodes = [ i for i in range( 0, main.Cluster.numCtrls ) ]
189 newNodes = [ x for x in activeNodes if x not in prevNodes ]
190 main.Cluster.resetActive()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700191 main.step( "Start new nodes" ) # OR stop old nodes?
192 started = main.TRUE
193 for i in newNodes:
Devin Lim142b5342017-07-20 15:22:39 -0700194 started = main.ONOSbench.onosStart( main.Cluster.runningNodes[ i ].ipAddress ) and main.TRUE
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700195 utilities.assert_equals( expect=main.TRUE, actual=started,
196 onpass="ONOS started",
197 onfail="ONOS start NOT successful" )
198
Devin Lim142b5342017-07-20 15:22:39 -0700199 main.testSetUp.setupSsh( main.Cluster )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700200
Devin Lim142b5342017-07-20 15:22:39 -0700201 main.testSetUp.checkOnosService( main.Cluster )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700202
Devin Lim142b5342017-07-20 15:22:39 -0700203 main.Cluster.startCLIs()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700204
205 main.step( "Checking ONOS nodes" )
206 nodeResults = utilities.retry( main.HA.nodesCheck,
207 False,
Devin Lim142b5342017-07-20 15:22:39 -0700208 args=[ main.Cluster.active() ],
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700209 attempts=5 )
210 utilities.assert_equals( expect=True, actual=nodeResults,
211 onpass="Nodes check successful",
212 onfail="Nodes check NOT successful" )
213
214 for i in range( 10 ):
215 ready = True
Devin Lim142b5342017-07-20 15:22:39 -0700216 for ctrl in main.Cluster.active():
217 output = ctrl.CLI.summary()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700218 if not output:
219 ready = False
220 if ready:
221 break
222 time.sleep( 30 )
223 utilities.assert_equals( expect=True, actual=ready,
224 onpass="ONOS summary command succeded",
225 onfail="ONOS summary command failed" )
226 if not ready:
Devin Lim44075962017-08-11 10:56:37 -0700227 main.cleanAndExit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700228
229 # Rerun for election on new nodes
230 runResults = main.TRUE
Devin Lim142b5342017-07-20 15:22:39 -0700231 for ctrl in main.Cluster.active():
232 run = ctrl.CLI.electionTestRun()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700233 if run != main.TRUE:
Devin Lim142b5342017-07-20 15:22:39 -0700234 main.log.error( "Error running for election on " + ctrl.name )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700235 runResults = runResults and run
236 utilities.assert_equals( expect=main.TRUE, actual=runResults,
237 onpass="Reran for election",
238 onfail="Failed to rerun for election" )
239
240 # TODO: Make this configurable
241 time.sleep( 60 )
Devin Lim142b5342017-07-20 15:22:39 -0700242 main.HA.commonChecks()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700243
244 def CASE7( self, main ):
245 """
246 Check state after ONOS scaling
247 """
Devin Lim142b5342017-07-20 15:22:39 -0700248 main.HA.checkStateAfterEvent( main, afterWhich=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700249
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700250 main.step( "Leadership Election is still functional" )
251 # Test of LeadershipElection
252 leaderList = []
253 leaderResult = main.TRUE
254
Devin Lim142b5342017-07-20 15:22:39 -0700255 for ctrl in main.Cluster.active():
256 leaderN = ctrl.CLI.electionTestLeader()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700257 leaderList.append( leaderN )
258 if leaderN == main.FALSE:
259 # error in response
260 main.log.error( "Something is wrong with " +
261 "electionTestLeader function, check the" +
262 " error logs" )
263 leaderResult = main.FALSE
264 elif leaderN is None:
265 main.log.error( cli.name +
266 " shows no leader for the election-app." )
267 leaderResult = main.FALSE
268 if len( set( leaderList ) ) != 1:
269 leaderResult = main.FALSE
270 main.log.error(
271 "Inconsistent view of leader for the election test app" )
272 # TODO: print the list
273 utilities.assert_equals(
274 expect=main.TRUE,
275 actual=leaderResult,
276 onpass="Leadership election passed",
277 onfail="Something went wrong with Leadership election" )
278
279 def CASE8( self, main ):
280 """
281 Compare topo
282 """
Devin Lim58046fa2017-07-05 16:55:00 -0700283 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700284
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700285 def CASE9( self, main ):
286 """
287 Link s3-s28 down
288 """
Devin Lim58046fa2017-07-05 16:55:00 -0700289 main.HA.linkDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700290
291 def CASE10( self, main ):
292 """
293 Link s3-s28 up
294 """
Devin Lim58046fa2017-07-05 16:55:00 -0700295 main.HA.linkUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700296
297 def CASE11( self, main ):
298 """
299 Switch Down
300 """
301 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700302 main.HA.switchDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700303
304 def CASE12( self, main ):
305 """
306 Switch Up
307 """
308 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700309 main.HA.switchUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700310
311 def CASE13( self, main ):
312 """
313 Clean up
314 """
Devin Lim58046fa2017-07-05 16:55:00 -0700315 main.HA.cleanUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700316
317 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700318 status = main.Server.stop()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700319 utilities.assert_equals( expect=main.TRUE, actual=status,
320 onpass="Stop Server",
321 onfail="Failled to stop SimpleHTTPServer" )
322 del main.Server
323
324 def CASE14( self, main ):
325 """
326 start election app on all onos nodes
327 """
Devin Lim58046fa2017-07-05 16:55:00 -0700328 main.HA.startElectionApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700329
330 def CASE15( self, main ):
331 """
332 Check that Leadership Election is still functional
333 15.1 Run election on each node
334 15.2 Check that each node has the same leaders and candidates
335 15.3 Find current leader and withdraw
336 15.4 Check that a new node was elected leader
337 15.5 Check that that new leader was the candidate of old leader
338 15.6 Run for election on old leader
339 15.7 Check that oldLeader is a candidate, and leader if only 1 node
340 15.8 Make sure that the old leader was added to the candidate list
341
342 old and new variable prefixes refer to data from before vs after
343 withdrawl and later before withdrawl vs after re-election
344 """
Devin Lim58046fa2017-07-05 16:55:00 -0700345 main.HA.isElectionFunctional( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700346
347 def CASE16( self, main ):
348 """
349 Install Distributed Primitives app
350 """
Devin Lim58046fa2017-07-05 16:55:00 -0700351 main.HA.installDistributedPrimitiveApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700352
353 def CASE17( self, main ):
354 """
355 Check for basic functionality with distributed primitives
356 """
Devin Lim58046fa2017-07-05 16:55:00 -0700357 main.HA.checkDistPrimitivesFunc( main )