blob: b7da7bca3ea73b96bc7b6bfd6f2f69768939ae35 [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 """
68 import time
69 import os
70 import re
71 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
72 "initialization" )
Jon Hall69b2b982016-05-11 12:04:59 -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:
81 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 Hall69b2b982016-05-11 12:04:59 -070084 try:
85 from tests.HA.dependencies.HA import HA
86 main.HA = HA()
87 from tests.HA.HAswapNodes.dependencies.Server import Server
88 main.Server = Server()
Devin Lim58046fa2017-07-05 16:55:00 -070089 # load some variables from the params file
90 cellName = main.params[ 'ENV' ][ 'cellName' ]
91 main.apps = main.params[ 'ENV' ][ 'appString' ]
Devin Lim142b5342017-07-20 15:22:39 -070092 stepResult = main.testSetUp.envSetup()
Jon Hall69b2b982016-05-11 12:04:59 -070093 except Exception as e:
Devin Lim58046fa2017-07-05 16:55:00 -070094 main.testSetUp.envSetupException( e )
95 main.testSetUp.evnSetupConclusion( stepResult )
96 main.HA.generateGraph( "HAswapNodes" )
Jon Hall69b2b982016-05-11 12:04:59 -070097
Devin Lim142b5342017-07-20 15:22:39 -070098 main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster, cellName=cellName, removeLog=True,
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070099 extraApply=[ main.HA.setServerForCluster,
100 main.HA.swapNodeMetadata,
101 main.HA.startingMininet,
102 main.HA.copyBackupConfig,
103 main.HA.setMetadataUrl ],
104 extraClean=main.HA.cleanUpOnosService,
105 installMax=True )
Devin Lim58046fa2017-07-05 16:55:00 -0700106 main.HA.initialSetUp()
Jon Hall69b2b982016-05-11 12:04:59 -0700107
108 def CASE2( self, main ):
109 """
110 Assign devices to controllers
111 """
Devin Lim58046fa2017-07-05 16:55:00 -0700112 main.HA.assignDevices( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700113
114 def CASE21( self, main ):
115 """
116 Assign mastership to controllers
117 """
Devin Lim58046fa2017-07-05 16:55:00 -0700118 main.HA.assignMastership( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700119
120 def CASE3( self, main ):
121 """
122 Assign intents
123 """
Devin Lim58046fa2017-07-05 16:55:00 -0700124 main.HA.assignIntents( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700125
126 def CASE4( self, main ):
127 """
128 Ping across added host intents
129 """
Jon Hallca319892017-06-15 15:25:22 -0700130 main.HA.pingAcrossHostIntent( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700131
132 def CASE5( self, main ):
133 """
134 Reading state of ONOS
135 """
Devin Lim58046fa2017-07-05 16:55:00 -0700136 main.HA.readingState( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700137
138 def CASE6( self, main ):
139 """
140 The Scaling case.
141 """
142 import time
143 import re
Jon Hall69b2b982016-05-11 12:04:59 -0700144 assert main, "main not defined"
145 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Hall69b2b982016-05-11 12:04:59 -0700146 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700147 main.HAlabels
148 except ( NameError, AttributeError ):
149 main.log.error( "main.HAlabels not defined, setting to []" )
150 main.HAlabels = []
Jon Hall69b2b982016-05-11 12:04:59 -0700151 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700152 main.HAdata
153 except ( NameError, AttributeError ):
154 main.log.error( "main.HAdata not defined, setting to []" )
155 main.HAdata = []
Jon Hall69b2b982016-05-11 12:04:59 -0700156
157 main.case( "Swap some of the ONOS nodes" )
158
159 main.step( "Checking ONOS Logs for errors" )
Devin Lim142b5342017-07-20 15:22:39 -0700160 for ctrl in main.Cluster.active():
161 main.log.debug( "Checking logs for errors on " + ctrl.name + ":" )
162 main.log.warn( main.ONOSbench.checkLogs( ctrl.ipAddress ) )
Jon Hall69b2b982016-05-11 12:04:59 -0700163
Devin Lim142b5342017-07-20 15:22:39 -0700164 activeNodes = main.Cluster.getRunningPos()
165 # Todo : this could be wrong. need to double check.
Jon Hall69b2b982016-05-11 12:04:59 -0700166 main.step( "Generate new metadata file" )
Devin Lim142b5342017-07-20 15:22:39 -0700167 old = [ activeNodes[ 1 ], activeNodes[ -2 ] ]
168 new = range( main.Cluster.maxCtrls )[ -2: ]
Jon Hall69b2b982016-05-11 12:04:59 -0700169 assert len( old ) == len( new ), "Length of nodes to swap don't match"
170 handle = main.ONOSbench.handle
171 for x, y in zip( old, new ):
172 handle.sendline( "export OC{}=$OC{}".format( x + 1, y + 1 ) )
173 handle.expect( "\$" ) # from the variable
174 ret = handle.before
175 handle.expect( "\$" ) # From the prompt
176 ret += handle.before
177 main.log.debug( ret )
Devin Lim142b5342017-07-20 15:22:39 -0700178 activeNodes.remove( x )
179 activeNodes.append( y )
Jon Hall69b2b982016-05-11 12:04:59 -0700180
Devin Lim142b5342017-07-20 15:22:39 -0700181 genResult = main.Server.generateFile( main.Cluster.numCtrls )
Jon Hall69b2b982016-05-11 12:04:59 -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
Devin Lim142b5342017-07-20 15:22:39 -0700186 main.Cluster.resetActive()
187 # Note : done up to this point.
Jon Hall69b2b982016-05-11 12:04:59 -0700188 main.step( "Start new nodes" ) # OR stop old nodes?
189 started = main.TRUE
190 for i in new:
Devin Lim142b5342017-07-20 15:22:39 -0700191 started = main.ONOSbench.onosStart( main.Cluster.controllers[ i ].ipAddress ) and main.TRUE
Jon Hall69b2b982016-05-11 12:04:59 -0700192 utilities.assert_equals( expect=main.TRUE, actual=started,
193 onpass="ONOS started",
194 onfail="ONOS start NOT successful" )
195
Devin Lim142b5342017-07-20 15:22:39 -0700196 main.Cluster.setRunningNode( activeNodes )
Jon Hall69b2b982016-05-11 12:04:59 -0700197
Devin Lim142b5342017-07-20 15:22:39 -0700198 main.testSetUp.setupSsh( main.Cluster )
199 main.testSetUp.checkOnosService( main.Cluster )
Jon Hall69b2b982016-05-11 12:04:59 -0700200
Devin Lim142b5342017-07-20 15:22:39 -0700201 main.testSetUp.startOnosClis( main.Cluster )
Jon Hall69b2b982016-05-11 12:04:59 -0700202
203 main.step( "Checking ONOS nodes" )
Devin Lim3ebd5e72017-11-14 10:38:00 -0800204 nodeResults = utilities.retry( main.Cluster.nodesCheck,
Jon Hall69b2b982016-05-11 12:04:59 -0700205 False,
Jon Hall69b2b982016-05-11 12:04:59 -0700206 attempts=5 )
207 utilities.assert_equals( expect=True, actual=nodeResults,
208 onpass="Nodes check successful",
209 onfail="Nodes check NOT successful" )
210
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700211 ready = utilities.retry( main.Cluster.command,
Devin Lim142b5342017-07-20 15:22:39 -0700212 False,
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700213 kwargs={ "function": "summary", "contentCheck": True },
Devin Lim142b5342017-07-20 15:22:39 -0700214 sleep=30,
215 attempts=10 )
Jon Hall69b2b982016-05-11 12:04:59 -0700216 utilities.assert_equals( expect=True, actual=ready,
217 onpass="ONOS summary command succeded",
218 onfail="ONOS summary command failed" )
219 if not ready:
Devin Lim44075962017-08-11 10:56:37 -0700220 main.cleanAndExit()
Jon Hall69b2b982016-05-11 12:04:59 -0700221
222 # Rerun for election on new nodes
223 runResults = main.TRUE
Devin Lim142b5342017-07-20 15:22:39 -0700224 for ctrl in main.Cluster.active():
225 run = ctrl.CLI.electionTestRun()
Jon Hall69b2b982016-05-11 12:04:59 -0700226 if run != main.TRUE:
Devin Lim142b5342017-07-20 15:22:39 -0700227 main.log.error( "Error running for election on " + ctrl.name )
Jon Hall69b2b982016-05-11 12:04:59 -0700228 runResults = runResults and run
229 utilities.assert_equals( expect=main.TRUE, actual=runResults,
230 onpass="Reran for election",
231 onfail="Failed to rerun for election" )
232
Devin Lim142b5342017-07-20 15:22:39 -0700233 main.HA.commonChecks()
234
Jon Hall69b2b982016-05-11 12:04:59 -0700235 def CASE7( self, main ):
236 """
237 Check state after ONOS scaling
238 """
Devin Lim142b5342017-07-20 15:22:39 -0700239 main.HA.checkStateAfterEvent( main, afterWhich=1 )
Jon Hall69b2b982016-05-11 12:04:59 -0700240
Jon Hall69b2b982016-05-11 12:04:59 -0700241 main.step( "Leadership Election is still functional" )
242 # Test of LeadershipElection
243 leaderList = []
244 leaderResult = main.TRUE
245
Devin Lim142b5342017-07-20 15:22:39 -0700246 for ctrl in main.Cluster.active():
247 leaderN = ctrl.CLI.electionTestLeader()
Jon Hall69b2b982016-05-11 12:04:59 -0700248 leaderList.append( leaderN )
249 if leaderN == main.FALSE:
250 # error in response
251 main.log.error( "Something is wrong with " +
252 "electionTestLeader function, check the" +
253 " error logs" )
254 leaderResult = main.FALSE
255 elif leaderN is None:
Devin Lim142b5342017-07-20 15:22:39 -0700256 main.log.error( ctrl.name +
Jon Hall69b2b982016-05-11 12:04:59 -0700257 " shows no leader for the election-app." )
258 leaderResult = main.FALSE
259 if len( set( leaderList ) ) != 1:
260 leaderResult = main.FALSE
261 main.log.error(
262 "Inconsistent view of leader for the election test app" )
263 # TODO: print the list
264 utilities.assert_equals(
265 expect=main.TRUE,
266 actual=leaderResult,
267 onpass="Leadership election passed",
268 onfail="Something went wrong with Leadership election" )
269
270 def CASE8( self, main ):
271 """
272 Compare topo
273 """
Devin Lim58046fa2017-07-05 16:55:00 -0700274 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700275
Jon Hall69b2b982016-05-11 12:04:59 -0700276 def CASE9( self, main ):
277 """
278 Link s3-s28 down
279 """
Devin Lim58046fa2017-07-05 16:55:00 -0700280 main.HA.linkDown( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700281
282 def CASE10( self, main ):
283 """
284 Link s3-s28 up
285 """
Devin Lim58046fa2017-07-05 16:55:00 -0700286 main.HA.linkUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700287
288 def CASE11( self, main ):
289 """
290 Switch Down
291 """
292 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700293 main.HA.switchDown( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700294
295 def CASE12( self, main ):
296 """
297 Switch Up
298 """
299 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700300 main.HA.switchUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700301
302 def CASE13( self, main ):
303 """
304 Clean up
305 """
Devin Lim58046fa2017-07-05 16:55:00 -0700306 main.HA.cleanUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700307
308 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700309 status = main.Server.stop()
Jon Hall69b2b982016-05-11 12:04:59 -0700310 utilities.assert_equals( expect=main.TRUE, actual=status,
311 onpass="Stop Server",
312 onfail="Failled to stop SimpleHTTPServer" )
313 del main.Server
314
315 def CASE14( self, main ):
316 """
317 start election app on all onos nodes
318 """
Devin Lim58046fa2017-07-05 16:55:00 -0700319 main.HA.startElectionApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700320
321 def CASE15( self, main ):
322 """
323 Check that Leadership Election is still functional
324 15.1 Run election on each node
325 15.2 Check that each node has the same leaders and candidates
326 15.3 Find current leader and withdraw
327 15.4 Check that a new node was elected leader
328 15.5 Check that that new leader was the candidate of old leader
329 15.6 Run for election on old leader
330 15.7 Check that oldLeader is a candidate, and leader if only 1 node
331 15.8 Make sure that the old leader was added to the candidate list
332
333 old and new variable prefixes refer to data from before vs after
334 withdrawl and later before withdrawl vs after re-election
335 """
Devin Lim58046fa2017-07-05 16:55:00 -0700336 main.HA.isElectionFunctional( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700337
338 def CASE16( self, main ):
339 """
340 Install Distributed Primitives app
341 """
Devin Lim58046fa2017-07-05 16:55:00 -0700342 main.HA.installDistributedPrimitiveApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700343
344 def CASE17( self, main ):
345 """
346 Check for basic functionality with distributed primitives
347 """
Devin Lim58046fa2017-07-05 16:55:00 -0700348 main.HA.checkDistPrimitivesFunc( main )