blob: e5e9f467e7557c4d37022db0f057a7159c9e12b8 [file] [log] [blame]
Jon Hall69b2b982016-05-11 12:04:59 -07001"""
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07002Copyright 2016 Open Networking Foundation (ONF)
3
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
11 (at your option) any later version.
12
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"""
21
22"""
Jon Hall69b2b982016-05-11 12:04:59 -070023Description: This test is to determine if ONOS can handle
24 dynamic swapping of cluster nodes.
25
26List of test cases:
27CASE1: Compile ONOS and push it to the test machines
28CASE2: Assign devices to controllers
29CASE21: Assign mastership to controllers
30CASE3: Assign intents
31CASE4: Ping across added host intents
32CASE5: Reading state of ONOS
33CASE6: Swap nodes
34CASE7: Check state after control plane failure
35CASE8: Compare topo
36CASE9: Link s3-s28 down
37CASE10: Link s3-s28 up
38CASE11: Switch down
39CASE12: Switch up
40CASE13: Clean up
41CASE14: start election app on all onos nodes
42CASE15: Check that Leadership Election is still functional
43CASE16: Install Distributed Primitives app
44CASE17: Check for basic functionality with distributed primitives
45"""
Jon Hall69b2b982016-05-11 12:04:59 -070046class HAswapNodes:
47
48 def __init__( self ):
49 self.default = ''
50
51 def CASE1( self, main ):
52 """
53 CASE1 is to compile ONOS and push it to the test machines
54
55 Startup sequence:
56 cell <name>
57 onos-verify-cell
58 NOTE: temporary - onos-remove-raft-logs
59 onos-uninstall
60 start mininet
61 git pull
62 mvn clean install
63 onos-package
64 onos-install -f
65 onos-wait-for-start
66 start cli sessions
67 start tcpdump
68 """
69 import time
70 import os
71 import re
72 main.log.info( "ONOS HA test: Restart all ONOS nodes - " +
73 "initialization" )
Jon Hall69b2b982016-05-11 12:04:59 -070074 # set global variables
75 # These are for csv plotting in jenkins
Devin Lim58046fa2017-07-05 16:55:00 -070076 main.HAlabels = []
77 main.HAdata = []
78 try:
79 from tests.dependencies.ONOSSetup import ONOSSetup
80 main.testSetUp = ONOSSetup()
81 except ImportError:
82 main.log.error( "ONOSSetup not found. exiting the test" )
83 main.exit()
84 main.testSetUp.envSetupDescription()
Jon Hall69b2b982016-05-11 12:04:59 -070085 try:
86 from tests.HA.dependencies.HA import HA
87 main.HA = HA()
88 from tests.HA.HAswapNodes.dependencies.Server import Server
89 main.Server = Server()
Devin Lim58046fa2017-07-05 16:55:00 -070090 # load some variables from the params file
91 cellName = main.params[ 'ENV' ][ 'cellName' ]
92 main.apps = main.params[ 'ENV' ][ 'appString' ]
93 main.numCtrls = int( main.params[ 'num_controllers' ] )
94 if main.ONOSbench.maxNodes and\
95 main.ONOSbench.maxNodes < main.numCtrls:
96 main.numCtrls = int( main.ONOSbench.maxNodes )
97 main.maxNodes = main.numCtrls
98 stepResult = main.testSetUp.envSetup( hasNode=True )
Jon Hall69b2b982016-05-11 12:04:59 -070099 except Exception as e:
Devin Lim58046fa2017-07-05 16:55:00 -0700100 main.testSetUp.envSetupException( e )
101 main.testSetUp.evnSetupConclusion( stepResult )
102 main.HA.generateGraph( "HAswapNodes" )
Jon Hall69b2b982016-05-11 12:04:59 -0700103
Jon Hall69b2b982016-05-11 12:04:59 -0700104
Devin Lim58046fa2017-07-05 16:55:00 -0700105 main.testSetUp.ONOSSetUp( main.Mininet1, cellName=cellName, removeLog=True,
106 extraApply=main.HA.customizeOnosService,
107 arg=main.HA.swapNodeMetadata,
108 extraClean=main.HA.cleanUpOnosService,
109 installMax=True )
110 main.HA.initialSetUp()
Jon Hall69b2b982016-05-11 12:04:59 -0700111
112 def CASE2( self, main ):
113 """
114 Assign devices to controllers
115 """
Devin Lim58046fa2017-07-05 16:55:00 -0700116 main.HA.assignDevices( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700117
118 def CASE21( self, main ):
119 """
120 Assign mastership to controllers
121 """
Devin Lim58046fa2017-07-05 16:55:00 -0700122 main.HA.assignMastership( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700123
124 def CASE3( self, main ):
125 """
126 Assign intents
127 """
Devin Lim58046fa2017-07-05 16:55:00 -0700128 main.HA.assignIntents( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700129
130 def CASE4( self, main ):
131 """
132 Ping across added host intents
133 """
Devin Lim58046fa2017-07-05 16:55:00 -0700134 main.HA.pingAcrossHostIntent( main, True, True )
Jon Hall69b2b982016-05-11 12:04:59 -0700135
136 def CASE5( self, main ):
137 """
138 Reading state of ONOS
139 """
Devin Lim58046fa2017-07-05 16:55:00 -0700140 main.HA.readingState( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700141
142 def CASE6( self, main ):
143 """
144 The Scaling case.
145 """
146 import time
147 import re
148 assert main.numCtrls, "main.numCtrls not defined"
149 assert main, "main not defined"
150 assert utilities.assert_equals, "utilities.assert_equals not defined"
151 assert main.CLIs, "main.CLIs not defined"
152 assert main.nodes, "main.nodes not defined"
153 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700154 main.HAlabels
155 except ( NameError, AttributeError ):
156 main.log.error( "main.HAlabels not defined, setting to []" )
157 main.HAlabels = []
Jon Hall69b2b982016-05-11 12:04:59 -0700158 try:
Devin Lim58046fa2017-07-05 16:55:00 -0700159 main.HAdata
160 except ( NameError, AttributeError ):
161 main.log.error( "main.HAdata not defined, setting to []" )
162 main.HAdata = []
Jon Hall69b2b982016-05-11 12:04:59 -0700163
164 main.case( "Swap some of the ONOS nodes" )
165
166 main.step( "Checking ONOS Logs for errors" )
167 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700168 node = main.nodes[ i ]
Jon Hall69b2b982016-05-11 12:04:59 -0700169 main.log.debug( "Checking logs for errors on " + node.name + ":" )
170 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
171
172 main.step( "Generate new metadata file" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700173 old = [ main.activeNodes[ 1 ], main.activeNodes[ -2 ] ]
174 new = range( main.ONOSbench.maxNodes )[ -2: ]
Jon Hall69b2b982016-05-11 12:04:59 -0700175 assert len( old ) == len( new ), "Length of nodes to swap don't match"
176 handle = main.ONOSbench.handle
177 for x, y in zip( old, new ):
178 handle.sendline( "export OC{}=$OC{}".format( x + 1, y + 1 ) )
179 handle.expect( "\$" ) # from the variable
180 ret = handle.before
181 handle.expect( "\$" ) # From the prompt
182 ret += handle.before
183 main.log.debug( ret )
184 main.activeNodes.remove( x )
185 main.activeNodes.append( y )
186
187 genResult = main.Server.generateFile( main.numCtrls )
188 utilities.assert_equals( expect=main.TRUE, actual=genResult,
189 onpass="New cluster metadata file generated",
190 onfail="Failled to generate new metadata file" )
191 time.sleep( 5 ) # Give time for nodes to read new file
192
193 main.step( "Start new nodes" ) # OR stop old nodes?
194 started = main.TRUE
195 for i in new:
Jon Hallf37d44d2017-05-24 10:37:30 -0700196 started = main.ONOSbench.onosStart( main.nodes[ i ].ip_address ) and main.TRUE
Jon Hall69b2b982016-05-11 12:04:59 -0700197 utilities.assert_equals( expect=main.TRUE, actual=started,
198 onpass="ONOS started",
199 onfail="ONOS start NOT successful" )
200
201 main.step( "Checking if ONOS is up yet" )
202 for i in range( 2 ):
203 onosIsupResult = main.TRUE
204 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700205 node = main.nodes[ i ]
Jon Hall168c1862017-01-31 17:35:34 -0800206 main.ONOSbench.onosSecureSSH( node=node.ip_address )
Jon Hall69b2b982016-05-11 12:04:59 -0700207 started = main.ONOSbench.isup( node.ip_address )
208 if not started:
209 main.log.error( node.name + " didn't start!" )
210 onosIsupResult = onosIsupResult and started
211 if onosIsupResult == main.TRUE:
212 break
213 utilities.assert_equals( expect=main.TRUE, actual=onosIsupResult,
214 onpass="ONOS started",
215 onfail="ONOS start NOT successful" )
216
Jon Hall6509dbf2016-06-21 17:01:17 -0700217 main.step( "Starting ONOS CLI sessions" )
Jon Hall69b2b982016-05-11 12:04:59 -0700218 cliResults = main.TRUE
219 threads = []
220 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700221 t = main.Thread( target=main.CLIs[ i ].startOnosCli,
Jon Hall69b2b982016-05-11 12:04:59 -0700222 name="startOnosCli-" + str( i ),
Jon Hallf37d44d2017-05-24 10:37:30 -0700223 args=[ main.nodes[ i ].ip_address ] )
Jon Hall69b2b982016-05-11 12:04:59 -0700224 threads.append( t )
225 t.start()
226
227 for t in threads:
228 t.join()
229 cliResults = cliResults and t.result
230 utilities.assert_equals( expect=main.TRUE, actual=cliResults,
231 onpass="ONOS cli started",
232 onfail="ONOS clis did not start" )
233
234 main.step( "Checking ONOS nodes" )
235 nodeResults = utilities.retry( main.HA.nodesCheck,
236 False,
Jon Hallf37d44d2017-05-24 10:37:30 -0700237 args=[ main.activeNodes ],
Jon Hall69b2b982016-05-11 12:04:59 -0700238 attempts=5 )
239 utilities.assert_equals( expect=True, actual=nodeResults,
240 onpass="Nodes check successful",
241 onfail="Nodes check NOT successful" )
242
243 for i in range( 10 ):
244 ready = True
245 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700246 cli = main.CLIs[ i ]
Jon Hall69b2b982016-05-11 12:04:59 -0700247 output = cli.summary()
248 if not output:
249 ready = False
250 if ready:
251 break
252 time.sleep( 30 )
253 utilities.assert_equals( expect=True, actual=ready,
254 onpass="ONOS summary command succeded",
255 onfail="ONOS summary command failed" )
256 if not ready:
257 main.cleanup()
258 main.exit()
259
260 # Rerun for election on new nodes
261 runResults = main.TRUE
262 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700263 cli = main.CLIs[ i ]
Jon Hall69b2b982016-05-11 12:04:59 -0700264 run = cli.electionTestRun()
265 if run != main.TRUE:
266 main.log.error( "Error running for election on " + cli.name )
267 runResults = runResults and run
268 utilities.assert_equals( expect=main.TRUE, actual=runResults,
269 onpass="Reran for election",
270 onfail="Failed to rerun for election" )
271
272 for node in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700273 main.log.warn( "\n****************** {} **************".format( main.nodes[ node ].ip_address ) )
274 main.log.debug( main.CLIs[ node ].nodes( jsonFormat=False ) )
275 main.log.debug( main.CLIs[ node ].leaders( jsonFormat=False ) )
276 main.log.debug( main.CLIs[ node ].partitions( jsonFormat=False ) )
277 main.log.debug( main.CLIs[ node ].apps( jsonFormat=False ) )
Jon Hall69b2b982016-05-11 12:04:59 -0700278
279 main.step( "Reapplying cell variable to environment" )
280 cellName = main.params[ 'ENV' ][ 'cellName' ]
281 cellResult = main.ONOSbench.setCell( cellName )
282 utilities.assert_equals( expect=main.TRUE, actual=cellResult,
283 onpass="Set cell successfull",
284 onfail="Failled to set cell" )
285
286 def CASE7( self, main ):
287 """
288 Check state after ONOS scaling
289 """
Jon Hall69b2b982016-05-11 12:04:59 -0700290
Devin Lim58046fa2017-07-05 16:55:00 -0700291 main.HA.checkStateAfterONOS( main, afterWhich=1 )
Jon Hall69b2b982016-05-11 12:04:59 -0700292
Jon Hall69b2b982016-05-11 12:04:59 -0700293 main.step( "Leadership Election is still functional" )
294 # Test of LeadershipElection
295 leaderList = []
296 leaderResult = main.TRUE
297
298 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700299 cli = main.CLIs[ i ]
Jon Hall69b2b982016-05-11 12:04:59 -0700300 leaderN = cli.electionTestLeader()
301 leaderList.append( leaderN )
302 if leaderN == main.FALSE:
303 # error in response
304 main.log.error( "Something is wrong with " +
305 "electionTestLeader function, check the" +
306 " error logs" )
307 leaderResult = main.FALSE
308 elif leaderN is None:
309 main.log.error( cli.name +
310 " shows no leader for the election-app." )
311 leaderResult = main.FALSE
312 if len( set( leaderList ) ) != 1:
313 leaderResult = main.FALSE
314 main.log.error(
315 "Inconsistent view of leader for the election test app" )
316 # TODO: print the list
317 utilities.assert_equals(
318 expect=main.TRUE,
319 actual=leaderResult,
320 onpass="Leadership election passed",
321 onfail="Something went wrong with Leadership election" )
322
323 def CASE8( self, main ):
324 """
325 Compare topo
326 """
Devin Lim58046fa2017-07-05 16:55:00 -0700327 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700328
Jon Hall69b2b982016-05-11 12:04:59 -0700329 def CASE9( self, main ):
330 """
331 Link s3-s28 down
332 """
Devin Lim58046fa2017-07-05 16:55:00 -0700333 main.HA.linkDown( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700334
335 def CASE10( self, main ):
336 """
337 Link s3-s28 up
338 """
Devin Lim58046fa2017-07-05 16:55:00 -0700339 main.HA.linkUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700340
341 def CASE11( self, main ):
342 """
343 Switch Down
344 """
345 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700346 main.HA.switchDown( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700347
348 def CASE12( self, main ):
349 """
350 Switch Up
351 """
352 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700353 main.HA.switchUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700354
355 def CASE13( self, main ):
356 """
357 Clean up
358 """
Devin Lim58046fa2017-07-05 16:55:00 -0700359 main.HA.cleanUp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700360
361 main.step( "Stopping webserver" )
Jon Hallf37d44d2017-05-24 10:37:30 -0700362 status = main.Server.stop()
Jon Hall69b2b982016-05-11 12:04:59 -0700363 utilities.assert_equals( expect=main.TRUE, actual=status,
364 onpass="Stop Server",
365 onfail="Failled to stop SimpleHTTPServer" )
366 del main.Server
367
368 def CASE14( self, main ):
369 """
370 start election app on all onos nodes
371 """
Devin Lim58046fa2017-07-05 16:55:00 -0700372 main.HA.startElectionApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700373
374 def CASE15( self, main ):
375 """
376 Check that Leadership Election is still functional
377 15.1 Run election on each node
378 15.2 Check that each node has the same leaders and candidates
379 15.3 Find current leader and withdraw
380 15.4 Check that a new node was elected leader
381 15.5 Check that that new leader was the candidate of old leader
382 15.6 Run for election on old leader
383 15.7 Check that oldLeader is a candidate, and leader if only 1 node
384 15.8 Make sure that the old leader was added to the candidate list
385
386 old and new variable prefixes refer to data from before vs after
387 withdrawl and later before withdrawl vs after re-election
388 """
Devin Lim58046fa2017-07-05 16:55:00 -0700389 main.HA.isElectionFunctional( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700390
391 def CASE16( self, main ):
392 """
393 Install Distributed Primitives app
394 """
Devin Lim58046fa2017-07-05 16:55:00 -0700395 main.HA.installDistributedPrimitiveApp( main )
Jon Hall69b2b982016-05-11 12:04:59 -0700396
397 def CASE17( self, main ):
398 """
399 Check for basic functionality with distributed primitives
400 """
Devin Lim58046fa2017-07-05 16:55:00 -0700401 main.HA.checkDistPrimitivesFunc( main )