blob: d4c69e5dd72d096a1a68fbd9ff98d25eec737990 [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" )
203 nodeResults = utilities.retry( main.HA.nodesCheck,
204 False,
Devin Lim142b5342017-07-20 15:22:39 -0700205 args=[ main.Cluster.active() ],
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 )