blob: b221347533c9a5ca5fa61c1f9c2b964405eeab5c [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 )
Jon Hall69b2b982016-05-11 12:04:59 -070096
Devin Lim142b5342017-07-20 15:22:39 -070097 main.testSetUp.ONOSSetUp( main.Mininet1, main.Cluster, cellName=cellName, removeLog=True,
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070098 extraApply=[ main.HA.setServerForCluster,
99 main.HA.swapNodeMetadata,
100 main.HA.startingMininet,
101 main.HA.copyBackupConfig,
102 main.HA.setMetadataUrl ],
103 extraClean=main.HA.cleanUpOnosService,
104 installMax=True )
Devin Lim58046fa2017-07-05 16:55:00 -0700105 main.HA.initialSetUp()
Jon Hall69b2b982016-05-11 12:04:59 -0700106
107 def CASE2( self, main ):
108 """
109 Assign devices to controllers
110 """
Devin Lim58046fa2017-07-05 16:55:00 -0700111 main.HA.assignDevices( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700112
113 def CASE21( self, main ):
114 """
115 Assign mastership to controllers
116 """
Devin Lim58046fa2017-07-05 16:55:00 -0700117 main.HA.assignMastership( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700118
119 def CASE3( self, main ):
120 """
121 Assign intents
122 """
Devin Lim58046fa2017-07-05 16:55:00 -0700123 main.HA.assignIntents( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700124
125 def CASE4( self, main ):
126 """
127 Ping across added host intents
128 """
Jon Hallca319892017-06-15 15:25:22 -0700129 main.HA.pingAcrossHostIntent( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700130
131 def CASE5( self, main ):
132 """
133 Reading state of ONOS
134 """
Devin Lim58046fa2017-07-05 16:55:00 -0700135 main.HA.readingState( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700136
137 def CASE6( self, main ):
138 """
139 The Scaling case.
140 """
141 import time
142 import re
Jon Hall69b2b982016-05-11 12:04:59 -0700143 assert main, "main not defined"
144 assert utilities.assert_equals, "utilities.assert_equals not defined"
Jon Hall69b2b982016-05-11 12:04:59 -0700145 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700146 main.HAlabels
147 except ( NameError, AttributeError ):
148 main.log.error( "main.HAlabels not defined, setting to []" )
149 main.HAlabels = []
Jon Hall69b2b982016-05-11 12:04:59 -0700150 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700151 main.HAdata
152 except ( NameError, AttributeError ):
153 main.log.error( "main.HAdata not defined, setting to []" )
154 main.HAdata = []
Jon Hall69b2b982016-05-11 12:04:59 -0700155
156 main.case( "Swap some of the ONOS nodes" )
157
158 main.step( "Checking ONOS Logs for errors" )
Devin Lim142b5342017-07-20 15:22:39 -0700159 for ctrl in main.Cluster.active():
160 main.log.debug( "Checking logs for errors on " + ctrl.name + ":" )
161 main.log.warn( main.ONOSbench.checkLogs( ctrl.ipAddress ) )
Jon Hall69b2b982016-05-11 12:04:59 -0700162
Devin Lim142b5342017-07-20 15:22:39 -0700163 activeNodes = main.Cluster.getRunningPos()
164 # Todo : this could be wrong. need to double check.
Jon Hall69b2b982016-05-11 12:04:59 -0700165 main.step( "Generate new metadata file" )
Devin Lim142b5342017-07-20 15:22:39 -0700166 old = [ activeNodes[ 1 ], activeNodes[ -2 ] ]
167 new = range( main.Cluster.maxCtrls )[ -2: ]
Jon Hall69b2b982016-05-11 12:04:59 -0700168 assert len( old ) == len( new ), "Length of nodes to swap don't match"
169 handle = main.ONOSbench.handle
170 for x, y in zip( old, new ):
171 handle.sendline( "export OC{}=$OC{}".format( x + 1, y + 1 ) )
172 handle.expect( "\$" ) # from the variable
173 ret = handle.before
174 handle.expect( "\$" ) # From the prompt
175 ret += handle.before
176 main.log.debug( ret )
Devin Lim142b5342017-07-20 15:22:39 -0700177 activeNodes.remove( x )
178 activeNodes.append( y )
Jon Hall69b2b982016-05-11 12:04:59 -0700179
Devin Lim142b5342017-07-20 15:22:39 -0700180 genResult = main.Server.generateFile( main.Cluster.numCtrls )
Jon Hall69b2b982016-05-11 12:04:59 -0700181 utilities.assert_equals( expect=main.TRUE, actual=genResult,
182 onpass="New cluster metadata file generated",
183 onfail="Failled to generate new metadata file" )
184 time.sleep( 5 ) # Give time for nodes to read new file
Devin Lim142b5342017-07-20 15:22:39 -0700185 main.Cluster.resetActive()
186 # Note : done up to this point.
Jon Hall69b2b982016-05-11 12:04:59 -0700187 main.step( "Start new nodes" ) # OR stop old nodes?
188 started = main.TRUE
189 for i in new:
Devin Lim142b5342017-07-20 15:22:39 -0700190 started = main.ONOSbench.onosStart( main.Cluster.controllers[ i ].ipAddress ) and main.TRUE
Jon Hall69b2b982016-05-11 12:04:59 -0700191 utilities.assert_equals( expect=main.TRUE, actual=started,
192 onpass="ONOS started",
193 onfail="ONOS start NOT successful" )
194
Devin Lim142b5342017-07-20 15:22:39 -0700195 main.Cluster.setRunningNode( activeNodes )
Jon Hall69b2b982016-05-11 12:04:59 -0700196
Devin Lim142b5342017-07-20 15:22:39 -0700197 main.testSetUp.setupSsh( main.Cluster )
198 main.testSetUp.checkOnosService( main.Cluster )
Jon Hall69b2b982016-05-11 12:04:59 -0700199
Devin Lim142b5342017-07-20 15:22:39 -0700200 main.testSetUp.startOnosClis( main.Cluster )
Jon Hall69b2b982016-05-11 12:04:59 -0700201
202 main.step( "Checking ONOS nodes" )
Devin Lim3ebd5e72017-11-14 10:38:00 -0800203 nodeResults = utilities.retry( main.Cluster.nodesCheck,
Jon Hall69b2b982016-05-11 12:04:59 -0700204 False,
Jon Hall69b2b982016-05-11 12:04:59 -0700205 attempts=5 )
206 utilities.assert_equals( expect=True, actual=nodeResults,
207 onpass="Nodes check successful",
208 onfail="Nodes check NOT successful" )
209
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700210 ready = utilities.retry( main.Cluster.command,
Devin Lim142b5342017-07-20 15:22:39 -0700211 False,
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700212 kwargs={ "function": "summary", "contentCheck": True },
Devin Lim142b5342017-07-20 15:22:39 -0700213 sleep=30,
214 attempts=10 )
Jon Hall69b2b982016-05-11 12:04:59 -0700215 utilities.assert_equals( expect=True, actual=ready,
216 onpass="ONOS summary command succeded",
217 onfail="ONOS summary command failed" )
218 if not ready:
Devin Lim44075962017-08-11 10:56:37 -0700219 main.cleanAndExit()
Jon Hall69b2b982016-05-11 12:04:59 -0700220
221 # Rerun for election on new nodes
222 runResults = main.TRUE
Devin Lim142b5342017-07-20 15:22:39 -0700223 for ctrl in main.Cluster.active():
224 run = ctrl.CLI.electionTestRun()
Jon Hall69b2b982016-05-11 12:04:59 -0700225 if run != main.TRUE:
Devin Lim142b5342017-07-20 15:22:39 -0700226 main.log.error( "Error running for election on " + ctrl.name )
Jon Hall69b2b982016-05-11 12:04:59 -0700227 runResults = runResults and run
228 utilities.assert_equals( expect=main.TRUE, actual=runResults,
229 onpass="Reran for election",
230 onfail="Failed to rerun for election" )
231
Devin Lim142b5342017-07-20 15:22:39 -0700232 main.HA.commonChecks()
233
Jon Hall69b2b982016-05-11 12:04:59 -0700234 def CASE7( self, main ):
235 """
236 Check state after ONOS scaling
237 """
Devin Lim142b5342017-07-20 15:22:39 -0700238 main.HA.checkStateAfterEvent( main, afterWhich=1 )
Jon Hall69b2b982016-05-11 12:04:59 -0700239
Jon Hall69b2b982016-05-11 12:04:59 -0700240 main.step( "Leadership Election is still functional" )
241 # Test of LeadershipElection
242 leaderList = []
243 leaderResult = main.TRUE
244
Devin Lim142b5342017-07-20 15:22:39 -0700245 for ctrl in main.Cluster.active():
246 leaderN = ctrl.CLI.electionTestLeader()
Jon Hall69b2b982016-05-11 12:04:59 -0700247 leaderList.append( leaderN )
248 if leaderN == main.FALSE:
249 # error in response
250 main.log.error( "Something is wrong with " +
251 "electionTestLeader function, check the" +
252 " error logs" )
253 leaderResult = main.FALSE
254 elif leaderN is None:
Devin Lim142b5342017-07-20 15:22:39 -0700255 main.log.error( ctrl.name +
Jon Hall69b2b982016-05-11 12:04:59 -0700256 " shows no leader for the election-app." )
257 leaderResult = main.FALSE
258 if len( set( leaderList ) ) != 1:
259 leaderResult = main.FALSE
260 main.log.error(
261 "Inconsistent view of leader for the election test app" )
262 # TODO: print the list
263 utilities.assert_equals(
264 expect=main.TRUE,
265 actual=leaderResult,
266 onpass="Leadership election passed",
267 onfail="Something went wrong with Leadership election" )
268
269 def CASE8( self, main ):
270 """
271 Compare topo
272 """
Devin Lim58046fa2017-07-05 16:55:00 -0700273 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700274
Jon Hall69b2b982016-05-11 12:04:59 -0700275 def CASE9( self, main ):
276 """
277 Link s3-s28 down
278 """
Devin Lim58046fa2017-07-05 16:55:00 -0700279 main.HA.linkDown( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700280
281 def CASE10( self, main ):
282 """
283 Link s3-s28 up
284 """
Devin Lim58046fa2017-07-05 16:55:00 -0700285 main.HA.linkUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700286
287 def CASE11( self, main ):
288 """
289 Switch Down
290 """
291 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700292 main.HA.switchDown( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700293
294 def CASE12( self, main ):
295 """
296 Switch Up
297 """
298 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700299 main.HA.switchUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700300
301 def CASE13( self, main ):
302 """
303 Clean up
304 """
Devin Lim58046fa2017-07-05 16:55:00 -0700305 main.HA.cleanUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700306
307 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700308 status = main.Server.stop()
Jon Hall69b2b982016-05-11 12:04:59 -0700309 utilities.assert_equals( expect=main.TRUE, actual=status,
310 onpass="Stop Server",
311 onfail="Failled to stop SimpleHTTPServer" )
312 del main.Server
313
314 def CASE14( self, main ):
315 """
316 start election app on all onos nodes
317 """
Devin Lim58046fa2017-07-05 16:55:00 -0700318 main.HA.startElectionApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700319
320 def CASE15( self, main ):
321 """
322 Check that Leadership Election is still functional
323 15.1 Run election on each node
324 15.2 Check that each node has the same leaders and candidates
325 15.3 Find current leader and withdraw
326 15.4 Check that a new node was elected leader
327 15.5 Check that that new leader was the candidate of old leader
328 15.6 Run for election on old leader
329 15.7 Check that oldLeader is a candidate, and leader if only 1 node
330 15.8 Make sure that the old leader was added to the candidate list
331
332 old and new variable prefixes refer to data from before vs after
333 withdrawl and later before withdrawl vs after re-election
334 """
Devin Lim58046fa2017-07-05 16:55:00 -0700335 main.HA.isElectionFunctional( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700336
337 def CASE16( self, main ):
338 """
339 Install Distributed Primitives app
340 """
Devin Lim58046fa2017-07-05 16:55:00 -0700341 main.HA.installDistributedPrimitiveApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700342
343 def CASE17( self, main ):
344 """
345 Check for basic functionality with distributed primitives
346 """
Devin Lim58046fa2017-07-05 16:55:00 -0700347 main.HA.checkDistPrimitivesFunc( main )