blob: 7e10a09bf6337e0da9df11ac173bbff67e300ea9 [file] [log] [blame]
Jon Hall6e709752016-02-01 13:38:46 -08001"""
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 Hall6e709752016-02-01 13:38:46 -080023Description: This test is to determine if ONOS can handle
24 a full network partion
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
33CASE61: The Failure inducing case.
34CASE62: The Failure recovery case.
35CASE7: Check state after control plane failure
36CASE8: Compare topo
37CASE9: Link s3-s28 down
38CASE10: Link s3-s28 up
39CASE11: Switch down
40CASE12: Switch up
41CASE13: Clean up
42CASE14: start election app on all onos nodes
43CASE15: Check that Leadership Election is still functional
44CASE16: Install Distributed Primitives app
45CASE17: Check for basic functionality with distributed primitives
46"""
Jon Hall6e709752016-02-01 13:38:46 -080047class HAfullNetPartition:
48
49 def __init__( self ):
50 self.default = ''
51
52 def CASE1( self, main ):
53 """
54 CASE1 is to compile ONOS and push it to the test machines
55
56 Startup sequence:
57 cell <name>
58 onos-verify-cell
59 NOTE: temporary - onos-remove-raft-logs
60 onos-uninstall
61 start mininet
62 git pull
63 mvn clean install
64 onos-package
65 onos-install -f
66 onos-wait-for-start
67 start cli sessions
68 start tcpdump
69 """
70 import imp
71 import pexpect
72 import time
Jon Halla440e872016-03-31 15:15:50 -070073 import json
Jon Hall6e709752016-02-01 13:38:46 -080074 main.log.info( "ONOS HA test: Partition ONOS nodes into two sub-clusters - " +
75 "initialization" )
Jon Hall6e709752016-02-01 13:38:46 -080076 # set global variables
Jon Halla440e872016-03-31 15:15:50 -070077 # These are for csv plotting in jenkins
Devin Lim58046fa2017-07-05 16:55:00 -070078 main.HAlabels = []
79 main.HAdata = []
80 try:
81 from tests.dependencies.ONOSSetup import ONOSSetup
82 main.testSetUp = ONOSSetup()
83 except ImportError:
84 main.log.error( "ONOSSetup not found. exiting the test" )
85 main.exit()
86 main.testSetUp.envSetupDescription()
Jon Hall6e709752016-02-01 13:38:46 -080087 try:
Jon Hall53c5e662016-04-13 16:06:56 -070088 from tests.HA.dependencies.HA import HA
Jon Hall41d39f12016-04-11 22:54:35 -070089 main.HA = HA()
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 Hall6e709752016-02-01 13:38:46 -080099 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( "HAfullNetPartition" )
Jon Hall6e709752016-02-01 13:38:46 -0800103
Devin Lim58046fa2017-07-05 16:55:00 -0700104 main.testSetUp.ONOSSetUp( main.Mininet1, cellName=cellName, removeLog=True,
105 extraApply=main.HA.customizeOnosGenPartitions,
106 extraClean=main.HA.cleanUpGenPartition )
Jon Hall6e709752016-02-01 13:38:46 -0800107
Devin Lim58046fa2017-07-05 16:55:00 -0700108 main.HA.initialSetUp()
Jon Hall6e709752016-02-01 13:38:46 -0800109
Jon Hall9d2dcad2016-04-08 10:15:20 -0700110
Jon Hall6e709752016-02-01 13:38:46 -0800111 def CASE2( self, main ):
112 """
113 Assign devices to controllers
114 """
Devin Lim58046fa2017-07-05 16:55:00 -0700115 main.HA.assignDevices( main )
Jon Hall6e709752016-02-01 13:38:46 -0800116
117 def CASE21( self, main ):
118 """
119 Assign mastership to controllers
120 """
Devin Lim58046fa2017-07-05 16:55:00 -0700121 main.HA.assignMastership( main )
Jon Hall6e709752016-02-01 13:38:46 -0800122
123 def CASE3( self, main ):
124 """
125 Assign intents
126 """
Devin Lim58046fa2017-07-05 16:55:00 -0700127 main.HA.assignIntents( main )
Jon Hall6e709752016-02-01 13:38:46 -0800128
129 def CASE4( self, main ):
130 """
131 Ping across added host intents
132 """
Jon Hallca319892017-06-15 15:25:22 -0700133 main.HA.pingAcrossHostIntent( main )
Jon Hall6e709752016-02-01 13:38:46 -0800134
135 def CASE5( self, main ):
136 """
137 Reading state of ONOS
138 """
Devin Lim58046fa2017-07-05 16:55:00 -0700139 main.HA.readingState( main )
Jon Hall6e709752016-02-01 13:38:46 -0800140
141 def CASE61( self, main ):
142 """
143 The Failure case.
144 """
145 import math
146 assert main.numCtrls, "main.numCtrls not defined"
147 assert main, "main not defined"
148 assert utilities.assert_equals, "utilities.assert_equals not defined"
149 assert main.CLIs, "main.CLIs not defined"
150 assert main.nodes, "main.nodes not defined"
151 main.case( "Partition ONOS nodes into two distinct partitions" )
152
153 main.step( "Checking ONOS Logs for errors" )
154 for node in main.nodes:
155 main.log.debug( "Checking logs for errors on " + node.name + ":" )
156 main.log.warn( main.ONOSbench.checkLogs( node.ip_address ) )
157
Jon Hallf37d44d2017-05-24 10:37:30 -0700158 main.log.debug( main.CLIs[ 0 ].roles( jsonFormat=False ) )
Jon Halld2871c22016-07-26 11:01:14 -0700159
Jon Hall6e709752016-02-01 13:38:46 -0800160 n = len( main.nodes ) # Number of nodes
161 p = ( ( n + 1 ) / 2 ) + 1 # Number of partitions
162 main.partition = [ 0 ] # ONOS node to partition, listed by index in main.nodes
163 if n > 3:
164 main.partition.append( p - 1 )
165 # NOTE: This only works for cluster sizes of 3,5, or 7.
166
167 main.step( "Partitioning ONOS nodes" )
168 nodeList = [ str( i + 1 ) for i in main.partition ]
169 main.log.info( "Nodes to be partitioned: " + str( nodeList ) )
170 partitionResults = main.TRUE
171 for i in range( 0, n ):
Jon Hallf37d44d2017-05-24 10:37:30 -0700172 this = main.nodes[ i ]
Jon Hall6e709752016-02-01 13:38:46 -0800173 if i not in main.partition:
174 for j in main.partition:
Jon Hallf37d44d2017-05-24 10:37:30 -0700175 foe = main.nodes[ j ]
Jon Hall6e709752016-02-01 13:38:46 -0800176 main.log.warn( "Setting IP Tables rule from {} to {}. ".format( this.ip_address, foe.ip_address ) )
177 #CMD HERE
178 cmdStr = "sudo iptables -A {} -d {} -s {} -j DROP".format( "INPUT", this.ip_address, foe.ip_address )
179 this.handle.sendline( cmdStr )
180 this.handle.expect( "\$" )
181 main.log.debug( this.handle.before )
182 else:
183 for j in range( 0, n ):
184 if j not in main.partition:
Jon Hallf37d44d2017-05-24 10:37:30 -0700185 foe = main.nodes[ j ]
Jon Hall6e709752016-02-01 13:38:46 -0800186 main.log.warn( "Setting IP Tables rule from {} to {}. ".format( this.ip_address, foe.ip_address ) )
187 #CMD HERE
188 cmdStr = "sudo iptables -A {} -d {} -s {} -j DROP".format( "INPUT", this.ip_address, foe.ip_address )
189 this.handle.sendline( cmdStr )
190 this.handle.expect( "\$" )
191 main.log.debug( this.handle.before )
192 main.activeNodes.remove( i )
193 # NOTE: When dynamic clustering is finished, we need to start checking
194 # main.partion nodes still work when partitioned
195 utilities.assert_equals( expect=main.TRUE, actual=partitionResults,
196 onpass="Firewall rules set successfully",
197 onfail="Error setting firewall rules" )
198
Jon Hall6509dbf2016-06-21 17:01:17 -0700199 main.step( "Sleeping 60 seconds" )
Jon Hall6e709752016-02-01 13:38:46 -0800200 time.sleep( 60 )
201
202 def CASE62( self, main ):
203 """
204 Healing Partition
205 """
206 import time
207 assert main.numCtrls, "main.numCtrls not defined"
208 assert main, "main not defined"
209 assert utilities.assert_equals, "utilities.assert_equals not defined"
210 assert main.CLIs, "main.CLIs not defined"
211 assert main.nodes, "main.nodes not defined"
212 assert main.partition, "main.partition not defined"
213 main.case( "Healing Partition" )
214
215 main.step( "Deleteing firewall rules" )
216 healResults = main.TRUE
217 for node in main.nodes:
218 cmdStr = "sudo iptables -F"
219 node.handle.sendline( cmdStr )
220 node.handle.expect( "\$" )
221 main.log.debug( node.handle.before )
222 utilities.assert_equals( expect=main.TRUE, actual=healResults,
223 onpass="Firewall rules removed",
224 onfail="Error removing firewall rules" )
225
226 for node in main.partition:
227 main.activeNodes.append( node )
228 main.activeNodes.sort()
229 try:
230 assert list( set( main.activeNodes ) ) == main.activeNodes,\
231 "List of active nodes has duplicates, this likely indicates something was run out of order"
232 except AssertionError:
233 main.log.exception( "" )
234 main.cleanup()
235 main.exit()
236
Jon Halld2871c22016-07-26 11:01:14 -0700237 main.step( "Checking ONOS nodes" )
238 nodeResults = utilities.retry( main.HA.nodesCheck,
239 False,
Jon Hallf37d44d2017-05-24 10:37:30 -0700240 args=[ main.activeNodes ],
Jon Halld2871c22016-07-26 11:01:14 -0700241 sleep=15,
242 attempts=5 )
243
244 utilities.assert_equals( expect=True, actual=nodeResults,
245 onpass="Nodes check successful",
246 onfail="Nodes check NOT successful" )
247
248 if not nodeResults:
249 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700250 cli = main.CLIs[ i ]
Jon Halld2871c22016-07-26 11:01:14 -0700251 main.log.debug( "{} components not ACTIVE: \n{}".format(
252 cli.name,
253 cli.sendline( "scr:list | grep -v ACTIVE" ) ) )
254 main.log.error( "Failed to start ONOS, stopping test" )
255 main.cleanup()
256 main.exit()
257
Jon Hall6e709752016-02-01 13:38:46 -0800258 def CASE7( self, main ):
259 """
260 Check state after ONOS failure
261 """
Jon Hall6e709752016-02-01 13:38:46 -0800262
Devin Lim58046fa2017-07-05 16:55:00 -0700263 main.HA.checkStateAfterONOS( main, afterWhich=0 )
Jon Hall6e709752016-02-01 13:38:46 -0800264
Jon Hall6e709752016-02-01 13:38:46 -0800265 main.step( "Leadership Election is still functional" )
266 # Test of LeadershipElection
267 leaderList = []
268
269 partitioned = []
270 for i in main.partition:
Jon Hallf37d44d2017-05-24 10:37:30 -0700271 partitioned.append( main.nodes[ i ].ip_address )
Jon Hall6e709752016-02-01 13:38:46 -0800272 leaderResult = main.TRUE
273
274 for i in main.activeNodes:
Jon Hallf37d44d2017-05-24 10:37:30 -0700275 cli = main.CLIs[ i ]
Jon Hall6e709752016-02-01 13:38:46 -0800276 leaderN = cli.electionTestLeader()
277 leaderList.append( leaderN )
278 if leaderN == main.FALSE:
279 # error in response
280 main.log.error( "Something is wrong with " +
281 "electionTestLeader function, check the" +
282 " error logs" )
283 leaderResult = main.FALSE
284 elif leaderN is None:
285 main.log.error( cli.name +
286 " shows no leader for the election-app was" +
287 " elected after the old one died" )
288 leaderResult = main.FALSE
289 elif leaderN in partitioned:
290 main.log.error( cli.name + " shows " + str( leaderN ) +
291 " as leader for the election-app, but it " +
292 "was partitioned" )
293 leaderResult = main.FALSE
294 if len( set( leaderList ) ) != 1:
295 leaderResult = main.FALSE
296 main.log.error(
297 "Inconsistent view of leader for the election test app" )
298 # TODO: print the list
299 utilities.assert_equals(
300 expect=main.TRUE,
301 actual=leaderResult,
302 onpass="Leadership election passed",
303 onfail="Something went wrong with Leadership election" )
304
305 def CASE8( self, main ):
306 """
307 Compare topo
308 """
Devin Lim58046fa2017-07-05 16:55:00 -0700309 main.HA.compareTopo( main )
Jon Halld2871c22016-07-26 11:01:14 -0700310
Jon Hall6e709752016-02-01 13:38:46 -0800311 def CASE9( self, main ):
312 """
313 Link s3-s28 down
314 """
Devin Lim58046fa2017-07-05 16:55:00 -0700315 main.HA.linkDown( main )
Jon Hall6e709752016-02-01 13:38:46 -0800316
317 def CASE10( self, main ):
318 """
319 Link s3-s28 up
320 """
Devin Lim58046fa2017-07-05 16:55:00 -0700321 main.HA.linkUp( main )
Jon Hall6e709752016-02-01 13:38:46 -0800322
323 def CASE11( self, main ):
324 """
325 Switch Down
326 """
327 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700328 main.HA.switchDown( main )
Jon Hall6e709752016-02-01 13:38:46 -0800329
330 def CASE12( self, main ):
331 """
332 Switch Up
333 """
334 # NOTE: You should probably run a topology check after this
Devin Lim58046fa2017-07-05 16:55:00 -0700335 main.HA.switchUp( main )
Jon Hall6e709752016-02-01 13:38:46 -0800336
337 def CASE13( self, main ):
338 """
339 Clean up
340 """
Devin Lim58046fa2017-07-05 16:55:00 -0700341 main.HA.cleanUp( main )
Jon Hall6e709752016-02-01 13:38:46 -0800342
343 def CASE14( self, main ):
344 """
345 start election app on all onos nodes
346 """
Devin Lim58046fa2017-07-05 16:55:00 -0700347 main.HA.startElectionApp( main )
Jon Hall6e709752016-02-01 13:38:46 -0800348
349 def CASE15( self, main ):
350 """
351 Check that Leadership Election is still functional
352 15.1 Run election on each node
353 15.2 Check that each node has the same leaders and candidates
354 15.3 Find current leader and withdraw
355 15.4 Check that a new node was elected leader
356 15.5 Check that that new leader was the candidate of old leader
357 15.6 Run for election on old leader
358 15.7 Check that oldLeader is a candidate, and leader if only 1 node
359 15.8 Make sure that the old leader was added to the candidate list
360
361 old and new variable prefixes refer to data from before vs after
362 withdrawl and later before withdrawl vs after re-election
363 """
Devin Lim58046fa2017-07-05 16:55:00 -0700364 main.HA.isElectionFunctional( main )
Jon Hall6e709752016-02-01 13:38:46 -0800365
366 def CASE16( self, main ):
367 """
368 Install Distributed Primitives app
369 """
Devin Lim58046fa2017-07-05 16:55:00 -0700370 main.HA.installDistributedPrimitiveApp( main )
Jon Hall6e709752016-02-01 13:38:46 -0800371
372 def CASE17( self, main ):
373 """
374 Check for basic functionality with distributed primitives
375 """
Devin Lim58046fa2017-07-05 16:55:00 -0700376 main.HA.checkDistPrimitivesFunc( main )