blob: 0f10515ff3f53c8919005a5f3ba45ea6674d7757 [file] [log] [blame]
Jon Halla478b852017-12-04 15:00:15 -08001"""
2Copyright 2015 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"""
23Description: This test is to determine if ONOS can handle
24 a minority of it's nodes restarting
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
Jon Hallab611372018-02-21 15:26:05 -080033CASE60: Initialize the upgrade.
34CASE61: Upgrade a minority of nodes PHASE 1
35CASE62: Transfer to new version. PHASE 2
36CASE63: Rollback the upgrade
37CASE64: Reset the upgrade state.
Jon Halla478b852017-12-04 15:00:15 -080038CASE7: Check state after control plane failure
39CASE8: Compare topo
40CASE9: Link s3-s28 down
41CASE10: Link s3-s28 up
42CASE11: Switch down
43CASE12: Switch up
44CASE13: Clean up
45CASE14: start election app on all onos nodes
46CASE15: Check that Leadership Election is still functional
47CASE16: Install Distributed Primitives app
48CASE17: Check for basic functionality with distributed primitives
49"""
50class HAupgradeRollback:
51
52 def __init__( self ):
53 self.default = ''
54
55 def CASE1( self, main ):
56 """
57 CASE1 is to compile ONOS and push it to the test machines
58
59 Startup sequence:
60 cell <name>
61 onos-verify-cell
62 NOTE: temporary - onos-remove-raft-logs
63 onos-uninstall
64 start mininet
65 git pull
66 mvn clean install
67 onos-package
68 onos-install -f
69 onos-wait-for-start
70 start cli sessions
71 start tcpdump
72 """
73 main.log.info( "ONOS HA test: Stop a minority of ONOS nodes - " +
74 "initialization" )
75 # These are for csv plotting in jenkins
76 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.cleanAndExit()
84 main.testSetUp.envSetupDescription()
85 try:
86 from tests.HA.dependencies.HA import HA
87 main.HA = HA()
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 Halla478b852017-12-04 15:00:15 -080091 except Exception as e:
92 main.testSetUp.envSetupException( e )
93 main.testSetUp.evnSetupConclusion( stepResult )
Jon Hallab611372018-02-21 15:26:05 -080094
Jon Hall5a5c8432018-11-28 11:39:57 -080095 applyFuncs = [ main.HA.removeKarafConsoleLogging, main.HA.copyBackupConfig ]
96 applyArgs = [ None, None ]
Jon Hallab611372018-02-21 15:26:05 -080097 try:
98 if main.params[ 'topology' ][ 'topoFile' ]:
99 main.log.info( 'Skipping start of Mininet in this case, make sure you start it elsewhere' )
100 else:
101 applyFuncs.append( main.HA.startingMininet )
102 applyArgs.append( None )
103 except (KeyError, IndexError):
104 applyFuncs.append( main.HA.startingMininet )
105 applyArgs.append( None )
Jon Halla478b852017-12-04 15:00:15 -0800106
Jon Hall3e6edb32018-08-21 16:20:30 -0700107 main.testSetUp.ONOSSetUp( main.Cluster, cellName=cellName,
Jon Hallab611372018-02-21 15:26:05 -0800108 extraApply=applyFuncs,
109 applyArgs=applyArgs,
110 extraClean=main.HA.cleanUpGenPartition,
111 includeCaseDesc=False )
Jon Halla478b852017-12-04 15:00:15 -0800112
113 main.HA.initialSetUp( serviceClean=True )
114
Jon Hallab611372018-02-21 15:26:05 -0800115 main.step( 'Set logging levels' )
116 logging = True
117 try:
118 logs = main.params.get( 'ONOS_Logging', False )
119 if logs:
120 for namespace, level in logs.items():
121 for ctrl in main.Cluster.active():
122 ctrl.CLI.logSet( level, namespace )
123 except AttributeError:
124 logging = False
125 utilities.assert_equals( expect=True, actual=logging,
126 onpass="Set log levels",
127 onfail="Failed to set log levels" )
128
Jon Halla478b852017-12-04 15:00:15 -0800129 def CASE2( self, main ):
130 """
131 Assign devices to controllers
132 """
133 main.HA.assignDevices( main )
134
Jon Hallab611372018-02-21 15:26:05 -0800135 def CASE102( self, main ):
136 """
137 Set up Spine-Leaf fabric topology in Mininet
138 """
139 main.HA.startTopology( main )
140
Jon Halla478b852017-12-04 15:00:15 -0800141 def CASE21( self, main ):
142 """
143 Assign mastership to controllers
144 """
145 main.HA.assignMastership( main )
146
147 def CASE3( self, main ):
148 """
149 Assign intents
150 """
151 main.HA.assignIntents( main )
152
153 def CASE4( self, main ):
154 """
155 Ping across added host intents
156 """
157 main.HA.pingAcrossHostIntent( main )
158
Jon Hallab611372018-02-21 15:26:05 -0800159 def CASE104( self, main ):
160 """
161 Ping Hosts
162 """
163 main.case( "Check connectivity" )
164 main.step( "Ping between all hosts" )
165 pingResult = main.Mininet1.pingall()
166 utilities.assert_equals( expect=main.TRUE, actual=pingResult,
167 onpass="All Pings Passed",
168 onfail="Failed to ping between all hosts" )
169
Jon Halla478b852017-12-04 15:00:15 -0800170 def CASE5( self, main ):
171 """
172 Reading state of ONOS
173 """
174 main.HA.readingState( main )
175
176 def CASE60( self, main ):
177 """
178 Initialize the upgrade.
179 """
180 assert main, "main not defined"
181 assert utilities.assert_equals, "utilities.assert_equals not defined"
182 main.case( "Initialize upgrade" )
183 main.HA.upgradeInit( main )
184
185 def CASE61( self, main ):
186 """
187 Upgrade a minority of nodes PHASE 1
188 """
189 assert main, "main not defined"
190 assert utilities.assert_equals, "utilities.assert_equals not defined"
191 main.case( "Upgrade minority of ONOS nodes" )
192
193 main.step( "Checking ONOS Logs for errors" )
194 for ctrl in main.Cluster.active():
195 main.log.debug( "Checking logs for errors on " + ctrl.name + ":" )
196 main.log.warn( ctrl.checkLogs( ctrl.ipAddress ) )
197
198 main.kill = []
199 n = len( main.Cluster.runningNodes ) # Number of nodes
200 p = n / 2 # Number of nodes in the minority
201 for i in range( p ):
202 main.kill.append( main.Cluster.runningNodes[ i ] ) # ONOS node to kill, listed by index in main.nodes
203 main.HA.upgradeNodes( main )
204
Jon Hall30668ff2019-02-27 17:43:09 -0800205 main.testSetUp.checkOnosNodes( main.Cluster )
Jon Halla478b852017-12-04 15:00:15 -0800206
207 def CASE62( self, main ):
208 """
209 Transfer to new version. PHASE 2
210 """
211 assert main, "main not defined"
212 assert utilities.assert_equals, "utilities.assert_equals not defined"
213 main.case( "Start the upgrade" )
214
215 main.step( "Send the command to switch to new version" )
216 ctrl = main.Cluster.next().CLI
217 upgraded = ctrl.issuUpgrade()
218 utilities.assert_equals( expect=main.TRUE, actual=upgraded,
219 onpass="Cluster has moved to the upgraded nodes",
220 onfail="Error transitioning to the upgraded nodes" )
221
222 main.step( "Check the status of the upgrade" )
223 ctrl = main.Cluster.next().CLI
224 status = ctrl.issu()
225 main.log.debug( status )
226 # TODO: check things here?
227
Jon Hall30668ff2019-02-27 17:43:09 -0800228 main.testSetUp.checkOnosNodes( main.Cluster )
Jon Halla478b852017-12-04 15:00:15 -0800229
230 def CASE63( self, main ):
231 """
232 Rollback the upgrade
233 """
234 main.case( "Rollback the upgrade" )
235 main.step( "Rollbak the upgrade" )
236 # send rollback command
237 ctrl = main.Cluster.next().CLI
238 rollback = ctrl.issuRollback()
239 utilities.assert_equals( expect=main.TRUE, actual=rollback,
240 onpass="Upgrade has been rolled back",
241 onfail="Error rolling back the upgrade" )
242
243 main.step( "Check the status of the upgrade" )
244 ctrl = main.Cluster.next().CLI
245 status = ctrl.issu()
246 main.log.debug( status )
247
248 # restart and reinstall old version on upgrade nodes
249 for ctrl in main.kill:
250 ctrl.onosStop( ctrl.ipAddress )
251 ctrl.onosUninstall( ctrl.ipAddress )
252 ctrl.onosInstall( options="-f", node=ctrl.ipAddress )
253 ctrl.onosSecureSSH( node=ctrl.ipAddress )
254 ctrl.startOnosCli( ctrl.ipAddress, waitForStart=True )
Jon Hall30668ff2019-02-27 17:43:09 -0800255 main.testSetUp.checkOnosNodes( main.Cluster )
Jon Halla478b852017-12-04 15:00:15 -0800256
257 def CASE64( self, main ):
258 """
259 Reset the upgrade state.
260 """
261 assert main, "main not defined"
262 assert utilities.assert_equals, "utilities.assert_equals not defined"
263 main.case( "Reset the upgrade state" )
264
265 main.step( "Send the command to reset the upgrade" )
266 ctrl = main.Cluster.next().CLI
267 committed = ctrl.issuCommit()
268 utilities.assert_equals( expect=main.TRUE, actual=committed,
269 onpass="Upgrade has been committed",
270 onfail="Error committing the upgrade" )
271
272 main.step( "Check the status of the upgrade" )
273 ctrl = main.Cluster.next().CLI
274 status = ctrl.issu()
275 main.log.debug( status )
276 # TODO: check things here?
277
278 def CASE7( self, main ):
279 """
280 Check state after ONOS failure
281 """
282 try:
283 main.kill
284 except AttributeError:
285 main.kill = []
286
287 main.HA.checkStateAfterEvent( main, afterWhich=0 )
288 main.step( "Leadership Election is still functional" )
289 # Test of LeadershipElection
290 leaderList = []
291
292 restarted = []
293 for ctrl in main.kill:
294 restarted.append( ctrl.ipAddress )
295 leaderResult = main.TRUE
296
297 for ctrl in main.Cluster.active():
298 leaderN = ctrl.electionTestLeader()
299 leaderList.append( leaderN )
300 if leaderN == main.FALSE:
301 # error in response
302 main.log.error( "Something is wrong with " +
303 "electionTestLeader function, check the" +
304 " error logs" )
305 leaderResult = main.FALSE
306 elif leaderN is None:
307 main.log.error( ctrl.name +
308 " shows no leader for the election-app was" +
309 " elected after the old one died" )
310 leaderResult = main.FALSE
311 elif leaderN in restarted:
312 main.log.error( ctrl.name + " shows " + str( leaderN ) +
313 " as leader for the election-app, but it " +
314 "was restarted" )
315 leaderResult = main.FALSE
316 if len( set( leaderList ) ) != 1:
317 leaderResult = main.FALSE
318 main.log.error(
319 "Inconsistent view of leader for the election test app" )
Jon Hallab611372018-02-21 15:26:05 -0800320 main.log.debug( leaderList )
Jon Halla478b852017-12-04 15:00:15 -0800321 utilities.assert_equals(
322 expect=main.TRUE,
323 actual=leaderResult,
324 onpass="Leadership election passed",
325 onfail="Something went wrong with Leadership election" )
326
327 def CASE8( self, main ):
328 """
329 Compare topo
330 """
331 main.HA.compareTopo( main )
332
333 def CASE9( self, main ):
334 """
Jon Hallab611372018-02-21 15:26:05 -0800335 Link down
Jon Halla478b852017-12-04 15:00:15 -0800336 """
Jon Hallab611372018-02-21 15:26:05 -0800337 src = main.params['kill']['linkSrc']
338 dst = main.params['kill']['linkDst']
339 main.HA.linkDown( main, src, dst )
Jon Halla478b852017-12-04 15:00:15 -0800340
341 def CASE10( self, main ):
342 """
Jon Hallab611372018-02-21 15:26:05 -0800343 Link up
Jon Halla478b852017-12-04 15:00:15 -0800344 """
Jon Hallab611372018-02-21 15:26:05 -0800345 src = main.params['kill']['linkSrc']
346 dst = main.params['kill']['linkDst']
347 main.HA.linkUp( main, src, dst )
Jon Halla478b852017-12-04 15:00:15 -0800348
349 def CASE11( self, main ):
350 """
351 Switch Down
352 """
353 # NOTE: You should probably run a topology check after this
354 main.HA.switchDown( main )
355
356 def CASE12( self, main ):
357 """
358 Switch Up
359 """
360 # NOTE: You should probably run a topology check after this
361 main.HA.switchUp( main )
362
363 def CASE13( self, main ):
364 """
365 Clean up
366 """
367 main.HAlabels.append( "Restart" )
368 main.HAdata.append( str( main.restartTime ) )
369 main.HA.cleanUp( main )
370
371 def CASE14( self, main ):
372 """
Jon Hallab611372018-02-21 15:26:05 -0800373 Start election app on all onos nodes
Jon Halla478b852017-12-04 15:00:15 -0800374 """
375 main.HA.startElectionApp( main )
376
377 def CASE15( self, main ):
378 """
379 Check that Leadership Election is still functional
380 15.1 Run election on each node
381 15.2 Check that each node has the same leaders and candidates
382 15.3 Find current leader and withdraw
383 15.4 Check that a new node was elected leader
384 15.5 Check that that new leader was the candidate of old leader
385 15.6 Run for election on old leader
386 15.7 Check that oldLeader is a candidate, and leader if only 1 node
387 15.8 Make sure that the old leader was added to the candidate list
388
389 old and new variable prefixes refer to data from before vs after
390 withdrawl and later before withdrawl vs after re-election
391 """
392 main.HA.isElectionFunctional( main )
393
394 def CASE16( self, main ):
395 """
396 Install Distributed Primitives app
397 """
398 main.HA.installDistributedPrimitiveApp( main )
399
400 def CASE17( self, main ):
401 """
402 Check for basic functionality with distributed primitives
403 """
404 main.HA.checkDistPrimitivesFunc( main )