blob: cecd09e4b0897ac255a9795fc9b9e01f5bb61d94 [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" )
Devin Lim44075962017-08-11 10:56:37 -070083 main.cleanAndExit()
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' ]
Devin Lim142b5342017-07-20 15:22:39 -070095 stepResult = main.testSetUp.envSetup()
Jon Hall9ebd1bd2016-04-19 01:37:17 -070096 except Exception as e:
Devin Lim58046fa2017-07-05 16:55:00 -070097 main.testSetUp.envSetupException( e )
98 main.testSetUp.evnSetupConclusion( stepResult )
99 main.HA.generateGraph( "HAscaling", index=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700100
Devin Lim142b5342017-07-20 15:22:39 -0700101 main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster, cellName=cellName, removeLog=True,
102 extraApply=[ main.HA.setServerForCluster,
103 main.HA.scalingMetadata,
104 main.HA.startingMininet,
105 main.HA.copyingBackupConfig ],
Devin Lim58046fa2017-07-05 16:55:00 -0700106 extraClean=main.HA.cleanUpOnosService,
107 installMax=True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700108
Devin Lim58046fa2017-07-05 16:55:00 -0700109 main.HA.initialSetUp( True )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700110
111 def CASE2( self, main ):
112 """
113 Assign devices to controllers
114 """
Devin Lim58046fa2017-07-05 16:55:00 -0700115 main.HA.assignDevices( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700116
117 def CASE21( self, main ):
118 """
119 Assign mastership to controllers
120 """
Devin Lim58046fa2017-07-05 16:55:00 -0700121 main.HA.assignMastership( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700122
123 def CASE3( self, main ):
124 """
125 Assign intents
126 """
Devin Lim58046fa2017-07-05 16:55:00 -0700127 main.HA.assignIntents( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700128
129 def CASE4( self, main ):
130 """
131 Ping across added host intents
132 """
Jon Hallca319892017-06-15 15:25:22 -0700133 main.HA.pingAcrossHostIntent( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700134
135 def CASE5( self, main ):
136 """
137 Reading state of ONOS
138 """
Devin Lim58046fa2017-07-05 16:55:00 -0700139 main.HA.readingState( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700140
141 def CASE6( self, main ):
142 """
143 The Scaling case.
144 """
145 import time
146 import re
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700147 assert main, "main not defined"
148 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700149 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700150 main.HAlabels
151 except ( NameError, AttributeError ):
152 main.log.error( "main.HAlabels not defined, setting to []" )
153 main.HAlabels = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700154 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700155 main.HAdata
156 except ( NameError, AttributeError ):
157 main.log.error( "main.HAdata not defined, setting to []" )
158 main.HAdata = []
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700159
Jon Hall69b2b982016-05-11 12:04:59 -0700160 main.case( "Scale the number of nodes in the ONOS cluster" )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700161
162 main.step( "Checking ONOS Logs for errors" )
Devin Lim142b5342017-07-20 15:22:39 -0700163 for ctrl in main.Cluster.active():
164 main.log.debug( "Checking logs for errors on " + ctrl.name + ":" )
165 main.log.warn( main.ONOSbench.checkLogs( ctrl.ipAddress ) )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700166
167 """
168 pop # of nodes from a list, might look like 1,3b,3,5b,5,7b,7,7b,5,5b,3...
169 modify cluster.json file appropriately
170 install/deactivate node as needed
171 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700172 try:
Devin Lim142b5342017-07-20 15:22:39 -0700173 prevNodes = main.Cluster.active()
Jon Hallf37d44d2017-05-24 10:37:30 -0700174 scale = main.scaling.pop( 0 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700175 if "e" in scale:
176 equal = True
177 else:
178 equal = False
Devin Lim142b5342017-07-20 15:22:39 -0700179 main.Cluster.setRunningNode( int( re.search( "\d+", scale ).group( 0 ) ) )
180 main.log.info( "Scaling to {} nodes".format( main.Cluster.numCtrls ) )
181 genResult = main.Server.generateFile( main.Cluster.numCtrls, equal=equal )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700182 utilities.assert_equals( expect=main.TRUE, actual=genResult,
183 onpass="New cluster metadata file generated",
184 onfail="Failled to generate new metadata file" )
185 time.sleep( 5 ) # Give time for nodes to read new file
186 except IndexError:
Devin Lim44075962017-08-11 10:56:37 -0700187 main.cleanAndExit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700188
Devin Lim142b5342017-07-20 15:22:39 -0700189 activeNodes = [ i for i in range( 0, main.Cluster.numCtrls ) ]
190 newNodes = [ x for x in activeNodes if x not in prevNodes ]
191 main.Cluster.resetActive()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700192 main.step( "Start new nodes" ) # OR stop old nodes?
193 started = main.TRUE
194 for i in newNodes:
Devin Lim142b5342017-07-20 15:22:39 -0700195 started = main.ONOSbench.onosStart( main.Cluster.runningNodes[ i ].ipAddress ) and main.TRUE
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700196 utilities.assert_equals( expect=main.TRUE, actual=started,
197 onpass="ONOS started",
198 onfail="ONOS start NOT successful" )
199
Devin Lim142b5342017-07-20 15:22:39 -0700200 main.testSetUp.setupSsh( main.Cluster )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700201
Devin Lim142b5342017-07-20 15:22:39 -0700202 main.testSetUp.checkOnosService( main.Cluster )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700203
Devin Lim142b5342017-07-20 15:22:39 -0700204 main.Cluster.startCLIs()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700205
206 main.step( "Checking ONOS nodes" )
207 nodeResults = utilities.retry( main.HA.nodesCheck,
208 False,
Devin Lim142b5342017-07-20 15:22:39 -0700209 args=[ main.Cluster.active() ],
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700210 attempts=5 )
211 utilities.assert_equals( expect=True, actual=nodeResults,
212 onpass="Nodes check successful",
213 onfail="Nodes check NOT successful" )
214
215 for i in range( 10 ):
216 ready = True
Devin Lim142b5342017-07-20 15:22:39 -0700217 for ctrl in main.Cluster.active():
218 output = ctrl.CLI.summary()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700219 if not output:
220 ready = False
221 if ready:
222 break
223 time.sleep( 30 )
224 utilities.assert_equals( expect=True, actual=ready,
225 onpass="ONOS summary command succeded",
226 onfail="ONOS summary command failed" )
227 if not ready:
Devin Lim44075962017-08-11 10:56:37 -0700228 main.cleanAndExit()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700229
230 # Rerun for election on new nodes
231 runResults = main.TRUE
Devin Lim142b5342017-07-20 15:22:39 -0700232 for ctrl in main.Cluster.active():
233 run = ctrl.CLI.electionTestRun()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700234 if run != main.TRUE:
Devin Lim142b5342017-07-20 15:22:39 -0700235 main.log.error( "Error running for election on " + ctrl.name )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700236 runResults = runResults and run
237 utilities.assert_equals( expect=main.TRUE, actual=runResults,
238 onpass="Reran for election",
239 onfail="Failed to rerun for election" )
240
241 # TODO: Make this configurable
242 time.sleep( 60 )
Devin Lim142b5342017-07-20 15:22:39 -0700243 main.HA.commonChecks()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700244
245 def CASE7( self, main ):
246 """
247 Check state after ONOS scaling
248 """
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700249
Devin Lim142b5342017-07-20 15:22:39 -0700250 main.HA.checkStateAfterEvent( main, afterWhich=1 )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700251
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700252 main.step( "Leadership Election is still functional" )
253 # Test of LeadershipElection
254 leaderList = []
255 leaderResult = main.TRUE
256
Devin Lim142b5342017-07-20 15:22:39 -0700257 for ctrl in main.Cluster.active():
258 leaderN = ctrl.CLI.electionTestLeader()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700259 leaderList.append( leaderN )
260 if leaderN == main.FALSE:
261 # error in response
262 main.log.error( "Something is wrong with " +
263 "electionTestLeader function, check the" +
264 " error logs" )
265 leaderResult = main.FALSE
266 elif leaderN is None:
267 main.log.error( cli.name +
268 " shows no leader for the election-app." )
269 leaderResult = main.FALSE
270 if len( set( leaderList ) ) != 1:
271 leaderResult = main.FALSE
272 main.log.error(
273 "Inconsistent view of leader for the election test app" )
274 # TODO: print the list
275 utilities.assert_equals(
276 expect=main.TRUE,
277 actual=leaderResult,
278 onpass="Leadership election passed",
279 onfail="Something went wrong with Leadership election" )
280
281 def CASE8( self, main ):
282 """
283 Compare topo
284 """
Devin Lim58046fa2017-07-05 16:55:00 -0700285 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700286
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700287 def CASE9( self, main ):
288 """
289 Link s3-s28 down
290 """
Devin Lim58046fa2017-07-05 16:55:00 -0700291 main.HA.linkDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700292
293 def CASE10( self, main ):
294 """
295 Link s3-s28 up
296 """
Devin Lim58046fa2017-07-05 16:55:00 -0700297 main.HA.linkUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700298
299 def CASE11( self, main ):
300 """
301 Switch Down
302 """
303 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700304 main.HA.switchDown( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700305
306 def CASE12( self, main ):
307 """
308 Switch Up
309 """
310 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700311 main.HA.switchUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700312
313 def CASE13( self, main ):
314 """
315 Clean up
316 """
Devin Lim58046fa2017-07-05 16:55:00 -0700317 main.HA.cleanUp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700318
319 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700320 status = main.Server.stop()
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700321 utilities.assert_equals( expect=main.TRUE, actual=status,
322 onpass="Stop Server",
323 onfail="Failled to stop SimpleHTTPServer" )
324 del main.Server
325
326 def CASE14( self, main ):
327 """
328 start election app on all onos nodes
329 """
Devin Lim58046fa2017-07-05 16:55:00 -0700330 main.HA.startElectionApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700331
332 def CASE15( self, main ):
333 """
334 Check that Leadership Election is still functional
335 15.1 Run election on each node
336 15.2 Check that each node has the same leaders and candidates
337 15.3 Find current leader and withdraw
338 15.4 Check that a new node was elected leader
339 15.5 Check that that new leader was the candidate of old leader
340 15.6 Run for election on old leader
341 15.7 Check that oldLeader is a candidate, and leader if only 1 node
342 15.8 Make sure that the old leader was added to the candidate list
343
344 old and new variable prefixes refer to data from before vs after
345 withdrawl and later before withdrawl vs after re-election
346 """
Devin Lim58046fa2017-07-05 16:55:00 -0700347 main.HA.isElectionFunctional( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700348
349 def CASE16( self, main ):
350 """
351 Install Distributed Primitives app
352 """
Devin Lim58046fa2017-07-05 16:55:00 -0700353 main.HA.installDistributedPrimitiveApp( main )
Jon Hall9ebd1bd2016-04-19 01:37:17 -0700354
355 def CASE17( self, main ):
356 """
357 Check for basic functionality with distributed primitives
358 """
Devin Lim58046fa2017-07-05 16:55:00 -0700359 main.HA.checkDistPrimitivesFunc( main )