blob: e2efe920e2c0871d150c5eca524eb1d45d553796 [file] [log] [blame]
Jon Hall69b2b982016-05-11 12:04:59 -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 Hall69b2b982016-05-11 12:04:59 -070022Description: This test is to determine if ONOS can handle
23 dynamic swapping of cluster nodes.
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: Swap nodes
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 Hall69b2b982016-05-11 12:04:59 -070045class HAswapNodes:
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 Hall69b2b982016-05-11 12:04:59 -070068 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
69 "initialization" )
Jon Hall69b2b982016-05-11 12:04:59 -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:
78 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 Hall69b2b982016-05-11 12:04:59 -070081 try:
82 from tests.HA.dependencies.HA import HA
83 main.HA = HA()
Devin Lim58046fa2017-07-05 16:55:00 -070084 # load some variables from the params file
85 cellName = main.params[ 'ENV' ][ 'cellName' ]
86 main.apps = main.params[ 'ENV' ][ 'appString' ]
Jon Hallab611372018-02-21 15:26:05 -080087 stepResult = main.testSetUp.envSetup( includeCaseDesc=False )
Jon Hall69b2b982016-05-11 12:04:59 -070088 except Exception as e:
Devin Lim58046fa2017-07-05 16:55:00 -070089 main.testSetUp.envSetupException( e )
90 main.testSetUp.evnSetupConclusion( stepResult )
Jon Hall69b2b982016-05-11 12:04:59 -070091
Jon Hall5a5c8432018-11-28 11:39:57 -080092 applyFuncs = [ main.HA.removeKarafConsoleLogging, main.HA.swapNodeMetadata ]
93 applyArgs = [ None, None ]
Jon Hallab611372018-02-21 15:26:05 -080094 try:
95 if main.params[ 'topology' ][ 'topoFile' ]:
96 main.log.info( 'Skipping start of Mininet in this case, make sure you start it elsewhere' )
97 else:
98 applyFuncs.append( main.HA.startingMininet )
99 applyArgs.append( None )
100 except (KeyError, IndexError):
101 applyFuncs.append( main.HA.startingMininet )
102 applyArgs.append( None )
103
Jon Hall3e6edb32018-08-21 16:20:30 -0700104 main.testSetUp.ONOSSetUp( main.Cluster, cellName=cellName,
Jon Hallab611372018-02-21 15:26:05 -0800105 extraApply=applyFuncs,
106 applyArgs=applyArgs,
Jon Hallab611372018-02-21 15:26:05 -0800107 installMax=True,
108 includeCaseDesc=False )
Jon Hall3e6edb32018-08-21 16:20:30 -0700109 main.HA.initialSetUp()
Jon Hallab611372018-02-21 15:26:05 -0800110
111 main.step( 'Set logging levels' )
112 logging = True
113 try:
114 logs = main.params.get( 'ONOS_Logging', False )
115 if logs:
116 for namespace, level in logs.items():
117 for ctrl in main.Cluster.active():
118 ctrl.CLI.logSet( level, namespace )
119 except AttributeError:
120 logging = False
121 utilities.assert_equals( expect=True, actual=logging,
122 onpass="Set log levels",
123 onfail="Failed to set log levels" )
Jon Hall69b2b982016-05-11 12:04:59 -0700124
125 def CASE2( self, main ):
126 """
127 Assign devices to controllers
128 """
Devin Lim58046fa2017-07-05 16:55:00 -0700129 main.HA.assignDevices( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700130
Jon Hallab611372018-02-21 15:26:05 -0800131 def CASE102( self, main ):
132 """
133 Set up Spine-Leaf fabric topology in Mininet
134 """
135 main.HA.startTopology( main )
136
Jon Hall69b2b982016-05-11 12:04:59 -0700137 def CASE21( self, main ):
138 """
139 Assign mastership to controllers
140 """
Devin Lim58046fa2017-07-05 16:55:00 -0700141 main.HA.assignMastership( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700142
143 def CASE3( self, main ):
144 """
145 Assign intents
146 """
Devin Lim58046fa2017-07-05 16:55:00 -0700147 main.HA.assignIntents( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700148
149 def CASE4( self, main ):
150 """
151 Ping across added host intents
152 """
Jon Hallca319892017-06-15 15:25:22 -0700153 main.HA.pingAcrossHostIntent( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700154
Jon Hallab611372018-02-21 15:26:05 -0800155 def CASE104( self, main ):
156 """
157 Ping Hosts
158 """
159 main.case( "Check connectivity" )
160 main.step( "Ping between all hosts" )
161 pingResult = main.Mininet1.pingall()
162 utilities.assert_equals( expect=main.TRUE, actual=pingResult,
163 onpass="All Pings Passed",
164 onfail="Failed to ping between all hosts" )
165
Jon Hall69b2b982016-05-11 12:04:59 -0700166 def CASE5( self, main ):
167 """
168 Reading state of ONOS
169 """
Devin Lim58046fa2017-07-05 16:55:00 -0700170 main.HA.readingState( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700171
172 def CASE6( self, main ):
173 """
174 The Scaling case.
175 """
Jon Hall69b2b982016-05-11 12:04:59 -0700176 assert main, "main not defined"
177 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Hall69b2b982016-05-11 12:04:59 -0700178 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700179 main.HAlabels
180 except ( NameError, AttributeError ):
181 main.log.error( "main.HAlabels not defined, setting to []" )
182 main.HAlabels = []
Jon Hall69b2b982016-05-11 12:04:59 -0700183 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700184 main.HAdata
185 except ( NameError, AttributeError ):
186 main.log.error( "main.HAdata not defined, setting to []" )
187 main.HAdata = []
Jon Hall69b2b982016-05-11 12:04:59 -0700188
189 main.case( "Swap some of the ONOS nodes" )
190
191 main.step( "Checking ONOS Logs for errors" )
Devin Lim142b5342017-07-20 15:22:39 -0700192 for ctrl in main.Cluster.active():
193 main.log.debug( "Checking logs for errors on " + ctrl.name + ":" )
194 main.log.warn( main.ONOSbench.checkLogs( ctrl.ipAddress ) )
Jon Hall69b2b982016-05-11 12:04:59 -0700195
Devin Lim142b5342017-07-20 15:22:39 -0700196 activeNodes = main.Cluster.getRunningPos()
Devin Lim142b5342017-07-20 15:22:39 -0700197 old = [ activeNodes[ 1 ], activeNodes[ -2 ] ]
198 new = range( main.Cluster.maxCtrls )[ -2: ]
Jon Hall69b2b982016-05-11 12:04:59 -0700199 assert len( old ) == len( new ), "Length of nodes to swap don't match"
200 handle = main.ONOSbench.handle
201 for x, y in zip( old, new ):
202 handle.sendline( "export OC{}=$OC{}".format( x + 1, y + 1 ) )
203 handle.expect( "\$" ) # from the variable
204 ret = handle.before
205 handle.expect( "\$" ) # From the prompt
206 ret += handle.before
207 main.log.debug( ret )
Devin Lim142b5342017-07-20 15:22:39 -0700208 activeNodes.remove( x )
209 activeNodes.append( y )
Jon Hall69b2b982016-05-11 12:04:59 -0700210
Jon Halla1e8e512018-05-11 13:30:57 -0700211 main.Cluster.clearActive()
Devin Lim142b5342017-07-20 15:22:39 -0700212 # Note : done up to this point.
Jon Hall69b2b982016-05-11 12:04:59 -0700213 main.step( "Start new nodes" ) # OR stop old nodes?
214 started = main.TRUE
Jon Hall3e6edb32018-08-21 16:20:30 -0700215 stopped = main.TRUE
Jon Hall69b2b982016-05-11 12:04:59 -0700216 for i in new:
Jon Hall3e6edb32018-08-21 16:20:30 -0700217 started = main.ONOSbench.onosStart( main.Cluster.controllers[ i ].ipAddress ) and started
Jon Hall69b2b982016-05-11 12:04:59 -0700218 utilities.assert_equals( expect=main.TRUE, actual=started,
219 onpass="ONOS started",
220 onfail="ONOS start NOT successful" )
Jon Hall3e6edb32018-08-21 16:20:30 -0700221 for i in old:
222 main.log.debug( "Stopping " + str( main.Cluster.controllers[ i ].ipAddress ) )
223 stopped = main.ONOSbench.onosStop( main.Cluster.controllers[ i ].ipAddress ) and stopped
224 utilities.assert_equals( expect=main.TRUE, actual=stopped,
225 onpass="ONOS stopped",
226 onfail="ONOS stop NOT successful" )
Jon Hall69b2b982016-05-11 12:04:59 -0700227
Devin Lim142b5342017-07-20 15:22:39 -0700228 main.Cluster.setRunningNode( activeNodes )
Jon Hall69b2b982016-05-11 12:04:59 -0700229
Devin Lim142b5342017-07-20 15:22:39 -0700230 main.testSetUp.setupSsh( main.Cluster )
231 main.testSetUp.checkOnosService( main.Cluster )
Jon Hall69b2b982016-05-11 12:04:59 -0700232
Devin Lim142b5342017-07-20 15:22:39 -0700233 main.testSetUp.startOnosClis( main.Cluster )
Jon Hall69b2b982016-05-11 12:04:59 -0700234
235 main.step( "Checking ONOS nodes" )
Devin Lim3ebd5e72017-11-14 10:38:00 -0800236 nodeResults = utilities.retry( main.Cluster.nodesCheck,
Jon Hall69b2b982016-05-11 12:04:59 -0700237 False,
Jon Hall3e6edb32018-08-21 16:20:30 -0700238 attempts=15 )
Jon Hall69b2b982016-05-11 12:04:59 -0700239 utilities.assert_equals( expect=True, actual=nodeResults,
240 onpass="Nodes check successful",
241 onfail="Nodes check NOT successful" )
242
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700243 ready = utilities.retry( main.Cluster.command,
Jon Hall3e6edb32018-08-21 16:20:30 -0700244 False,
245 kwargs={ "function": "summary", "contentCheck": True },
246 sleep=30,
247 attempts=10 )
Jon Hall69b2b982016-05-11 12:04:59 -0700248 utilities.assert_equals( expect=True, actual=ready,
249 onpass="ONOS summary command succeded",
250 onfail="ONOS summary command failed" )
251 if not ready:
Devin Lim44075962017-08-11 10:56:37 -0700252 main.cleanAndExit()
Jon Hall69b2b982016-05-11 12:04:59 -0700253
254 # Rerun for election on new nodes
255 runResults = main.TRUE
Devin Lim142b5342017-07-20 15:22:39 -0700256 for ctrl in main.Cluster.active():
257 run = ctrl.CLI.electionTestRun()
Jon Hall69b2b982016-05-11 12:04:59 -0700258 if run != main.TRUE:
Devin Lim142b5342017-07-20 15:22:39 -0700259 main.log.error( "Error running for election on " + ctrl.name )
Jon Hall69b2b982016-05-11 12:04:59 -0700260 runResults = runResults and run
261 utilities.assert_equals( expect=main.TRUE, actual=runResults,
262 onpass="Reran for election",
263 onfail="Failed to rerun for election" )
264
Devin Lim142b5342017-07-20 15:22:39 -0700265 main.HA.commonChecks()
266
Jon Hall69b2b982016-05-11 12:04:59 -0700267 def CASE7( self, main ):
268 """
269 Check state after ONOS scaling
270 """
Devin Lim142b5342017-07-20 15:22:39 -0700271 main.HA.checkStateAfterEvent( main, afterWhich=1 )
Jon Hall69b2b982016-05-11 12:04:59 -0700272
Jon Hall69b2b982016-05-11 12:04:59 -0700273 main.step( "Leadership Election is still functional" )
274 # Test of LeadershipElection
275 leaderList = []
276 leaderResult = main.TRUE
277
Devin Lim142b5342017-07-20 15:22:39 -0700278 for ctrl in main.Cluster.active():
279 leaderN = ctrl.CLI.electionTestLeader()
Jon Hall69b2b982016-05-11 12:04:59 -0700280 leaderList.append( leaderN )
281 if leaderN == main.FALSE:
282 # error in response
283 main.log.error( "Something is wrong with " +
284 "electionTestLeader function, check the" +
285 " error logs" )
286 leaderResult = main.FALSE
287 elif leaderN is None:
Devin Lim142b5342017-07-20 15:22:39 -0700288 main.log.error( ctrl.name +
Jon Hall69b2b982016-05-11 12:04:59 -0700289 " shows no leader for the election-app." )
290 leaderResult = main.FALSE
291 if len( set( leaderList ) ) != 1:
292 leaderResult = main.FALSE
293 main.log.error(
294 "Inconsistent view of leader for the election test app" )
Jon Hallab611372018-02-21 15:26:05 -0800295 main.log.debug( leaderList )
Jon Hall69b2b982016-05-11 12:04:59 -0700296 utilities.assert_equals(
297 expect=main.TRUE,
298 actual=leaderResult,
299 onpass="Leadership election passed",
300 onfail="Something went wrong with Leadership election" )
301
302 def CASE8( self, main ):
303 """
304 Compare topo
305 """
Devin Lim58046fa2017-07-05 16:55:00 -0700306 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700307
Jon Hall69b2b982016-05-11 12:04:59 -0700308 def CASE9( self, main ):
309 """
Jon Hallab611372018-02-21 15:26:05 -0800310 Link down
Jon Hall69b2b982016-05-11 12:04:59 -0700311 """
Jon Hallab611372018-02-21 15:26:05 -0800312 src = main.params['kill']['linkSrc']
313 dst = main.params['kill']['linkDst']
314 main.HA.linkDown( main, src, dst )
Jon Hall69b2b982016-05-11 12:04:59 -0700315
316 def CASE10( self, main ):
317 """
Jon Hallab611372018-02-21 15:26:05 -0800318 Link up
Jon Hall69b2b982016-05-11 12:04:59 -0700319 """
Jon Hallab611372018-02-21 15:26:05 -0800320 src = main.params['kill']['linkSrc']
321 dst = main.params['kill']['linkDst']
322 main.HA.linkUp( main, src, dst )
Jon Hall69b2b982016-05-11 12:04:59 -0700323
324 def CASE11( self, main ):
325 """
326 Switch Down
327 """
328 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700329 main.HA.switchDown( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700330
331 def CASE12( self, main ):
332 """
333 Switch Up
334 """
335 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700336 main.HA.switchUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700337
338 def CASE13( self, main ):
339 """
340 Clean up
341 """
Devin Lim58046fa2017-07-05 16:55:00 -0700342 main.HA.cleanUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700343
Jon Hall69b2b982016-05-11 12:04:59 -0700344 def CASE14( self, main ):
345 """
Jon Hallab611372018-02-21 15:26:05 -0800346 Start election app on all onos nodes
Jon Hall69b2b982016-05-11 12:04:59 -0700347 """
Devin Lim58046fa2017-07-05 16:55:00 -0700348 main.HA.startElectionApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700349
350 def CASE15( self, main ):
351 """
352 Check that Leadership Election is still functional
353 15.1 Run election on each node
354 15.2 Check that each node has the same leaders and candidates
355 15.3 Find current leader and withdraw
356 15.4 Check that a new node was elected leader
357 15.5 Check that that new leader was the candidate of old leader
358 15.6 Run for election on old leader
359 15.7 Check that oldLeader is a candidate, and leader if only 1 node
360 15.8 Make sure that the old leader was added to the candidate list
361
362 old and new variable prefixes refer to data from before vs after
363 withdrawl and later before withdrawl vs after re-election
364 """
Devin Lim58046fa2017-07-05 16:55:00 -0700365 main.HA.isElectionFunctional( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700366
367 def CASE16( self, main ):
368 """
369 Install Distributed Primitives app
370 """
Devin Lim58046fa2017-07-05 16:55:00 -0700371 main.HA.installDistributedPrimitiveApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700372
373 def CASE17( self, main ):
374 """
375 Check for basic functionality with distributed primitives
376 """
Devin Lim58046fa2017-07-05 16:55:00 -0700377 main.HA.checkDistPrimitivesFunc( main )