blob: e0751f6fdbb7e332c1d7ae6ec57952ac86babd0a [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" )
204 nodeResults = utilities.retry( main.HA.nodesCheck,
205 False,
Devin Lim142b5342017-07-20 15:22:39 -0700206 args=[ main.Cluster.active() ],
Jon Hall69b2b982016-05-11 12:04:59 -0700207 attempts=5 )
208 utilities.assert_equals( expect=True, actual=nodeResults,
209 onpass="Nodes check successful",
210 onfail="Nodes check NOT successful" )
211
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700212 ready = utilities.retry( main.Cluster.command,
Devin Lim142b5342017-07-20 15:22:39 -0700213 False,
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700214 kwargs={ "function": "summary", "contentCheck": True },
Devin Lim142b5342017-07-20 15:22:39 -0700215 sleep=30,
216 attempts=10 )
Jon Hall69b2b982016-05-11 12:04:59 -0700217 utilities.assert_equals( expect=True, actual=ready,
218 onpass="ONOS summary command succeded",
219 onfail="ONOS summary command failed" )
220 if not ready:
Devin Lim44075962017-08-11 10:56:37 -0700221 main.cleanAndExit()
Jon Hall69b2b982016-05-11 12:04:59 -0700222
223 # Rerun for election on new nodes
224 runResults = main.TRUE
Devin Lim142b5342017-07-20 15:22:39 -0700225 for ctrl in main.Cluster.active():
226 run = ctrl.CLI.electionTestRun()
Jon Hall69b2b982016-05-11 12:04:59 -0700227 if run != main.TRUE:
Devin Lim142b5342017-07-20 15:22:39 -0700228 main.log.error( "Error running for election on " + ctrl.name )
Jon Hall69b2b982016-05-11 12:04:59 -0700229 runResults = runResults and run
230 utilities.assert_equals( expect=main.TRUE, actual=runResults,
231 onpass="Reran for election",
232 onfail="Failed to rerun for election" )
233
Devin Lim142b5342017-07-20 15:22:39 -0700234 main.HA.commonChecks()
235
Jon Hall69b2b982016-05-11 12:04:59 -0700236 def CASE7( self, main ):
237 """
238 Check state after ONOS scaling
239 """
Devin Lim142b5342017-07-20 15:22:39 -0700240 main.HA.checkStateAfterEvent( main, afterWhich=1 )
Jon Hall69b2b982016-05-11 12:04:59 -0700241
Jon Hall69b2b982016-05-11 12:04:59 -0700242 main.step( "Leadership Election is still functional" )
243 # Test of LeadershipElection
244 leaderList = []
245 leaderResult = main.TRUE
246
Devin Lim142b5342017-07-20 15:22:39 -0700247 for ctrl in main.Cluster.active():
248 leaderN = ctrl.CLI.electionTestLeader()
Jon Hall69b2b982016-05-11 12:04:59 -0700249 leaderList.append( leaderN )
250 if leaderN == main.FALSE:
251 # error in response
252 main.log.error( "Something is wrong with " +
253 "electionTestLeader function, check the" +
254 " error logs" )
255 leaderResult = main.FALSE
256 elif leaderN is None:
Devin Lim142b5342017-07-20 15:22:39 -0700257 main.log.error( ctrl.name +
Jon Hall69b2b982016-05-11 12:04:59 -0700258 " shows no leader for the election-app." )
259 leaderResult = main.FALSE
260 if len( set( leaderList ) ) != 1:
261 leaderResult = main.FALSE
262 main.log.error(
263 "Inconsistent view of leader for the election test app" )
264 # TODO: print the list
265 utilities.assert_equals(
266 expect=main.TRUE,
267 actual=leaderResult,
268 onpass="Leadership election passed",
269 onfail="Something went wrong with Leadership election" )
270
271 def CASE8( self, main ):
272 """
273 Compare topo
274 """
Devin Lim58046fa2017-07-05 16:55:00 -0700275 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700276
Jon Hall69b2b982016-05-11 12:04:59 -0700277 def CASE9( self, main ):
278 """
279 Link s3-s28 down
280 """
Devin Lim58046fa2017-07-05 16:55:00 -0700281 main.HA.linkDown( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700282
283 def CASE10( self, main ):
284 """
285 Link s3-s28 up
286 """
Devin Lim58046fa2017-07-05 16:55:00 -0700287 main.HA.linkUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700288
289 def CASE11( self, main ):
290 """
291 Switch Down
292 """
293 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700294 main.HA.switchDown( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700295
296 def CASE12( self, main ):
297 """
298 Switch Up
299 """
300 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700301 main.HA.switchUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700302
303 def CASE13( self, main ):
304 """
305 Clean up
306 """
Devin Lim58046fa2017-07-05 16:55:00 -0700307 main.HA.cleanUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700308
309 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700310 status = main.Server.stop()
Jon Hall69b2b982016-05-11 12:04:59 -0700311 utilities.assert_equals( expect=main.TRUE, actual=status,
312 onpass="Stop Server",
313 onfail="Failled to stop SimpleHTTPServer" )
314 del main.Server
315
316 def CASE14( self, main ):
317 """
318 start election app on all onos nodes
319 """
Devin Lim58046fa2017-07-05 16:55:00 -0700320 main.HA.startElectionApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700321
322 def CASE15( self, main ):
323 """
324 Check that Leadership Election is still functional
325 15.1 Run election on each node
326 15.2 Check that each node has the same leaders and candidates
327 15.3 Find current leader and withdraw
328 15.4 Check that a new node was elected leader
329 15.5 Check that that new leader was the candidate of old leader
330 15.6 Run for election on old leader
331 15.7 Check that oldLeader is a candidate, and leader if only 1 node
332 15.8 Make sure that the old leader was added to the candidate list
333
334 old and new variable prefixes refer to data from before vs after
335 withdrawl and later before withdrawl vs after re-election
336 """
Devin Lim58046fa2017-07-05 16:55:00 -0700337 main.HA.isElectionFunctional( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700338
339 def CASE16( self, main ):
340 """
341 Install Distributed Primitives app
342 """
Devin Lim58046fa2017-07-05 16:55:00 -0700343 main.HA.installDistributedPrimitiveApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700344
345 def CASE17( self, main ):
346 """
347 Check for basic functionality with distributed primitives
348 """
Devin Lim58046fa2017-07-05 16:55:00 -0700349 main.HA.checkDistPrimitivesFunc( main )