blob: 7c51b0a2d8e05423ae2bff125486af2372e4783e [file] [log] [blame]
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -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"""
Jon Hall1efcb3f2016-08-23 13:42:15 -070021import os
22import imp
23import time
24import json
25import urllib
26from core import utilities
27
28
29class Testcaselib:
Pierfb719b12016-09-19 14:51:44 -070030
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070031 useSSH = True
Pierfb719b12016-09-19 14:51:44 -070032
Jon Hall1efcb3f2016-08-23 13:42:15 -070033 @staticmethod
34 def initTest( main ):
35 """
36 - Construct tests variables
37 - GIT ( optional )
38 - Checkout ONOS master branch
39 - Pull latest ONOS code
40 - Building ONOS ( optional )
41 - Install ONOS package
42 - Build ONOS package
43 """
Devin Lim58046fa2017-07-05 16:55:00 -070044 try:
45 from tests.dependencies.ONOSSetup import ONOSSetup
46 main.testSetUp = ONOSSetup()
47 except ImportError:
48 main.log.error( "ONOSSetup not found. exiting the test" )
Devin Lim44075962017-08-11 10:56:37 -070049 main.cleanAndExit()
You Wangd5873482018-01-24 12:30:00 -080050 from tests.dependencies.Network import Network
51 main.Network = Network()
Devin Lim0c972b72018-02-08 14:53:59 -080052 main.testSetUp.envSetupDescription( False )
Devin Lim58046fa2017-07-05 16:55:00 -070053 stepResult = main.FALSE
54 try:
55 main.step( "Constructing test variables" )
56 # Test variables
57 main.cellName = main.params[ 'ENV' ][ 'cellName' ]
58 main.apps = main.params[ 'ENV' ][ 'cellApps' ]
Devin Lim58046fa2017-07-05 16:55:00 -070059 main.path = os.path.dirname( main.testFile )
Devin Lim57221b02018-02-14 15:45:36 -080060 main.useCommonTopo = main.params[ 'DEPENDENCY' ][ 'useCommonTopo' ] == 'True'
61 main.topoPath = main.path + ( "/.." if main.useCommonTopo else "" ) + "/dependencies/"
62 main.useCommonConf = main.params[ 'DEPENDENCY' ][ 'useCommonConf' ] == 'True'
63 main.configPath = main.path + ( "/.." if main.useCommonConf else "" ) + "/dependencies/"
64 main.forJson = "json/"
65 main.forChart = "chart/"
66 main.forConfig = "conf/"
67 main.forHost = "host/"
Devin Lim58046fa2017-07-05 16:55:00 -070068 main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
You Wangd87b2312018-01-30 12:47:17 -080069 main.topologyLib = main.params[ 'DEPENDENCY' ][ 'lib' ] if 'lib' in main.params[ 'DEPENDENCY' ] else None
70 main.topologyConf = main.params[ 'DEPENDENCY' ][ 'conf' ] if 'conf' in main.params[ 'DEPENDENCY' ] else None
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070071 main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
Devin Lim58046fa2017-07-05 16:55:00 -070072 main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
Devin Lim58046fa2017-07-05 16:55:00 -070073 main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
Jon Hall1efcb3f2016-08-23 13:42:15 -070074
Devin Lim0c972b72018-02-08 14:53:59 -080075 stepResult = main.testSetUp.envSetup( False )
Devin Lim58046fa2017-07-05 16:55:00 -070076 except Exception as e:
77 main.testSetUp.envSetupException( e )
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -070078
Devin Lim58046fa2017-07-05 16:55:00 -070079 main.testSetUp.evnSetupConclusion( stepResult )
Jon Hall1efcb3f2016-08-23 13:42:15 -070080
Jon Hall1efcb3f2016-08-23 13:42:15 -070081 @staticmethod
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080082 def installOnos( main, vlanCfg=True, skipPackage=False, cliSleep=10,
83 parallel=True ):
Jon Hall1efcb3f2016-08-23 13:42:15 -070084 """
85 - Set up cell
86 - Create cell file
87 - Set cell file
88 - Verify cell file
89 - Kill ONOS process
90 - Uninstall ONOS cluster
91 - Verify ONOS start up
92 - Install ONOS cluster
93 - Connect to cli
94 """
95 # main.scale[ 0 ] determines the current number of ONOS controller
You Wangd87b2312018-01-30 12:47:17 -080096 if not main.apps:
Jon Hall1efcb3f2016-08-23 13:42:15 -070097 main.log.error( "App list is empty" )
Devin Lim142b5342017-07-20 15:22:39 -070098 main.log.info( "NODE COUNT = " + str( main.Cluster.numCtrls ) )
99 main.log.info( ''.join( main.Cluster.getIps() ) )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700100 main.dynamicHosts = [ 'in1', 'out1' ]
You Wanga0f6ff62018-01-11 15:46:30 -0800101 main.testSetUp.ONOSSetUp( main.Cluster, newCell=True, cellName=main.cellName,
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800102 skipPack=skipPackage,
103 useSSH=Testcaselib.useSSH,
Devin Lim0c972b72018-02-08 14:53:59 -0800104 installParallel=parallel, includeCaseDesc=False )
Devin Lim142b5342017-07-20 15:22:39 -0700105 ready = utilities.retry( main.Cluster.active( 0 ).CLI.summary,
106 main.FALSE,
You Wang1cdc5f52017-12-19 16:47:51 -0800107 sleep=cliSleep,
Devin Lim142b5342017-07-20 15:22:39 -0700108 attempts=10 )
109 if ready:
110 ready = main.TRUE
111 utilities.assert_equals( expect=main.TRUE, actual=ready,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700112 onpass="ONOS summary command succeded",
113 onfail="ONOS summary command failed" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700114 if not ready:
115 main.log.error( "ONOS startup failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700116 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700117
Devin Lim142b5342017-07-20 15:22:39 -0700118 for ctrl in main.Cluster.active():
119 ctrl.CLI.logSet( "DEBUG", "org.onosproject.segmentrouting" )
120 ctrl.CLI.logSet( "DEBUG", "org.onosproject.driver.pipeline" )
121 ctrl.CLI.logSet( "DEBUG", "org.onosproject.store.group.impl" )
122 ctrl.CLI.logSet( "DEBUG", "org.onosproject.net.flowobjective.impl" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700123
124 @staticmethod
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800125 def loadCount( main ):
126 with open("%s/count/%s.count" % (main.configPath, main.cfgName)) as count:
127 main.count = json.load(count)
128
129 @staticmethod
Devin Lim57221b02018-02-14 15:45:36 -0800130 def loadJson( main ):
131 with open( "%s%s.json" % ( main.configPath + main.forJson,
132 main.cfgName ) ) as cfg:
133 main.Cluster.active( 0 ).REST.setNetCfg( json.load( cfg ) )
134
135 @staticmethod
136 def loadChart( main ):
137 try:
138 with open( "%s%s.chart" % ( main.configPath + main.forChart,
139 main.cfgName ) ) as chart:
140 main.pingChart = json.load(chart)
141 except IOError:
142 main.log.warn( "No chart file found." )
143
144 @staticmethod
145 def loadHost( main ):
146 with open( "%s%s.host" % ( main.configPath + main.forHost,
147 main.cfgName ) ) as host:
148 main.expectedHosts = json.load( host )
149
150 @staticmethod
Jon Hall1efcb3f2016-08-23 13:42:15 -0700151 def startMininet( main, topology, args="" ):
You Wangd87b2312018-01-30 12:47:17 -0800152 copyResult = main.ONOSbench.scp( main.Mininet1,
153 main.topoPath + main.topology,
154 main.Mininet1.home,
155 direction="to" )
156 if main.topologyLib:
157 for lib in main.topologyLib.split(","):
158 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
159 main.topoPath + lib,
160 main.Mininet1.home,
161 direction="to" )
162 if main.topologyConf:
163 for conf in main.topologyConf.split(","):
164 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
Devin Lim57221b02018-02-14 15:45:36 -0800165 main.configPath + main.forConfig + conf,
You Wangd87b2312018-01-30 12:47:17 -0800166 "~/",
167 direction="to" )
168 stepResult = copyResult
169 utilities.assert_equals( expect=main.TRUE,
170 actual=stepResult,
171 onpass="Successfully copied topo files",
172 onfail="Failed to copy topo files" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700173 main.step( "Starting Mininet Topology" )
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -0700174 arg = "--onos-ip=%s %s" % (",".join([ctrl.ipAddress for ctrl in main.Cluster.runningNodes]), args)
Jon Hall1efcb3f2016-08-23 13:42:15 -0700175 main.topology = topology
176 topoResult = main.Mininet1.startNet(
177 topoFile=main.Mininet1.home + main.topology, args=arg )
178 stepResult = topoResult
179 utilities.assert_equals( expect=main.TRUE,
180 actual=stepResult,
181 onpass="Successfully loaded topology",
182 onfail="Failed to load topology" )
183 # Exit if topology did not load properly
184 if not topoResult:
Devin Lim44075962017-08-11 10:56:37 -0700185 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700186
187 @staticmethod
You Wang84f981d2018-01-12 16:11:50 -0800188 def connectToPhysicalNetwork( main, switchNames ):
189 main.step( "Connecting to physical netowrk" )
190 topoResult = main.NetworkBench.connectToNet()
191 stepResult = topoResult
192 utilities.assert_equals( expect=main.TRUE,
193 actual=stepResult,
194 onpass="Successfully loaded topology",
195 onfail="Failed to load topology" )
196 # Exit if topology did not load properly
197 if not topoResult:
198 main.cleanAndExit()
199
200 main.step( "Assign switches to controllers." )
201 assignResult = main.TRUE
202 for name in switchNames:
203 assignResult = assignResult & main.NetworkBench.assignSwController( sw=name,
204 ip=main.Cluster.getIps(),
205 port='6653' )
206 utilities.assert_equals( expect=main.TRUE,
207 actual=stepResult,
208 onpass="Successfully assign switches to controllers",
209 onfail="Failed to assign switches to controllers" )
210
211 @staticmethod
Devin Lim142b5342017-07-20 15:22:39 -0700212 def config( main, cfgName ):
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700213 main.spines = []
Piera2a7e1b2016-10-04 11:51:43 -0700214
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700215 main.failures = int( main.params[ 'failures' ] )
216 main.cfgName = cfgName
Piera2a7e1b2016-10-04 11:51:43 -0700217
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700218 if main.cfgName == '2x2':
219 spine = {}
220 spine[ 'name' ] = main.params[ 'switches' ][ 'spine1' ]
221 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid1' ]
222 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700223
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700224 spine = {}
225 spine[ 'name' ] = main.params[ 'switches' ][ 'spine2' ]
226 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid2' ]
227 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700228
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700229 elif main.cfgName == '4x4':
230 spine = {}
231 spine[ 'name' ] = main.params[ 'switches' ][ 'spine1' ]
232 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid1' ]
233 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700234
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700235 spine = {}
236 spine[ 'name' ] = main.params[ 'switches' ][ 'spine2' ]
237 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid2' ]
238 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700239
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700240 spine = {}
241 spine[ 'name' ] = main.params[ 'switches' ][ 'spine3' ]
242 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid3' ]
243 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700244
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700245 spine = {}
246 spine[ 'name' ] = main.params[ 'switches' ][ 'spine4' ]
247 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid4' ]
248 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700249
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700250 else:
Piera2a7e1b2016-10-04 11:51:43 -0700251 main.log.error( "Configuration failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700252 main.cleanAndExit()
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -0800253
254 @staticmethod
255 def addStaticOnosRoute( main, subnet, intf):
256 """
257 Adds an ONOS static route with the use route-add command.
258 """
259 main.step("Add static route for subnet {0} towards router interface {1}".format(subnet, intf))
260 routeResult = main.Cluster.active( 0 ).addStaticRoute(subnet, intf)
261
262 utilities.assert_equals( expect=True, actual=( not routeResult ),
263 onpass="route-add command succeeded",
264 onfail="route-add command failed")
Piera2a7e1b2016-10-04 11:51:43 -0700265
266 @staticmethod
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900267 def checkFlows( main, minFlowCount, tag="", dumpflows=True, sleep=10 ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700268 main.step(
269 " Check whether the flow count is bigger than %s" % minFlowCount )
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900270 if tag == "":
271 tag = 'CASE%d' % main.CurrentTestCaseNumber
Devin Lim142b5342017-07-20 15:22:39 -0700272 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowCount,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700273 main.FALSE,
274 kwargs={ 'min': minFlowCount },
275 attempts=10,
You Wang1cdc5f52017-12-19 16:47:51 -0800276 sleep=sleep )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700277 utilities.assertEquals(
Jon Hall1efcb3f2016-08-23 13:42:15 -0700278 expect=True,
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700279 actual=( count > 0 ),
Jon Hall1efcb3f2016-08-23 13:42:15 -0700280 onpass="Flow count looks correct: " + str( count ),
281 onfail="Flow count looks wrong: " + str( count ) )
282
283 main.step( "Check whether all flow status are ADDED" )
Devin Lim142b5342017-07-20 15:22:39 -0700284 flowCheck = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowsState,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700285 main.FALSE,
286 kwargs={ 'isPENDING': False },
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800287 attempts=5,
You Wang1cdc5f52017-12-19 16:47:51 -0800288 sleep=sleep )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700289 utilities.assertEquals(
Jon Hall1efcb3f2016-08-23 13:42:15 -0700290 expect=main.TRUE,
291 actual=flowCheck,
292 onpass="Flow status is correct!",
293 onfail="Flow status is wrong!" )
294 if dumpflows:
Devin Lim142b5342017-07-20 15:22:39 -0700295 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
Pier50f0bc62016-09-07 17:53:40 -0700296 "flows",
297 main.logdir,
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900298 tag + "_FlowsBefore" )
Devin Lim142b5342017-07-20 15:22:39 -0700299 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
Pier50f0bc62016-09-07 17:53:40 -0700300 "groups",
301 main.logdir,
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900302 tag + "_GroupsBefore" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700303
304 @staticmethod
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800305 def checkFlowsByDpid( main, dpid, minFlowCount, sleep=10 ):
306 main.step(
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800307 " Check whether the flow count of device %s is bigger than %s" % ( dpid, minFlowCount ) )
308 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
309 main.FALSE,
310 args=( dpid, minFlowCount ),
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800311 attempts=5,
312 sleep=sleep )
313 utilities.assertEquals(
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800314 expect=True,
315 actual=( count > minFlowCount ),
316 onpass="Flow count looks correct: " + str( count ),
317 onfail="Flow count looks wrong. " )
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800318
319 @staticmethod
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800320 def checkFlowEqualityByDpid( main, dpid, flowCount, sleep=10):
321 main.step(
322 " Check whether the flow count of device %s is equal to %s" % ( dpid, flowCount ) )
323 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
324 main.FALSE,
325 args=( dpid, flowCount, False, 1),
326 attempts=5,
327 sleep=sleep )
328
329 utilities.assertEquals(
330 expect=True,
331 actual=( int( count ) == flowCount ),
332 onpass="Flow count looks correct: " + str(count) ,
333 onfail="Flow count looks wrong, should be " + str(flowCount))
334
335 @staticmethod
336 def checkGroupEqualityByDpid( main, dpid, groupCount, sleep=10):
337 main.step(
338 " Check whether the group count of device %s is equal to %s" % ( dpid, groupCount ) )
339 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkGroupAddedCount,
340 main.FALSE,
341 args=( dpid, groupCount, False, 1),
342 attempts=5,
343 sleep=sleep )
344
345 utilities.assertEquals(
346 expect=True,
347 actual=( count == groupCount ),
348 onpass="Group count looks correct: " + str(count) ,
349 onfail="Group count looks wrong: should be " + str(groupCount))
350
351 @staticmethod
352 def checkFlowsGroupsFromFile(main):
353
354 for dpid, values in main.count.items():
355 flowCount = values["flows"]
356 groupCount = values["groups"]
357 main.log.report( "Check flow count for dpid " + str(dpid) +
358 ", should be " + str(flowCount))
359 Testcaselib.checkFlowEqualityByDpid(main, dpid, flowCount)
360
361 main.log.report( "Check group count for dpid " + str(dpid) +
362 ", should be " + str(groupCount))
363 Testcaselib.checkGroupEqualityByDpid(main, dpid, groupCount)
364
365 return
366
367 @staticmethod
You Wangf19d9f42018-02-23 16:34:19 -0800368 def pingAll( main, tag="", dumpflows=True, acceptableFailed=0, basedOnIp=False ):
369 '''
You Wangba231e72018-03-01 13:18:21 -0800370 Verify connectivity between hosts according to the ping chart
371 acceptableFailed: max number of acceptable failed pings.
You Wangf19d9f42018-02-23 16:34:19 -0800372 basedOnIp: if True, run ping or ping6 based on suffix of host names
373 '''
You Wangba231e72018-03-01 13:18:21 -0800374 main.log.report( "Check host connectivity" )
375 main.log.debug( "Ping chart: %s" % main.pingChart )
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800376 if tag == "":
377 tag = 'CASE%d' % main.CurrentTestCaseNumber
378 for entry in main.pingChart.itervalues():
You Wangba231e72018-03-01 13:18:21 -0800379 main.log.debug( "Entry in ping chart: %s" % entry )
380 expect = entry[ 'expect' ]
381 if expect == "Unidirectional":
382 # Verify ping from each src host to each dst host
383 src = entry[ 'src' ]
384 dst = entry[ 'dst' ]
385 expect = main.TRUE
386 main.step( "Verify unidirectional connectivity from %s to %s with tag %s" % ( str( src ), str( dst ), tag ) )
387 if basedOnIp:
388 if ("v4" in src[0]):
389 pa = main.Network.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed )
390 utilities.assert_equals( expect=expect, actual=pa,
391 onpass="IPv4 connectivity successfully tested",
392 onfail="IPv4 connectivity failed" )
393 if ("v6" in src[0]):
394 pa = main.Network.pingallHostsUnidirectional( src, dst, ipv6=True, acceptableFailed=acceptableFailed )
395 utilities.assert_equals( expect=expect, actual=pa,
396 onpass="IPv6 connectivity successfully tested",
397 onfail="IPv6 connectivity failed" )
398 else:
399 pa = main.Network.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed )
400 utilities.assert_equals( expect=expect, actual=pa,
401 onpass="IP connectivity successfully tested",
402 onfail="IP connectivity failed" )
403 else:
404 # Verify ping between each host pair
405 hosts = entry[ 'hosts' ]
406 try:
407 expect = main.TRUE if str(expect).lower() == 'true' else main.FALSE
408 except:
409 expect = main.FALSE
410 main.step( "Verify full connectivity for %s with tag %s" % ( str( hosts ), tag ) )
411 if basedOnIp:
412 if ("v4" in hosts[0]):
413 pa = main.Network.pingallHosts( hosts )
414 utilities.assert_equals( expect=expect, actual=pa,
415 onpass="IPv4 connectivity successfully tested",
416 onfail="IPv4 connectivity failed" )
417 if ("v6" in hosts[0]):
418 pa = main.Network.pingIpv6Hosts( hosts, acceptableFailed=acceptableFailed )
419 utilities.assert_equals( expect=expect, actual=pa,
420 onpass="IPv6 connectivity successfully tested",
421 onfail="IPv6 connectivity failed" )
422 else:
You Wangf19d9f42018-02-23 16:34:19 -0800423 pa = main.Network.pingallHosts( hosts )
424 utilities.assert_equals( expect=expect, actual=pa,
You Wangba231e72018-03-01 13:18:21 -0800425 onpass="IP connectivity successfully tested",
426 onfail="IP connectivity failed" )
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800427
428 if dumpflows:
429 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
430 "flows",
431 main.logdir,
432 tag + "_FlowsOn" )
433 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
434 "groups",
435 main.logdir,
436 tag + "_GroupsOn" )
437
438 @staticmethod
Jon Hall1efcb3f2016-08-23 13:42:15 -0700439 def killLink( main, end1, end2, switches, links ):
440 """
441 end1,end2: identify the switches, ex.: 'leaf1', 'spine1'
442 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
443 Kill a link and verify ONOS can see the proper link change
444 """
445 main.linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700446 main.step( "Kill link between %s and %s" % ( end1, end2 ) )
You Wangd5873482018-01-24 12:30:00 -0800447 LinkDown = main.Network.link( END1=end1, END2=end2, OPTION="down" )
448 LinkDown = main.Network.link( END2=end1, END1=end2, OPTION="down" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700449 main.log.info(
450 "Waiting %s seconds for link down to be discovered" % main.linkSleep )
451 time.sleep( main.linkSleep )
Devin Lim142b5342017-07-20 15:22:39 -0700452 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700453 main.FALSE,
454 kwargs={ 'numoswitch': switches,
455 'numolink': links },
456 attempts=10,
457 sleep=main.linkSleep )
458 result = topology & LinkDown
459 utilities.assert_equals( expect=main.TRUE, actual=result,
460 onpass="Link down successful",
461 onfail="Failed to turn off link?" )
462
463 @staticmethod
464 def restoreLink( main, end1, end2, dpid1, dpid2, port1, port2, switches,
465 links ):
466 """
467 Params:
468 end1,end2: identify the end switches, ex.: 'leaf1', 'spine1'
469 dpid1, dpid2: dpid of the end switches respectively, ex.: 'of:0000000000000002'
470 port1, port2: respective port of the end switches that connects to the link, ex.:'1'
471 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
472 Kill a link and verify ONOS can see the proper link change
473 """
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700474 main.step( "Restore link between %s and %s" % ( end1, end2 ) )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700475 result = False
476 count = 0
477 while True:
478 count += 1
You Wangd5873482018-01-24 12:30:00 -0800479 main.Network.link( END1=end1, END2=end2, OPTION="up" )
480 main.Network.link( END2=end1, END1=end2, OPTION="up" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700481 main.log.info(
482 "Waiting %s seconds for link up to be discovered" % main.linkSleep )
483 time.sleep( main.linkSleep )
Pierfb719b12016-09-19 14:51:44 -0700484
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700485 for i in range( 0, main.Cluster.numCtrls ):
Devin Lim142b5342017-07-20 15:22:39 -0700486 ctrl = main.Cluster.runningNodes[ i ]
487 onosIsUp = main.ONOSbench.isup( ctrl.ipAddress )
Pierfb719b12016-09-19 14:51:44 -0700488 if onosIsUp == main.TRUE:
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900489 ctrl.CLI.portstate( dpid=dpid1, port=port1, state='Enable' )
490 ctrl.CLI.portstate( dpid=dpid2, port=port2, state='Enable' )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700491 time.sleep( main.linkSleep )
492
Devin Lim142b5342017-07-20 15:22:39 -0700493 result = main.Cluster.active( 0 ).CLI.checkStatus( numoswitch=switches,
494 numolink=links )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700495 if count > 5 or result:
496 break
497 utilities.assert_equals( expect=main.TRUE, actual=result,
498 onpass="Link up successful",
499 onfail="Failed to bring link up" )
500
501 @staticmethod
502 def killSwitch( main, switch, switches, links ):
503 """
504 Params: switches, links: number of expected switches and links after SwitchDown, ex.: '4', '6'
505 Completely kill a switch and verify ONOS can see the proper change
506 """
507 main.switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
508 main.step( "Kill " + switch )
509 main.log.info( "Stopping" + switch )
You Wangd5873482018-01-24 12:30:00 -0800510 main.Network.switch( SW=switch, OPTION="stop" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700511 # todo make this repeatable
512 main.log.info( "Waiting %s seconds for switch down to be discovered" % (
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700513 main.switchSleep ) )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700514 time.sleep( main.switchSleep )
Devin Lim142b5342017-07-20 15:22:39 -0700515 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700516 main.FALSE,
517 kwargs={ 'numoswitch': switches,
518 'numolink': links },
519 attempts=10,
520 sleep=main.switchSleep )
521 utilities.assert_equals( expect=main.TRUE, actual=topology,
522 onpass="Kill switch successful",
523 onfail="Failed to kill switch?" )
524
525 @staticmethod
526 def recoverSwitch( main, switch, switches, links ):
527 """
528 Params: switches, links: number of expected switches and links after SwitchUp, ex.: '4', '6'
529 Recover a switch and verify ONOS can see the proper change
530 """
531 # todo make this repeatable
532 main.step( "Recovering " + switch )
533 main.log.info( "Starting" + switch )
You Wangd5873482018-01-24 12:30:00 -0800534 main.Network.switch( SW=switch, OPTION="start" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700535 main.log.info( "Waiting %s seconds for switch up to be discovered" % (
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700536 main.switchSleep ) )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700537 time.sleep( main.switchSleep )
Devin Lim142b5342017-07-20 15:22:39 -0700538 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700539 main.FALSE,
540 kwargs={ 'numoswitch': switches,
541 'numolink': links },
542 attempts=10,
543 sleep=main.switchSleep )
544 utilities.assert_equals( expect=main.TRUE, actual=topology,
545 onpass="Switch recovery successful",
546 onfail="Failed to recover switch?" )
547
548 @staticmethod
549 def cleanup( main ):
550 """
551 Stop Onos-cluster.
552 Stops Mininet
553 Copies ONOS log
554 """
Devin Lim58046fa2017-07-05 16:55:00 -0700555 try:
556 from tests.dependencies.utils import Utils
557 except ImportError:
558 main.log.error( "Utils not found exiting the test" )
Devin Lim44075962017-08-11 10:56:37 -0700559 main.cleanAndExit()
Devin Lim58046fa2017-07-05 16:55:00 -0700560 try:
Devin Lim142b5342017-07-20 15:22:39 -0700561 main.utils
Devin Lim58046fa2017-07-05 16:55:00 -0700562 except ( NameError, AttributeError ):
Devin Lim142b5342017-07-20 15:22:39 -0700563 main.utils = Utils()
Devin Lim58046fa2017-07-05 16:55:00 -0700564
565 main.utils.mininetCleanup( main.Mininet1 )
566
Devin Lim0c972b72018-02-08 14:53:59 -0800567 main.utils.copyKarafLog( "CASE%d" % main.CurrentTestCaseNumber, before=True, includeCaseDesc=False )
Devin Lim58046fa2017-07-05 16:55:00 -0700568
Devin Lim142b5342017-07-20 15:22:39 -0700569 for ctrl in main.Cluster.active():
570 main.ONOSbench.onosStop( ctrl.ipAddress )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700571
572 @staticmethod
573 def killOnos( main, nodes, switches, links, expNodes ):
574 """
575 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
576 switches, links, nodes: number of expected switches, links and nodes after KillOnos, ex.: '4', '6'
577 Completely Kill an ONOS instance and verify the ONOS cluster can see the proper change
578 """
579 main.step( "Killing ONOS instance" )
Pier3b58c652016-09-26 12:03:31 -0700580
Jon Hall1efcb3f2016-08-23 13:42:15 -0700581 for i in nodes:
Devin Lim142b5342017-07-20 15:22:39 -0700582 killResult = main.ONOSbench.onosDie( main.Cluster.runningNodes[ i ].ipAddress )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700583 utilities.assert_equals( expect=main.TRUE, actual=killResult,
584 onpass="ONOS instance Killed",
585 onfail="Error killing ONOS instance" )
Devin Lim142b5342017-07-20 15:22:39 -0700586 main.Cluster.runningNodes[ i ].active = False
Jon Hall1efcb3f2016-08-23 13:42:15 -0700587 time.sleep( 12 )
Pier3b58c652016-09-26 12:03:31 -0700588
Devin Lim142b5342017-07-20 15:22:39 -0700589 if len( nodes ) < main.Cluster.numCtrls:
Pier3b58c652016-09-26 12:03:31 -0700590
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -0700591 nodeResults = utilities.retry( main.Cluster.nodesCheck,
Pier3b58c652016-09-26 12:03:31 -0700592 False,
Pier3b58c652016-09-26 12:03:31 -0700593 attempts=5,
594 sleep=10 )
595 utilities.assert_equals( expect=True, actual=nodeResults,
596 onpass="Nodes check successful",
597 onfail="Nodes check NOT successful" )
598
599 if not nodeResults:
600 for i in nodes:
Devin Lim142b5342017-07-20 15:22:39 -0700601 ctrl = main.Cluster.runningNodes[ i ]
Pier3b58c652016-09-26 12:03:31 -0700602 main.log.debug( "{} components not ACTIVE: \n{}".format(
Devin Lim142b5342017-07-20 15:22:39 -0700603 ctrl.name,
604 ctrl.CLI.sendline( "scr:list | grep -v ACTIVE" ) ) )
Pier3b58c652016-09-26 12:03:31 -0700605 main.log.error( "Failed to kill ONOS, stopping test" )
Devin Lim44075962017-08-11 10:56:37 -0700606 main.cleanAndExit()
Pier3b58c652016-09-26 12:03:31 -0700607
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900608 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700609 main.FALSE,
610 kwargs={ 'numoswitch': switches,
611 'numolink': links,
612 'numoctrl': expNodes },
613 attempts=10,
614 sleep=12 )
615 utilities.assert_equals( expect=main.TRUE, actual=topology,
616 onpass="ONOS Instance down successful",
617 onfail="Failed to turn off ONOS Instance" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700618
619 @staticmethod
620 def recoverOnos( main, nodes, switches, links, expNodes ):
621 """
622 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
623 switches, links, nodes: number of expected switches, links and nodes after recoverOnos, ex.: '4', '6'
624 Recover an ONOS instance and verify the ONOS cluster can see the proper change
625 """
626 main.step( "Recovering ONOS instance" )
Devin Lim142b5342017-07-20 15:22:39 -0700627 [ main.ONOSbench.onosStart( main.Cluster.runningNodes[ i ].ipAddress ) for i in nodes ]
Jon Hall1efcb3f2016-08-23 13:42:15 -0700628 for i in nodes:
Devin Lim142b5342017-07-20 15:22:39 -0700629 isUp = main.ONOSbench.isup( main.Cluster.runningNodes[ i ].ipAddress )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700630 utilities.assert_equals( expect=main.TRUE, actual=isUp,
631 onpass="ONOS service is ready",
632 onfail="ONOS service did not start properly" )
633 for i in nodes:
634 main.step( "Checking if ONOS CLI is ready" )
Devin Lim142b5342017-07-20 15:22:39 -0700635 ctrl = main.Cluster.runningNodes[ i ]
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900636 # ctrl.CLI.startCellCli()
Devin Lim142b5342017-07-20 15:22:39 -0700637 cliResult = ctrl.CLI.startOnosCli( ctrl.ipAddress,
638 commandlineTimeout=60,
639 onosStartTimeout=100 )
640 ctrl.active = True
Jon Hall1efcb3f2016-08-23 13:42:15 -0700641 utilities.assert_equals( expect=main.TRUE,
642 actual=cliResult,
643 onpass="ONOS CLI is ready",
644 onfail="ONOS CLI is not ready" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700645
Pier3b58c652016-09-26 12:03:31 -0700646 main.step( "Checking ONOS nodes" )
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -0700647 nodeResults = utilities.retry( main.Cluster.nodesCheck,
Pier3b58c652016-09-26 12:03:31 -0700648 False,
Pier3b58c652016-09-26 12:03:31 -0700649 attempts=5,
650 sleep=10 )
651 utilities.assert_equals( expect=True, actual=nodeResults,
652 onpass="Nodes check successful",
653 onfail="Nodes check NOT successful" )
654
655 if not nodeResults:
656 for i in nodes:
Devin Lim142b5342017-07-20 15:22:39 -0700657 ctrl = main.Cluster.runningNodes[ i ]
Pier3b58c652016-09-26 12:03:31 -0700658 main.log.debug( "{} components not ACTIVE: \n{}".format(
Devin Lim142b5342017-07-20 15:22:39 -0700659 ctrl.name,
660 ctrl.CLI.sendline( "scr:list | grep -v ACTIVE" ) ) )
Pier3b58c652016-09-26 12:03:31 -0700661 main.log.error( "Failed to start ONOS, stopping test" )
Devin Lim44075962017-08-11 10:56:37 -0700662 main.cleanAndExit()
Pier3b58c652016-09-26 12:03:31 -0700663
Devin Lim142b5342017-07-20 15:22:39 -0700664 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700665 main.FALSE,
666 kwargs={ 'numoswitch': switches,
667 'numolink': links,
668 'numoctrl': expNodes },
669 attempts=10,
670 sleep=12 )
671 utilities.assert_equals( expect=main.TRUE, actual=topology,
672 onpass="ONOS Instance down successful",
673 onfail="Failed to turn off ONOS Instance" )
Devin Lim142b5342017-07-20 15:22:39 -0700674 ready = utilities.retry( main.Cluster.active( 0 ).CLI.summary,
675 main.FALSE,
676 attempts=10,
677 sleep=12 )
678 if ready:
679 ready = main.TRUE
680 utilities.assert_equals( expect=main.TRUE, actual=ready,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700681 onpass="ONOS summary command succeded",
682 onfail="ONOS summary command failed" )
683 if not ready:
684 main.log.error( "ONOS startup failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700685 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700686
687 @staticmethod
688 def addHostCfg( main ):
689 """
690 Adds Host Configuration to ONOS
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700691 Updates expected state of the network ( pingChart )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700692 """
693 import json
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700694 hostCfg = {}
Devin Lim57221b02018-02-14 15:45:36 -0800695 with open( main.configPath + main.forJson + "extra.json" ) as template:
Jon Hall1efcb3f2016-08-23 13:42:15 -0700696 hostCfg = json.load( template )
697 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'in1' ]
698 main.step( "Pushing new configuration" )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700699 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -0700700 main.Cluster.active( 0 ).REST.setNetCfg( cfg[ 'basic' ],
701 subjectClass="hosts",
702 subjectKey=urllib.quote( mac,
703 safe='' ),
704 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700705 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'out1' ]
706 main.step( "Pushing new configuration" )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700707 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -0700708 main.Cluster.active( 0 ).REST.setNetCfg( cfg[ 'basic' ],
709 subjectClass="hosts",
710 subjectKey=urllib.quote( mac,
711 safe='' ),
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700712 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700713 main.pingChart.update( { 'vlan1': { "expect": "True",
714 "hosts": [ "olt1", "vsg1" ] } } )
715 main.pingChart[ 'vlan5' ][ 'expect' ] = 0
716 main.pingChart[ 'vlan10' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700717 ports = "[%s,%s]" % ( 5, 6 )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700718 cfg = '{"of:0000000000000001":[{"vlan":1,"ports":%s,"name":"OLT 1"}]}' % ports
Devin Lim142b5342017-07-20 15:22:39 -0700719 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( cfg ),
720 subjectClass="apps",
721 subjectKey="org.onosproject.segmentrouting",
722 configKey="xconnect" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700723
724 @staticmethod
725 def delHostCfg( main ):
726 """
727 Removest Host Configuration from ONOS
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700728 Updates expected state of the network ( pingChart )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700729 """
730 import json
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700731 hostCfg = {}
Devin Lim57221b02018-02-14 15:45:36 -0800732 with open( main.configPath + main.forJson + "extra.json" ) as template:
Jon Hall1efcb3f2016-08-23 13:42:15 -0700733 hostCfg = json.load( template )
734 main.step( "Removing host configuration" )
735 main.pingChart[ 'ip' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700736 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -0700737 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="hosts",
738 subjectKey=urllib.quote(
739 mac,
740 safe='' ),
741 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700742 main.step( "Removing configuration" )
743 main.pingChart[ 'ip' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700744 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -0700745 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="hosts",
746 subjectKey=urllib.quote(
747 mac,
748 safe='' ),
749 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700750 main.step( "Removing vlan configuration" )
751 main.pingChart[ 'vlan1' ][ 'expect' ] = 0
Devin Lim142b5342017-07-20 15:22:39 -0700752 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="apps",
753 subjectKey="org.onosproject.segmentrouting",
754 configKey="xconnect" )
You Wang53dba1e2018-02-02 17:45:44 -0800755
756 @staticmethod
757 def verifyNetworkHostIp( main, attempts=10, sleep=10 ):
758 """
759 Verifies IP address assignment from the hosts
760 """
761 main.step( "Verify IP address assignment from hosts" )
762 ipResult = main.TRUE
763 for hostName, ip in main.expectedHosts[ "network" ].items():
764 ipResult = ipResult and utilities.retry( main.Network.verifyHostIp,
765 main.FALSE,
766 kwargs={ 'hostList': [ hostName ],
767 'prefix': ip },
768 attempts=attempts,
769 sleep=sleep )
770 utilities.assert_equals( expect=main.TRUE, actual=ipResult,
771 onpass="Verify network host IP succeded",
772 onfail="Verify network host IP failed" )
773
774 @staticmethod
775 def verifyOnosHostIp( main, attempts=10, sleep=10 ):
776 """
777 Verifies host IP address assignment from ONOS
778 """
779 main.step( "Verify host IP address assignment in ONOS" )
780 ipResult = main.TRUE
781 for hostName, ip in main.expectedHosts[ "onos" ].items():
782 ipResult = ipResult and utilities.retry( main.Cluster.active( 0 ).verifyHostIp,
783 main.FALSE,
784 kwargs={ 'hostList': [ hostName ],
785 'prefix': ip },
786 attempts=attempts,
787 sleep=sleep )
788 utilities.assert_equals( expect=main.TRUE, actual=ipResult,
789 onpass="Verify ONOS host IP succeded",
790 onfail="Verify ONOS host IP failed" )
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -0800791