blob: 08d190aca56e9c4e64b2a58454c7a6af49f0a9a7 [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
Jon Hall1efcb3f2016-08-23 13:42:15 -070022import time
23import json
24import urllib
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -070025import re
Jon Hall1efcb3f2016-08-23 13:42:15 -070026from 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:
Devin Lim58046fa2017-07-05 16:55:00 -070055 # Test variables
56 main.cellName = main.params[ 'ENV' ][ 'cellName' ]
57 main.apps = main.params[ 'ENV' ][ 'cellApps' ]
Devin Lim58046fa2017-07-05 16:55:00 -070058 main.path = os.path.dirname( main.testFile )
Devin Lim57221b02018-02-14 15:45:36 -080059 main.useCommonTopo = main.params[ 'DEPENDENCY' ][ 'useCommonTopo' ] == 'True'
60 main.topoPath = main.path + ( "/.." if main.useCommonTopo else "" ) + "/dependencies/"
61 main.useCommonConf = main.params[ 'DEPENDENCY' ][ 'useCommonConf' ] == 'True'
62 main.configPath = main.path + ( "/.." if main.useCommonConf else "" ) + "/dependencies/"
63 main.forJson = "json/"
64 main.forChart = "chart/"
65 main.forConfig = "conf/"
66 main.forHost = "host/"
You Wang27317572018-03-06 12:13:11 -080067 main.forSwitchFailure = "switchFailure/"
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -080068 main.forLinkFailure = "linkFailure/"
You Wange24d6272018-03-27 21:18:50 -070069 main.forMulticast = "multicast/"
Devin Lim58046fa2017-07-05 16:55:00 -070070 main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
You Wangd87b2312018-01-30 12:47:17 -080071 main.topologyLib = main.params[ 'DEPENDENCY' ][ 'lib' ] if 'lib' in main.params[ 'DEPENDENCY' ] else None
72 main.topologyConf = main.params[ 'DEPENDENCY' ][ 'conf' ] if 'conf' in main.params[ 'DEPENDENCY' ] else None
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070073 main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
Devin Lim58046fa2017-07-05 16:55:00 -070074 main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
Jon Hall1efcb3f2016-08-23 13:42:15 -070075
Devin Lim0c972b72018-02-08 14:53:59 -080076 stepResult = main.testSetUp.envSetup( False )
Devin Lim58046fa2017-07-05 16:55:00 -070077 except Exception as e:
78 main.testSetUp.envSetupException( e )
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -070079
Devin Lim58046fa2017-07-05 16:55:00 -070080 main.testSetUp.evnSetupConclusion( stepResult )
Jon Hall1efcb3f2016-08-23 13:42:15 -070081
Jon Hall1efcb3f2016-08-23 13:42:15 -070082 @staticmethod
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080083 def installOnos( main, vlanCfg=True, skipPackage=False, cliSleep=10,
84 parallel=True ):
Jon Hall1efcb3f2016-08-23 13:42:15 -070085 """
86 - Set up cell
87 - Create cell file
88 - Set cell file
89 - Verify cell file
90 - Kill ONOS process
91 - Uninstall ONOS cluster
92 - Verify ONOS start up
93 - Install ONOS cluster
94 - Connect to cli
95 """
96 # main.scale[ 0 ] determines the current number of ONOS controller
You Wangd87b2312018-01-30 12:47:17 -080097 if not main.apps:
Jon Hall1efcb3f2016-08-23 13:42:15 -070098 main.log.error( "App list is empty" )
Jon Hall3c910162018-03-07 14:42:16 -080099 main.log.info( "Cluster size: " + str( main.Cluster.numCtrls ) )
100 main.log.info( "Cluster ips: " + ', '.join( main.Cluster.getIps() ) )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700101 main.dynamicHosts = [ 'in1', 'out1' ]
You Wanga0f6ff62018-01-11 15:46:30 -0800102 main.testSetUp.ONOSSetUp( main.Cluster, newCell=True, cellName=main.cellName,
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800103 skipPack=skipPackage,
104 useSSH=Testcaselib.useSSH,
Devin Lim0c972b72018-02-08 14:53:59 -0800105 installParallel=parallel, includeCaseDesc=False )
Devin Lim142b5342017-07-20 15:22:39 -0700106 ready = utilities.retry( main.Cluster.active( 0 ).CLI.summary,
107 main.FALSE,
You Wang1cdc5f52017-12-19 16:47:51 -0800108 sleep=cliSleep,
Devin Lim142b5342017-07-20 15:22:39 -0700109 attempts=10 )
110 if ready:
111 ready = main.TRUE
112 utilities.assert_equals( expect=main.TRUE, actual=ready,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700113 onpass="ONOS summary command succeded",
114 onfail="ONOS summary command failed" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700115 if not ready:
116 main.log.error( "ONOS startup failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700117 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700118
Devin Lim142b5342017-07-20 15:22:39 -0700119 for ctrl in main.Cluster.active():
120 ctrl.CLI.logSet( "DEBUG", "org.onosproject.segmentrouting" )
You Wangf5f104f2018-03-30 17:09:10 -0700121 ctrl.CLI.logSet( "DEBUG", "org.onosproject.driver" )
Devin Lim142b5342017-07-20 15:22:39 -0700122 ctrl.CLI.logSet( "DEBUG", "org.onosproject.net.flowobjective.impl" )
You Wangf5f104f2018-03-30 17:09:10 -0700123 ctrl.CLI.logSet( "DEBUG", "org.onosproject.routeservice.impl" )
124 ctrl.CLI.logSet( "DEBUG", "org.onosproject.routeservice.store" )
125 ctrl.CLI.logSet( "DEBUG", "org.onosproject.routing.fpm" )
Jon Hall9677ed32018-04-24 11:16:23 -0700126 ctrl.CLI.logSet( "TRACE", "org.onosproject.events" )
127 ctrl.CLI.logSet( "DEBUG", "org.onosproject.mcast" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700128
129 @staticmethod
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800130 def loadCount( main ):
131 with open("%s/count/%s.count" % (main.configPath, main.cfgName)) as count:
You Wang5df1c6d2018-04-06 18:02:02 -0700132 main.count = json.load(count)
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800133
134 @staticmethod
Devin Lim57221b02018-02-14 15:45:36 -0800135 def loadJson( main ):
136 with open( "%s%s.json" % ( main.configPath + main.forJson,
137 main.cfgName ) ) as cfg:
138 main.Cluster.active( 0 ).REST.setNetCfg( json.load( cfg ) )
139
140 @staticmethod
141 def loadChart( main ):
142 try:
143 with open( "%s%s.chart" % ( main.configPath + main.forChart,
144 main.cfgName ) ) as chart:
145 main.pingChart = json.load(chart)
146 except IOError:
147 main.log.warn( "No chart file found." )
148
149 @staticmethod
150 def loadHost( main ):
151 with open( "%s%s.host" % ( main.configPath + main.forHost,
152 main.cfgName ) ) as host:
153 main.expectedHosts = json.load( host )
154
155 @staticmethod
You Wang27317572018-03-06 12:13:11 -0800156 def loadSwitchFailureChart( main ):
157 with open( "%s%s.switchFailureChart" % ( main.configPath + main.forSwitchFailure,
158 main.cfgName ) ) as sfc:
159 main.switchFailureChart = json.load( sfc )
160
161 @staticmethod
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800162 def loadLinkFailureChart( main ):
163 with open( "%s%s.linkFailureChart" % ( main.configPath + main.forLinkFailure,
You Wange24d6272018-03-27 21:18:50 -0700164 main.cfgName ) ) as lfc:
165 main.linkFailureChart = json.load( lfc )
166
167 @staticmethod
168 def loadMulticastConfig( main ):
169 with open( "%s%s.multicastConfig" % ( main.configPath + main.forMulticast,
170 main.cfgName ) ) as cfg:
171 main.multicastConfig = json.load( cfg )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800172
173 @staticmethod
Jon Hall1efcb3f2016-08-23 13:42:15 -0700174 def startMininet( main, topology, args="" ):
You Wangd87b2312018-01-30 12:47:17 -0800175 copyResult = main.ONOSbench.scp( main.Mininet1,
176 main.topoPath + main.topology,
You Wang5da39c82018-04-26 22:55:08 -0700177 main.Mininet1.home + "custom",
You Wangd87b2312018-01-30 12:47:17 -0800178 direction="to" )
179 if main.topologyLib:
180 for lib in main.topologyLib.split(","):
181 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
182 main.topoPath + lib,
You Wang5da39c82018-04-26 22:55:08 -0700183 main.Mininet1.home + "custom",
You Wangd87b2312018-01-30 12:47:17 -0800184 direction="to" )
185 if main.topologyConf:
You Wanga877ea42018-04-05 15:27:40 -0700186 import re
187 controllerIPs = [ ctrl.ipAddress for ctrl in main.Cluster.runningNodes ]
188 index = 0
You Wangd87b2312018-01-30 12:47:17 -0800189 for conf in main.topologyConf.split(","):
You Wanga877ea42018-04-05 15:27:40 -0700190 # Update zebra configurations with correct ONOS instance IP
191 if conf in [ "zebradbgp1.conf", "zebradbgp2.conf" ]:
192 ip = controllerIPs[ index ]
193 index = ( index + 1 ) % len( controllerIPs )
194 with open( main.configPath + main.forConfig + conf ) as f:
195 s = f.read()
196 s = re.sub( r"(fpm connection ip).*(port 2620)", r"\1 " + ip + r" \2", s )
197 with open( main.configPath + main.forConfig + conf, "w" ) as f:
198 f.write( s )
You Wangd87b2312018-01-30 12:47:17 -0800199 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
Devin Lim57221b02018-02-14 15:45:36 -0800200 main.configPath + main.forConfig + conf,
You Wangd87b2312018-01-30 12:47:17 -0800201 "~/",
202 direction="to" )
203 stepResult = copyResult
204 utilities.assert_equals( expect=main.TRUE,
205 actual=stepResult,
206 onpass="Successfully copied topo files",
207 onfail="Failed to copy topo files" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700208 main.step( "Starting Mininet Topology" )
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -0700209 arg = "--onos-ip=%s %s" % (",".join([ctrl.ipAddress for ctrl in main.Cluster.runningNodes]), args)
Jon Hall1efcb3f2016-08-23 13:42:15 -0700210 main.topology = topology
211 topoResult = main.Mininet1.startNet(
You Wang5da39c82018-04-26 22:55:08 -0700212 topoFile=main.Mininet1.home + "custom/" + main.topology, args=arg )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700213 stepResult = topoResult
214 utilities.assert_equals( expect=main.TRUE,
215 actual=stepResult,
216 onpass="Successfully loaded topology",
217 onfail="Failed to load topology" )
218 # Exit if topology did not load properly
219 if not topoResult:
Devin Lim44075962017-08-11 10:56:37 -0700220 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700221
222 @staticmethod
You Wang84f981d2018-01-12 16:11:50 -0800223 def connectToPhysicalNetwork( main, switchNames ):
224 main.step( "Connecting to physical netowrk" )
225 topoResult = main.NetworkBench.connectToNet()
226 stepResult = topoResult
227 utilities.assert_equals( expect=main.TRUE,
228 actual=stepResult,
229 onpass="Successfully loaded topology",
230 onfail="Failed to load topology" )
231 # Exit if topology did not load properly
232 if not topoResult:
233 main.cleanAndExit()
234
235 main.step( "Assign switches to controllers." )
236 assignResult = main.TRUE
237 for name in switchNames:
238 assignResult = assignResult & main.NetworkBench.assignSwController( sw=name,
239 ip=main.Cluster.getIps(),
240 port='6653' )
241 utilities.assert_equals( expect=main.TRUE,
242 actual=stepResult,
243 onpass="Successfully assign switches to controllers",
244 onfail="Failed to assign switches to controllers" )
245
246 @staticmethod
You Wang5df1c6d2018-04-06 18:02:02 -0700247 def saveOnosDiagnostics( main ):
248 """
249 Get onos-diags.tar.gz and save it to the log directory.
250 suffix: suffix string of the file name. E.g. onos-diags-case1.tar.gz
251 """
252 main.log.info( "Collecting onos-diags..." )
253 main.ONOSbench.onosDiagnostics( [ctrl.ipAddress for ctrl in main.Cluster.runningNodes],
254 main.logdir,
255 "-CASE%d" % main.CurrentTestCaseNumber )
256
257 @staticmethod
Devin Lim142b5342017-07-20 15:22:39 -0700258 def config( main, cfgName ):
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700259 main.spines = []
Piera2a7e1b2016-10-04 11:51:43 -0700260
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700261 main.failures = int( main.params[ 'failures' ] )
262 main.cfgName = cfgName
Piera2a7e1b2016-10-04 11:51:43 -0700263
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700264 if main.cfgName == '2x2':
265 spine = {}
266 spine[ 'name' ] = main.params[ 'switches' ][ 'spine1' ]
267 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid1' ]
268 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700269
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700270 spine = {}
271 spine[ 'name' ] = main.params[ 'switches' ][ 'spine2' ]
272 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid2' ]
273 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700274
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700275 elif main.cfgName == '4x4':
276 spine = {}
277 spine[ 'name' ] = main.params[ 'switches' ][ 'spine1' ]
278 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid1' ]
279 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700280
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700281 spine = {}
282 spine[ 'name' ] = main.params[ 'switches' ][ 'spine2' ]
283 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid2' ]
284 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700285
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700286 spine = {}
287 spine[ 'name' ] = main.params[ 'switches' ][ 'spine3' ]
288 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid3' ]
289 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700290
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700291 spine = {}
292 spine[ 'name' ] = main.params[ 'switches' ][ 'spine4' ]
293 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid4' ]
294 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700295
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700296 else:
Piera2a7e1b2016-10-04 11:51:43 -0700297 main.log.error( "Configuration failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700298 main.cleanAndExit()
You Wang27317572018-03-06 12:13:11 -0800299
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -0800300 @staticmethod
301 def addStaticOnosRoute( main, subnet, intf):
302 """
303 Adds an ONOS static route with the use route-add command.
304 """
305 main.step("Add static route for subnet {0} towards router interface {1}".format(subnet, intf))
306 routeResult = main.Cluster.active( 0 ).addStaticRoute(subnet, intf)
307
308 utilities.assert_equals( expect=True, actual=( not routeResult ),
309 onpass="route-add command succeeded",
310 onfail="route-add command failed")
Piera2a7e1b2016-10-04 11:51:43 -0700311
312 @staticmethod
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700313 def checkGroupsForBuckets( main, deviceId, subnetDict, routingTable=30):
314 """
315 Check number of groups for each subnet on device deviceId and matches
316 it with an expected value. subnetDict is a dictionarty containing values
317 of the type "10.0.1.0/24" : 5.
318 """
319 main.step("Checking if number of groups for subnets in device {0} is as expected.".format(deviceId))
320 groups = main.Cluster.active( 0 ).CLI.getGroups(deviceId, group_type="select")
321 flows = main.Cluster.active( 0 ).CLI.flows(jsonFormat=False, device=deviceId)
322
323 for subnet, number_in_select in subnetDict.iteritems():
324 for flow in flows.splitlines():
325 if "tableId={0}".format(routingTable) in flow and subnet in flow:
326
327 # this will match the group id that this flow entry points to, for example :
328 # 0x70000041 in flow entry which contains "deferred=[GROUP:0x70000041], transition=TABLE:60,"
329 group_id = re.search(r".*GROUP:(0x.*)], transition.*", flow).groups()[0]
330
331 count = 0
332 for group in groups.splitlines():
333 if 'id={0}'.format(group_id) in group:
334 count += 1
335
336 utilities.assert_equals( expect=True, actual=(count-1 == number_in_select),
337 onpass="Number of buckets in select group is correct",
338 onfail="Mismatch in number of buckets of select group, found {0}, expected {1} for subnet {2} on device {3}".format(count - 1, number_in_select, subnet, deviceId))
339 else:
340 continue
341
342 @staticmethod
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900343 def checkFlows( main, minFlowCount, tag="", dumpflows=True, sleep=10 ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700344 main.step(
Jon Hall3c910162018-03-07 14:42:16 -0800345 "Check whether the flow count is bigger than %s" % minFlowCount )
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900346 if tag == "":
347 tag = 'CASE%d' % main.CurrentTestCaseNumber
Devin Lim142b5342017-07-20 15:22:39 -0700348 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowCount,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700349 main.FALSE,
350 kwargs={ 'min': minFlowCount },
351 attempts=10,
You Wang1cdc5f52017-12-19 16:47:51 -0800352 sleep=sleep )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700353 utilities.assertEquals(
Jon Hall1efcb3f2016-08-23 13:42:15 -0700354 expect=True,
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700355 actual=( count > 0 ),
Jon Hall1efcb3f2016-08-23 13:42:15 -0700356 onpass="Flow count looks correct: " + str( count ),
357 onfail="Flow count looks wrong: " + str( count ) )
358
359 main.step( "Check whether all flow status are ADDED" )
Devin Lim142b5342017-07-20 15:22:39 -0700360 flowCheck = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowsState,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700361 main.FALSE,
362 kwargs={ 'isPENDING': False },
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800363 attempts=5,
You Wang1cdc5f52017-12-19 16:47:51 -0800364 sleep=sleep )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700365 utilities.assertEquals(
Jon Hall1efcb3f2016-08-23 13:42:15 -0700366 expect=main.TRUE,
367 actual=flowCheck,
368 onpass="Flow status is correct!",
369 onfail="Flow status is wrong!" )
370 if dumpflows:
Devin Lim142b5342017-07-20 15:22:39 -0700371 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
Pier50f0bc62016-09-07 17:53:40 -0700372 "flows",
373 main.logdir,
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900374 tag + "_FlowsBefore" )
Devin Lim142b5342017-07-20 15:22:39 -0700375 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
Pier50f0bc62016-09-07 17:53:40 -0700376 "groups",
377 main.logdir,
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900378 tag + "_GroupsBefore" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700379
380 @staticmethod
Pier6a0c4de2018-03-18 16:01:30 -0700381 def checkDevices( main, switches, tag="", sleep=10 ):
382 main.step(
383 "Check whether the switches count is equal to %s" % switches )
384 if tag == "":
385 tag = 'CASE%d' % main.CurrentTestCaseNumber
386 result = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
387 main.FALSE,
388 kwargs={ 'numoswitch': switches},
389 attempts=10,
390 sleep=sleep )
391 utilities.assert_equals( expect=main.TRUE, actual=result,
392 onpass="Device up successful",
393 onfail="Failed to boot up devices?" )
394
395 @staticmethod
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800396 def checkFlowsByDpid( main, dpid, minFlowCount, sleep=10 ):
397 main.step(
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800398 " Check whether the flow count of device %s is bigger than %s" % ( dpid, minFlowCount ) )
399 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
400 main.FALSE,
401 args=( dpid, minFlowCount ),
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800402 attempts=5,
403 sleep=sleep )
404 utilities.assertEquals(
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800405 expect=True,
406 actual=( count > minFlowCount ),
407 onpass="Flow count looks correct: " + str( count ),
408 onfail="Flow count looks wrong. " )
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800409
410 @staticmethod
Jon Hall9677ed32018-04-24 11:16:23 -0700411 def checkFlowEqualityByDpid( main, dpid, flowCount, sleep=10 ):
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800412 main.step(
413 " Check whether the flow count of device %s is equal to %s" % ( dpid, flowCount ) )
414 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
415 main.FALSE,
Jon Hall9677ed32018-04-24 11:16:23 -0700416 args=( dpid, flowCount, False, 1 ),
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800417 attempts=5,
418 sleep=sleep )
419
420 utilities.assertEquals(
421 expect=True,
422 actual=( int( count ) == flowCount ),
Jon Hall9677ed32018-04-24 11:16:23 -0700423 onpass="Flow count looks correct: " + str( count ) ,
424 onfail="Flow count looks wrong. found {}, should be {}.".format( count, flowCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800425
426 @staticmethod
427 def checkGroupEqualityByDpid( main, dpid, groupCount, sleep=10):
428 main.step(
429 " Check whether the group count of device %s is equal to %s" % ( dpid, groupCount ) )
430 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkGroupAddedCount,
431 main.FALSE,
432 args=( dpid, groupCount, False, 1),
433 attempts=5,
434 sleep=sleep )
435
436 utilities.assertEquals(
437 expect=True,
438 actual=( count == groupCount ),
Jon Hall9677ed32018-04-24 11:16:23 -0700439 onpass="Group count looks correct: " + str( count ) ,
440 onfail="Group count looks wrong. found {}, should be {}.".format( count, groupCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800441
442 @staticmethod
Jon Hall9677ed32018-04-24 11:16:23 -0700443 def checkFlowsGroupsFromFile( main ):
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800444
445 for dpid, values in main.count.items():
446 flowCount = values["flows"]
447 groupCount = values["groups"]
Jon Hall9677ed32018-04-24 11:16:23 -0700448 main.log.report( "Check flow count for dpid " + str( dpid ) +
449 ", should be " + str( flowCount ) )
450 Testcaselib.checkFlowEqualityByDpid( main, dpid, flowCount )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800451
Jon Hall9677ed32018-04-24 11:16:23 -0700452 main.log.report( "Check group count for dpid " + str( dpid ) +
453 ", should be " + str( groupCount ) )
454 Testcaselib.checkGroupEqualityByDpid( main, dpid, groupCount )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800455
456 return
457
458 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700459 def pingAll( main, tag="", dumpflows=True, acceptableFailed=0, basedOnIp=False,
460 sleep=10, retryAttempts=1, skipOnFail=False ):
You Wangf19d9f42018-02-23 16:34:19 -0800461 '''
You Wangba231e72018-03-01 13:18:21 -0800462 Verify connectivity between hosts according to the ping chart
463 acceptableFailed: max number of acceptable failed pings.
You Wangf19d9f42018-02-23 16:34:19 -0800464 basedOnIp: if True, run ping or ping6 based on suffix of host names
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800465 retryAttempts: the number of retry ping. Only works for IPv4 hosts.
You Wangf19d9f42018-02-23 16:34:19 -0800466 '''
You Wangba231e72018-03-01 13:18:21 -0800467 main.log.report( "Check host connectivity" )
468 main.log.debug( "Ping chart: %s" % main.pingChart )
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800469 if tag == "":
470 tag = 'CASE%d' % main.CurrentTestCaseNumber
471 for entry in main.pingChart.itervalues():
You Wangba231e72018-03-01 13:18:21 -0800472 main.log.debug( "Entry in ping chart: %s" % entry )
473 expect = entry[ 'expect' ]
474 if expect == "Unidirectional":
475 # Verify ping from each src host to each dst host
476 src = entry[ 'src' ]
477 dst = entry[ 'dst' ]
478 expect = main.TRUE
479 main.step( "Verify unidirectional connectivity from %s to %s with tag %s" % ( str( src ), str( dst ), tag ) )
480 if basedOnIp:
481 if ("v4" in src[0]):
482 pa = main.Network.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed )
483 utilities.assert_equals( expect=expect, actual=pa,
484 onpass="IPv4 connectivity successfully tested",
485 onfail="IPv4 connectivity failed" )
486 if ("v6" in src[0]):
487 pa = main.Network.pingallHostsUnidirectional( src, dst, ipv6=True, acceptableFailed=acceptableFailed )
488 utilities.assert_equals( expect=expect, actual=pa,
489 onpass="IPv6 connectivity successfully tested",
490 onfail="IPv6 connectivity failed" )
491 else:
492 pa = main.Network.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed )
493 utilities.assert_equals( expect=expect, actual=pa,
494 onpass="IP connectivity successfully tested",
495 onfail="IP connectivity failed" )
496 else:
497 # Verify ping between each host pair
498 hosts = entry[ 'hosts' ]
499 try:
500 expect = main.TRUE if str(expect).lower() == 'true' else main.FALSE
501 except:
502 expect = main.FALSE
503 main.step( "Verify full connectivity for %s with tag %s" % ( str( hosts ), tag ) )
504 if basedOnIp:
505 if ("v4" in hosts[0]):
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800506 pa = utilities.retry( main.Network.pingallHosts,
507 main.FALSE if expect else main.TRUE,
508 args=(hosts,),
509 attempts=retryAttempts,
510 sleep=sleep )
You Wangba231e72018-03-01 13:18:21 -0800511 utilities.assert_equals( expect=expect, actual=pa,
512 onpass="IPv4 connectivity successfully tested",
513 onfail="IPv4 connectivity failed" )
514 if ("v6" in hosts[0]):
515 pa = main.Network.pingIpv6Hosts( hosts, acceptableFailed=acceptableFailed )
516 utilities.assert_equals( expect=expect, actual=pa,
517 onpass="IPv6 connectivity successfully tested",
518 onfail="IPv6 connectivity failed" )
519 else:
You Wangf19d9f42018-02-23 16:34:19 -0800520 pa = main.Network.pingallHosts( hosts )
521 utilities.assert_equals( expect=expect, actual=pa,
You Wangba231e72018-03-01 13:18:21 -0800522 onpass="IP connectivity successfully tested",
523 onfail="IP connectivity failed" )
You Wang5df1c6d2018-04-06 18:02:02 -0700524 if skipOnFail and pa != expect:
525 Testcaselib.saveOnosDiagnostics( main )
You Wang24ad2f52018-04-10 10:47:12 -0700526 Testcaselib.cleanup( main, copyKarafLog=False )
You Wang5df1c6d2018-04-06 18:02:02 -0700527 main.skipCase()
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800528
529 if dumpflows:
530 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
531 "flows",
532 main.logdir,
533 tag + "_FlowsOn" )
534 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
535 "groups",
536 main.logdir,
537 tag + "_GroupsOn" )
538
539 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700540 def killLink( main, end1, end2, switches, links, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700541 """
542 end1,end2: identify the switches, ex.: 'leaf1', 'spine1'
543 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
544 Kill a link and verify ONOS can see the proper link change
545 """
Jon Halla604fd42018-05-04 14:27:27 -0700546 if sleep is None:
547 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
548 else:
549 sleep = float( sleep )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700550 main.step( "Kill link between %s and %s" % ( end1, end2 ) )
Jon Halla604fd42018-05-04 14:27:27 -0700551 linkDown = main.Network.link( END1=end1, END2=end2, OPTION="down" )
552 linkDown = linkDown and main.Network.link( END2=end1, END1=end2, OPTION="down" )
553 # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
Jon Hall1efcb3f2016-08-23 13:42:15 -0700554 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700555 "Waiting %s seconds for link down to be discovered" % sleep )
556 time.sleep( sleep )
Devin Lim142b5342017-07-20 15:22:39 -0700557 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700558 main.FALSE,
559 kwargs={ 'numoswitch': switches,
560 'numolink': links },
561 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700562 sleep=sleep )
563 result = topology and linkDown
Jon Hall1efcb3f2016-08-23 13:42:15 -0700564 utilities.assert_equals( expect=main.TRUE, actual=result,
565 onpass="Link down successful",
566 onfail="Failed to turn off link?" )
567
568 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700569 def killLinkBatch( main, links, linksAfter, switches, sleep=None ):
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800570 """
571 links = list of links (src, dst) to bring down.
572 """
573
574 main.step("Killing a batch of links {0}".format(links))
Jon Halla604fd42018-05-04 14:27:27 -0700575 if sleep is None:
576 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
577 else:
578 sleep = float( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800579
580 for end1, end2 in links:
581 main.Network.link( END1=end1, END2=end2, OPTION="down")
582 main.Network.link( END1=end2, END2=end1, OPTION="down")
583
Jon Halla604fd42018-05-04 14:27:27 -0700584 # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800585 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700586 "Waiting %s seconds for links down to be discovered" % sleep )
587 time.sleep( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800588
589 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
590 main.FALSE,
591 kwargs={ 'numoswitch': switches,
592 'numolink': linksAfter },
593 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700594 sleep=sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800595
You Wang2854bce2018-03-30 10:15:32 -0700596 utilities.assert_equals( expect=main.TRUE, actual=topology,
597 onpass="Link batch down successful",
598 onfail="Link batch down failed" )
599
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800600 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700601 def restoreLinkBatch( main, links, linksAfter, switches, sleep=None ):
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800602 """
603 links = list of link (src, dst) to bring up again.
604 """
605
606 main.step("Restoring a batch of links {0}".format(links))
Jon Halla604fd42018-05-04 14:27:27 -0700607 if sleep is None:
608 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
609 else:
610 sleep = float( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800611
612 for end1, end2 in links:
613 main.Network.link( END1=end1, END2=end2, OPTION="up")
614 main.Network.link( END1=end2, END2=end1, OPTION="up")
615
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800616 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700617 "Waiting %s seconds for links up to be discovered" % sleep )
618 time.sleep( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800619
620 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
621 main.FALSE,
622 kwargs={ 'numoswitch': switches,
623 'numolink': linksAfter },
624 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700625 sleep=sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800626
You Wang2854bce2018-03-30 10:15:32 -0700627 utilities.assert_equals( expect=main.TRUE, actual=topology,
628 onpass="Link batch up successful",
629 onfail="Link batch up failed" )
630
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800631 @staticmethod
You Wang85747762018-05-11 15:51:50 -0700632 def disablePortBatch( main, ports, switches=None, links=None, sleep=None ):
633 """
634 Disable a list of switch ports using 'portstate' and verify ONOS can see the proper link change
635 ports: a list of ports to disable ex. [ [ "of:0000000000000001", 1 ] ]
636 switches, links: number of expected switches and links after link change, ex.: '4', '6'
637 """
638 if sleep is None:
639 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
640 else:
641 sleep = float( sleep )
642 main.step( "Disable a batch of ports" )
643 for dpid, port in ports:
644 main.Cluster.active( 0 ).CLI.portstate( dpid=dpid, port=port, state="disable" )
645 main.log.info( "Waiting {} seconds for port down to be discovered".format( sleep ) )
646 time.sleep( sleep )
647 if switches and links:
648 result = main.Cluster.active( 0 ).CLI.checkStatus( numoswitch=switches,
649 numolink=links )
650 utilities.assert_equals( expect=main.TRUE, actual=result,
651 onpass="Port down successful",
652 onfail="Port down failed" )
653
654 @staticmethod
655 def enablePortBatch( main, ports, switches, links, sleep=None ):
656 """
657 Enable a list of switch ports using 'portstate' and verify ONOS can see the proper link change
658 ports: a list of ports to enable ex. [ [ "of:0000000000000001", 1 ] ]
659 switches, links: number of expected switches and links after link change, ex.: '4', '6'
660 """
661 if sleep is None:
662 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
663 else:
664 sleep = float( sleep )
665 main.step( "Enable a batch of ports" )
666 for dpid, port in ports:
667 main.Cluster.active( 0 ).CLI.portstate( dpid=dpid, port=port, state="enable" )
668 main.log.info( "Waiting {} seconds for port up to be discovered".format( sleep ) )
669 time.sleep( sleep )
670 if switches and links:
671 result = main.Cluster.active( 0 ).CLI.checkStatus( numoswitch=switches,
672 numolink=links )
673 utilities.assert_equals( expect=main.TRUE, actual=result,
674 onpass="Port up successful",
675 onfail="Port up failed" )
676
677 @staticmethod
You Wangc02d8352018-04-17 16:42:10 -0700678 def restoreLink( main, end1, end2, switches, links,
Jon Halla604fd42018-05-04 14:27:27 -0700679 portUp=False, dpid1='', dpid2='', port1='', port2='', sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700680 """
681 Params:
682 end1,end2: identify the end switches, ex.: 'leaf1', 'spine1'
You Wangc02d8352018-04-17 16:42:10 -0700683 portUp: enable portstate after restoring link
Jon Hall1efcb3f2016-08-23 13:42:15 -0700684 dpid1, dpid2: dpid of the end switches respectively, ex.: 'of:0000000000000002'
685 port1, port2: respective port of the end switches that connects to the link, ex.:'1'
686 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
687 Kill a link and verify ONOS can see the proper link change
688 """
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700689 main.step( "Restore link between %s and %s" % ( end1, end2 ) )
Jon Halla604fd42018-05-04 14:27:27 -0700690 if sleep is None:
691 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
692 else:
693 sleep = float( sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700694 result = False
695 count = 0
696 while True:
697 count += 1
Jon Halla604fd42018-05-04 14:27:27 -0700698 ctrl = main.Cluster.next()
You Wangd5873482018-01-24 12:30:00 -0800699 main.Network.link( END1=end1, END2=end2, OPTION="up" )
700 main.Network.link( END2=end1, END1=end2, OPTION="up" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700701 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700702 "Waiting %s seconds for link up to be discovered" % sleep )
703 time.sleep( sleep )
Pierfb719b12016-09-19 14:51:44 -0700704
You Wangc02d8352018-04-17 16:42:10 -0700705 if portUp:
706 ctrl.CLI.portstate( dpid=dpid1, port=port1, state='Enable' )
707 ctrl.CLI.portstate( dpid=dpid2, port=port2, state='Enable' )
Jon Halla604fd42018-05-04 14:27:27 -0700708 time.sleep( sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700709
Jon Halla604fd42018-05-04 14:27:27 -0700710 result = ctrl.CLI.checkStatus( numoswitch=switches,
711 numolink=links )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700712 if count > 5 or result:
713 break
714 utilities.assert_equals( expect=main.TRUE, actual=result,
715 onpass="Link up successful",
716 onfail="Failed to bring link up" )
717
718 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700719 def killSwitch( main, switch, switches, links, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700720 """
721 Params: switches, links: number of expected switches and links after SwitchDown, ex.: '4', '6'
722 Completely kill a switch and verify ONOS can see the proper change
723 """
Jon Halla604fd42018-05-04 14:27:27 -0700724 if sleep is None:
725 sleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
726 else:
727 sleep = float( sleep )
You Wangc02d8352018-04-17 16:42:10 -0700728 switch = switch if isinstance( switch, list ) else [ switch ]
729 main.step( "Kill " + str( switch ) )
730 for s in switch:
731 main.log.info( "Stopping " + s )
732 main.Network.switch( SW=s, OPTION="stop" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700733 # todo make this repeatable
Jon Halla604fd42018-05-04 14:27:27 -0700734
735 # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
Jon Hall1efcb3f2016-08-23 13:42:15 -0700736 main.log.info( "Waiting %s seconds for switch down to be discovered" % (
Jon Halla604fd42018-05-04 14:27:27 -0700737 sleep ) )
738 time.sleep( sleep )
Devin Lim142b5342017-07-20 15:22:39 -0700739 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700740 main.FALSE,
741 kwargs={ 'numoswitch': switches,
742 'numolink': links },
743 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700744 sleep=sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700745 utilities.assert_equals( expect=main.TRUE, actual=topology,
746 onpass="Kill switch successful",
747 onfail="Failed to kill switch?" )
748
749 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700750 def recoverSwitch( main, switch, switches, links, rediscoverHosts=False, hostsToDiscover=[], sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700751 """
752 Params: switches, links: number of expected switches and links after SwitchUp, ex.: '4', '6'
753 Recover a switch and verify ONOS can see the proper change
754 """
Jon Halla604fd42018-05-04 14:27:27 -0700755 if sleep is None:
756 sleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
757 else:
758 sleep = float( sleep )
759 # TODO make this repeatable
You Wangc02d8352018-04-17 16:42:10 -0700760 switch = switch if isinstance( switch, list ) else [ switch ]
761 main.step( "Recovering " + str( switch ) )
762 for s in switch:
763 main.log.info( "Starting " + s )
764 main.Network.switch( SW=s, OPTION="start" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700765 main.log.info( "Waiting %s seconds for switch up to be discovered" % (
Jon Halla604fd42018-05-04 14:27:27 -0700766 sleep ) )
767 time.sleep( sleep )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700768 if rediscoverHosts:
You Wang48381752018-05-07 13:50:57 -0700769 main.Network.discoverHosts( hostList=hostsToDiscover )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700770 main.log.info( "Waiting %s seconds for hosts to get re-discovered" % (
Jon Halla604fd42018-05-04 14:27:27 -0700771 sleep ) )
772 time.sleep( sleep )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -0700773
Devin Lim142b5342017-07-20 15:22:39 -0700774 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700775 main.FALSE,
776 kwargs={ 'numoswitch': switches,
777 'numolink': links },
778 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700779 sleep=sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700780 utilities.assert_equals( expect=main.TRUE, actual=topology,
781 onpass="Switch recovery successful",
782 onfail="Failed to recover switch?" )
783
Jonghwan Hyun25c98a62018-05-04 13:59:09 -0700784 @staticmethod
You Wang5da39c82018-04-26 22:55:08 -0700785 def cleanup( main, copyKarafLog=True, removeHostComponent=False ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700786 """
787 Stop Onos-cluster.
788 Stops Mininet
789 Copies ONOS log
790 """
Devin Lim58046fa2017-07-05 16:55:00 -0700791 try:
792 from tests.dependencies.utils import Utils
793 except ImportError:
794 main.log.error( "Utils not found exiting the test" )
Devin Lim44075962017-08-11 10:56:37 -0700795 main.cleanAndExit()
Devin Lim58046fa2017-07-05 16:55:00 -0700796 try:
Devin Lim142b5342017-07-20 15:22:39 -0700797 main.utils
Devin Lim58046fa2017-07-05 16:55:00 -0700798 except ( NameError, AttributeError ):
Devin Lim142b5342017-07-20 15:22:39 -0700799 main.utils = Utils()
Devin Lim58046fa2017-07-05 16:55:00 -0700800
You Wange24d6272018-03-27 21:18:50 -0700801 if hasattr( main, "scapyHosts" ):
802 scapyResult = main.TRUE
803 for host in main.scapyHosts:
804 scapyResult = host.stopScapy() and scapyResult
805 main.log.info( "Stopped Scapy Host: {0}".format( host.name ) )
806 for host in main.scapyHosts:
807 scapyResult = main.Scapy.removeHostComponent( host.name ) and scapyResult
808 main.log.info( "Removed Scapy Host Component: {0}".format( host.name ) )
809 main.scapyHosts = []
810
You Wang5da39c82018-04-26 22:55:08 -0700811 if removeHostComponent:
812 for host in main.internalIpv4Hosts + main.internalIpv6Hosts + main.externalIpv4Hosts + main.externalIpv6Hosts:
813 if hasattr( main, host ):
814 main.Network.removeHostComponent( host )
815
You Wang5df1c6d2018-04-06 18:02:02 -0700816 if hasattr( main, 'Mininet1' ):
Pier6a0c4de2018-03-18 16:01:30 -0700817 main.utils.mininetCleanup( main.Mininet1 )
Devin Lim58046fa2017-07-05 16:55:00 -0700818
You Wang5df1c6d2018-04-06 18:02:02 -0700819 if copyKarafLog:
820 main.utils.copyKarafLog( "CASE%d" % main.CurrentTestCaseNumber, before=True, includeCaseDesc=False )
Devin Lim58046fa2017-07-05 16:55:00 -0700821
Devin Lim142b5342017-07-20 15:22:39 -0700822 for ctrl in main.Cluster.active():
823 main.ONOSbench.onosStop( ctrl.ipAddress )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700824
825 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700826 def verifyNodes( main ):
827 """
828 Verifies Each active node in the cluster has an accurate view of other node's and their status
829
830 Params:
831 nodes, integer array with position of the ONOS nodes in the CLIs array
832 """
833 nodeResults = utilities.retry( main.Cluster.nodesCheck,
834 False,
835 attempts=10,
836 sleep=10 )
837 utilities.assert_equals( expect=True, actual=nodeResults,
838 onpass="Nodes check successful",
839 onfail="Nodes check NOT successful" )
840
841 if not nodeResults:
842 for ctrl in main.Cluster.runningNodes:
843 main.log.debug( "{} components not ACTIVE: \n{}".format(
844 ctrl.name,
845 ctrl.CLI.sendline( "scr:list | grep -v ACTIVE" ) ) )
846 main.log.error( "Failed to kill ONOS, stopping test" )
847 main.cleanAndExit()
848
849 @staticmethod
850 def verifyTopology( main, switches, links, expNodes ):
851 """
852 Verifies that the ONOS cluster has an acuurate view of the topology
853
854 Params:
855 switches, links, expNodes: number of expected switches, links, and nodes at this point in the test ex.: '4', '6', '2'
856 """
857 main.step( "Check number of topology elements" )
858 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
859 main.FALSE,
860 kwargs={ 'numoswitch': switches,
861 'numolink': links,
862 'numoctrl': expNodes },
863 attempts=10,
864 sleep=12 )
865 utilities.assert_equals( expect=main.TRUE, actual=topology,
866 onpass="Number of topology elements are correct",
867 onfail="Unexpected number of links, switches, and/or controllers" )
868
869 @staticmethod
870 def killOnos( main, nodes, switches, links, expNodes, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700871 """
872 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
873 switches, links, nodes: number of expected switches, links and nodes after KillOnos, ex.: '4', '6'
874 Completely Kill an ONOS instance and verify the ONOS cluster can see the proper change
875 """
Jon Halla604fd42018-05-04 14:27:27 -0700876 # TODO: We have enough information in the Cluster instance to remove expNodes from here and verifyTopology
Jon Hall3c910162018-03-07 14:42:16 -0800877 main.step( "Killing ONOS instances with index(es): {}".format( nodes ) )
Jon Halla604fd42018-05-04 14:27:27 -0700878 if sleep is None:
879 sleep = float( main.params[ 'timers' ][ 'OnosDiscovery' ] )
880 else:
881 sleep = float( sleep )
Pier3b58c652016-09-26 12:03:31 -0700882
Jon Hall1efcb3f2016-08-23 13:42:15 -0700883 for i in nodes:
Devin Lim142b5342017-07-20 15:22:39 -0700884 killResult = main.ONOSbench.onosDie( main.Cluster.runningNodes[ i ].ipAddress )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700885 utilities.assert_equals( expect=main.TRUE, actual=killResult,
886 onpass="ONOS instance Killed",
887 onfail="Error killing ONOS instance" )
Devin Lim142b5342017-07-20 15:22:39 -0700888 main.Cluster.runningNodes[ i ].active = False
Jon Halla604fd42018-05-04 14:27:27 -0700889 main.Cluster.reset()
890 time.sleep( sleep )
Pier3b58c652016-09-26 12:03:31 -0700891
Devin Lim142b5342017-07-20 15:22:39 -0700892 if len( nodes ) < main.Cluster.numCtrls:
Jon Halla604fd42018-05-04 14:27:27 -0700893 Testcaselib.verifyNodes( main )
894 Testcaselib.verifyTopology( main, switches, links, expNodes )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700895
896 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700897 def recoverOnos( main, nodes, switches, links, expNodes, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700898 """
899 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
900 switches, links, nodes: number of expected switches, links and nodes after recoverOnos, ex.: '4', '6'
901 Recover an ONOS instance and verify the ONOS cluster can see the proper change
902 """
Jon Hall3c910162018-03-07 14:42:16 -0800903 main.step( "Recovering ONOS instances with index(es): {}".format( nodes ) )
Jon Halla604fd42018-05-04 14:27:27 -0700904 if sleep is None:
905 sleep = float( main.params[ 'timers' ][ 'OnosDiscovery' ] )
906 else:
907 sleep = float( sleep )
Devin Lim142b5342017-07-20 15:22:39 -0700908 [ main.ONOSbench.onosStart( main.Cluster.runningNodes[ i ].ipAddress ) for i in nodes ]
Jon Halla604fd42018-05-04 14:27:27 -0700909 time.sleep( sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700910 for i in nodes:
Devin Lim142b5342017-07-20 15:22:39 -0700911 isUp = main.ONOSbench.isup( main.Cluster.runningNodes[ i ].ipAddress )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700912 utilities.assert_equals( expect=main.TRUE, actual=isUp,
913 onpass="ONOS service is ready",
914 onfail="ONOS service did not start properly" )
915 for i in nodes:
916 main.step( "Checking if ONOS CLI is ready" )
Devin Lim142b5342017-07-20 15:22:39 -0700917 ctrl = main.Cluster.runningNodes[ i ]
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900918 # ctrl.CLI.startCellCli()
Devin Lim142b5342017-07-20 15:22:39 -0700919 cliResult = ctrl.CLI.startOnosCli( ctrl.ipAddress,
920 commandlineTimeout=60,
921 onosStartTimeout=100 )
922 ctrl.active = True
Jon Hall1efcb3f2016-08-23 13:42:15 -0700923 utilities.assert_equals( expect=main.TRUE,
924 actual=cliResult,
925 onpass="ONOS CLI is ready",
926 onfail="ONOS CLI is not ready" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700927
Jon Halla604fd42018-05-04 14:27:27 -0700928 main.Cluster.reset()
Pier3b58c652016-09-26 12:03:31 -0700929 main.step( "Checking ONOS nodes" )
Jon Halla604fd42018-05-04 14:27:27 -0700930 Testcaselib.verifyNodes( main )
931 Testcaselib.verifyTopology( main, switches, links, expNodes )
Pier3b58c652016-09-26 12:03:31 -0700932
Devin Lim142b5342017-07-20 15:22:39 -0700933 ready = utilities.retry( main.Cluster.active( 0 ).CLI.summary,
934 main.FALSE,
935 attempts=10,
936 sleep=12 )
937 if ready:
938 ready = main.TRUE
939 utilities.assert_equals( expect=main.TRUE, actual=ready,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700940 onpass="ONOS summary command succeded",
941 onfail="ONOS summary command failed" )
942 if not ready:
943 main.log.error( "ONOS startup failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700944 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700945
946 @staticmethod
947 def addHostCfg( main ):
948 """
949 Adds Host Configuration to ONOS
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700950 Updates expected state of the network ( pingChart )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700951 """
952 import json
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700953 hostCfg = {}
Devin Lim57221b02018-02-14 15:45:36 -0800954 with open( main.configPath + main.forJson + "extra.json" ) as template:
Jon Hall1efcb3f2016-08-23 13:42:15 -0700955 hostCfg = json.load( template )
956 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'in1' ]
957 main.step( "Pushing new configuration" )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700958 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -0700959 main.Cluster.active( 0 ).REST.setNetCfg( cfg[ 'basic' ],
960 subjectClass="hosts",
961 subjectKey=urllib.quote( mac,
962 safe='' ),
963 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700964 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'out1' ]
965 main.step( "Pushing new configuration" )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700966 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -0700967 main.Cluster.active( 0 ).REST.setNetCfg( cfg[ 'basic' ],
968 subjectClass="hosts",
969 subjectKey=urllib.quote( mac,
970 safe='' ),
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700971 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700972 main.pingChart.update( { 'vlan1': { "expect": "True",
973 "hosts": [ "olt1", "vsg1" ] } } )
974 main.pingChart[ 'vlan5' ][ 'expect' ] = 0
975 main.pingChart[ 'vlan10' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700976 ports = "[%s,%s]" % ( 5, 6 )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700977 cfg = '{"of:0000000000000001":[{"vlan":1,"ports":%s,"name":"OLT 1"}]}' % ports
Devin Lim142b5342017-07-20 15:22:39 -0700978 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( cfg ),
979 subjectClass="apps",
980 subjectKey="org.onosproject.segmentrouting",
981 configKey="xconnect" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700982
983 @staticmethod
984 def delHostCfg( main ):
985 """
986 Removest Host Configuration from ONOS
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700987 Updates expected state of the network ( pingChart )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700988 """
989 import json
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700990 hostCfg = {}
Devin Lim57221b02018-02-14 15:45:36 -0800991 with open( main.configPath + main.forJson + "extra.json" ) as template:
Jon Hall1efcb3f2016-08-23 13:42:15 -0700992 hostCfg = json.load( template )
993 main.step( "Removing host configuration" )
994 main.pingChart[ 'ip' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700995 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -0700996 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="hosts",
997 subjectKey=urllib.quote(
998 mac,
999 safe='' ),
1000 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001001 main.step( "Removing configuration" )
1002 main.pingChart[ 'ip' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001003 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -07001004 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="hosts",
1005 subjectKey=urllib.quote(
1006 mac,
1007 safe='' ),
1008 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001009 main.step( "Removing vlan configuration" )
1010 main.pingChart[ 'vlan1' ][ 'expect' ] = 0
Devin Lim142b5342017-07-20 15:22:39 -07001011 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="apps",
1012 subjectKey="org.onosproject.segmentrouting",
1013 configKey="xconnect" )
You Wang53dba1e2018-02-02 17:45:44 -08001014
1015 @staticmethod
1016 def verifyNetworkHostIp( main, attempts=10, sleep=10 ):
1017 """
1018 Verifies IP address assignment from the hosts
1019 """
1020 main.step( "Verify IP address assignment from hosts" )
1021 ipResult = main.TRUE
You Wangd66de192018-04-30 17:30:12 -07001022 main.Network.update()
You Wang6acb7a42018-05-04 15:12:25 -07001023 # Find out names of disconnected hosts
1024 disconnectedHosts = []
1025 if hasattr( main, "disconnectedIpv4Hosts" ):
1026 for host in main.disconnectedIpv4Hosts:
1027 disconnectedHosts.append( host )
1028 if hasattr( main, "disconnectedIpv6Hosts" ):
1029 for host in main.disconnectedIpv6Hosts:
1030 disconnectedHosts.append( host )
You Wang53dba1e2018-02-02 17:45:44 -08001031 for hostName, ip in main.expectedHosts[ "network" ].items():
You Wang6acb7a42018-05-04 15:12:25 -07001032 # Exclude disconnected hosts
1033 if hostName in disconnectedHosts:
1034 main.log.debug( "Skip verifying IP for {} as it's disconnected".format( hostName ) )
1035 continue
You Wang53dba1e2018-02-02 17:45:44 -08001036 ipResult = ipResult and utilities.retry( main.Network.verifyHostIp,
1037 main.FALSE,
1038 kwargs={ 'hostList': [ hostName ],
You Wangd66de192018-04-30 17:30:12 -07001039 'prefix': ip,
1040 'update': False },
You Wang53dba1e2018-02-02 17:45:44 -08001041 attempts=attempts,
1042 sleep=sleep )
1043 utilities.assert_equals( expect=main.TRUE, actual=ipResult,
1044 onpass="Verify network host IP succeded",
1045 onfail="Verify network host IP failed" )
1046
1047 @staticmethod
1048 def verifyOnosHostIp( main, attempts=10, sleep=10 ):
1049 """
1050 Verifies host IP address assignment from ONOS
1051 """
1052 main.step( "Verify host IP address assignment in ONOS" )
1053 ipResult = main.TRUE
You Wang6acb7a42018-05-04 15:12:25 -07001054 # Find out IPs of disconnected hosts
1055 disconnectedIps = []
1056 if hasattr( main, "disconnectedIpv4Hosts" ):
1057 for host in main.disconnectedIpv4Hosts:
1058 disconnectedIps.append( main.expectedHosts[ "network" ][ host ] )
1059 if hasattr( main, "disconnectedIpv6Hosts" ):
1060 for host in main.disconnectedIpv6Hosts:
1061 disconnectedIps.append( main.expectedHosts[ "network" ][ host ] )
You Wang53dba1e2018-02-02 17:45:44 -08001062 for hostName, ip in main.expectedHosts[ "onos" ].items():
You Wang6acb7a42018-05-04 15:12:25 -07001063 # Exclude disconnected hosts
1064 if ip in disconnectedIps:
1065 main.log.debug( "Skip verifying IP for {} as it's disconnected".format( ip ) )
1066 continue
You Wang53dba1e2018-02-02 17:45:44 -08001067 ipResult = ipResult and utilities.retry( main.Cluster.active( 0 ).verifyHostIp,
1068 main.FALSE,
1069 kwargs={ 'hostList': [ hostName ],
1070 'prefix': ip },
1071 attempts=attempts,
1072 sleep=sleep )
1073 utilities.assert_equals( expect=main.TRUE, actual=ipResult,
1074 onpass="Verify ONOS host IP succeded",
1075 onfail="Verify ONOS host IP failed" )
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08001076
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08001077 @staticmethod
1078 def updateIntfCfg( main, connectPoint, ips=[], untagged=0, tagged=[], native=0 ):
1079 """
1080 Description:
1081 Updates interface configuration in ONOS, with given IP and vlan parameters
1082 Required:
1083 * connectPoint: connect point to update configuration
1084 Optional:
1085 * ips: list of IP addresses, combined with '/xx' subnet representation,
1086 corresponding to 'ips' field in the configuration
1087 * untagged: vlan ID as an integer, corresponding to 'vlan-untagged' field in the configuration
1088 * tagged: integer list of vlan IDs, corresponding to 'vlan-tagged' field in the configuration
1089 * native: vlan ID as an integer, corresponding to 'vlan-native' field in the configuration
1090 """
1091 cfg = dict()
1092 cfg[ "ports" ] = dict()
1093 cfg[ "ports" ][ connectPoint ] = dict()
1094 cfg[ "ports" ][ connectPoint ][ "interfaces" ] = [ dict() ]
1095 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "ips" ] = ips
1096 if untagged > 0:
1097 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "vlan-untagged" ] = untagged
1098 else:
1099 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "vlan-tagged" ] = tagged
1100 if native > 0:
1101 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "vlan-native" ] = native
1102
1103 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( json.dumps( cfg ) ) )
You Wange24d6272018-03-27 21:18:50 -07001104
1105 @staticmethod
1106 def startScapyHosts( main ):
1107 """
1108 Create host components and start Scapy CLIs
1109 """
1110 main.step( "Start Scapy CLIs" )
1111 main.scapyHostNames = main.params[ 'SCAPY' ][ 'HOSTNAMES' ].split( ',' )
1112 main.scapyHosts = []
1113 for hostName in main.scapyHostNames:
1114 main.Scapy.createHostComponent( hostName )
1115 main.scapyHosts.append( getattr( main, hostName ) )
1116 for host in main.scapyHosts:
1117 host.startHostCli()
1118 host.startScapy()
1119 host.updateSelf()
1120 main.log.debug( host.name )
1121 main.log.debug( host.hostIp )
1122 main.log.debug( host.hostMac )
1123
1124 @staticmethod
You Wang547893e2018-05-08 13:34:59 -07001125 def verifyMulticastTraffic( main, routeName, expect, skipOnFail=True, maxRetry=1 ):
You Wange24d6272018-03-27 21:18:50 -07001126 """
1127 Verify multicast traffic using scapy
1128 """
You Wangc564c6f2018-05-01 15:24:57 -07001129 from tests.dependencies.topology import Topology
1130 try:
1131 main.topo
1132 except ( NameError, AttributeError ):
1133 main.topo = Topology()
You Wang85747762018-05-11 15:51:50 -07001134 main.step( "Verify {} multicast traffic".format( routeName ) )
You Wangc02d8352018-04-17 16:42:10 -07001135 routeData = main.multicastConfig[ routeName ]
1136 srcs = main.mcastRoutes[ routeName ][ "src" ]
1137 dsts = main.mcastRoutes[ routeName ][ "dst" ]
1138 main.log.info( "Sending multicast traffic from {} to {}".format( [ routeData[ "src" ][ i ][ "host" ] for i in srcs ],
1139 [ routeData[ "dst" ][ i ][ "host" ] for i in dsts ] ) )
You Wang85747762018-05-11 15:51:50 -07001140 result = main.TRUE
You Wangc02d8352018-04-17 16:42:10 -07001141 for src in srcs:
1142 srcEntry = routeData[ "src" ][ src ]
1143 for dst in dsts:
1144 dstEntry = routeData[ "dst" ][ dst ]
1145 sender = getattr( main, srcEntry[ "host" ] )
1146 receiver = getattr( main, dstEntry[ "host" ] )
1147 main.Network.addRoute( str( srcEntry[ "host" ] ),
1148 str( routeData[ "group" ] ),
1149 str( srcEntry[ "interface" ] ),
1150 True if routeData[ "ipVersion" ] == 6 else False )
1151 # Build the packet
1152 sender.buildEther( dst=str( srcEntry[ "Ether" ] ) )
1153 if routeData[ "ipVersion" ] == 4:
1154 sender.buildIP( dst=str( routeData[ "group" ] ) )
1155 elif routeData[ "ipVersion" ] == 6:
1156 sender.buildIPv6( dst=str( routeData[ "group" ] ) )
1157 sender.buildUDP( ipVersion=routeData[ "ipVersion" ], dport=srcEntry[ "UDP" ] )
1158 sIface = srcEntry[ "interface" ]
1159 dIface = dstEntry[ "interface" ] if "interface" in dstEntry.keys() else None
1160 pktFilter = srcEntry[ "filter" ]
1161 pkt = srcEntry[ "packet" ]
1162 # Send packet and check received packet
1163 expectedResult = expect.pop( 0 ) if isinstance( expect, list ) else expect
You Wangc564c6f2018-05-01 15:24:57 -07001164 t3Cmd = "t3-troubleshoot -vv -sp {} -et ipv{} -d {} -dm {}".format( srcEntry[ "port" ], routeData[ "ipVersion" ],
Jon Halla604fd42018-05-04 14:27:27 -07001165 routeData[ "group" ], srcEntry[ "Ether" ] )
You Wangc564c6f2018-05-01 15:24:57 -07001166 trafficResult = main.topo.sendScapyPackets( sender, receiver, pktFilter, pkt, sIface, dIface,
1167 expectedResult, maxRetry, True, t3Cmd )
You Wang85747762018-05-11 15:51:50 -07001168 if not trafficResult:
1169 result = main.FALSE
1170 main.log.warn( "Scapy result from {} to {} is not as expected".format( srcEntry[ "host" ],
1171 dstEntry[ "host" ] ) )
1172 utilities.assert_equals( expect=main.TRUE,
1173 actual=result,
1174 onpass="Verify {} multicast traffic: Pass".format( routeName ),
1175 onfail="Verify {} multicast traffic: Fail".format( routeName ) )
1176 if skipOnFail and trafficResult != main.TRUE:
1177 Testcaselib.saveOnosDiagnostics( main )
1178 Testcaselib.cleanup( main, copyKarafLog=False )
1179 main.skipCase()
You Wangc02d8352018-04-17 16:42:10 -07001180
1181 @staticmethod
You Wang85747762018-05-11 15:51:50 -07001182 def verifyPing( main, srcList, dstList, ipv6=False, expect=True, wait=1,
1183 acceptableFailed=0, skipOnFail=True, stepMsg="Verify Ping" ):
You Wang5da39c82018-04-26 22:55:08 -07001184 """
1185 Verify reachability from each host in srcList to each host in dstList
1186 """
1187 from tests.dependencies.topology import Topology
1188 try:
1189 main.topo
1190 except ( NameError, AttributeError ):
1191 main.topo = Topology()
You Wang85747762018-05-11 15:51:50 -07001192 main.step( stepMsg )
You Wang5da39c82018-04-26 22:55:08 -07001193 pingResult = main.topo.ping( srcList, dstList, ipv6, expect, wait, acceptableFailed, skipOnFail )
You Wang85747762018-05-11 15:51:50 -07001194 utilities.assert_equals( expect=main.TRUE,
1195 actual=pingResult,
1196 onpass="{}: Pass".format( stepMsg ),
1197 onfail="{}: Fail".format( stepMsg ) )
You Wang5da39c82018-04-26 22:55:08 -07001198 if not pingResult and skipOnFail:
1199 Testcaselib.saveOnosDiagnostics( main )
1200 Testcaselib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
1201 main.skipCase()
You Wangbc898b82018-05-03 16:22:34 -07001202
1203 @staticmethod
You Wang85747762018-05-11 15:51:50 -07001204 def verifyHostLocations( main, locationDict, retry=2 ):
You Wangbc898b82018-05-03 16:22:34 -07001205 """
1206 Verify if the specified host is discovered by ONOS on the given locations
1207 Required:
You Wang85747762018-05-11 15:51:50 -07001208 locationDict: a dictionary that maps host names to expected locations.
1209 locations could be a string or a list.
1210 ex. { "h1v4": ["of:0000000000000005/8"] }
You Wangbc898b82018-05-03 16:22:34 -07001211 Returns:
1212 main.TRUE if host is discovered on all locations provided, otherwise main.FALSE
1213 """
You Wang85747762018-05-11 15:51:50 -07001214 main.step( "Verify locations of hosts {}".format( locationDict.keys() ) )
1215 result = main.TRUE
1216 for hostName, locations in locationDict.items():
1217 main.log.info( "Verify host {} is discovered at {}".format( hostName, locations ) )
1218 hostIp = main.Network.getIPAddress( hostName, proto='IPV4' )
1219 if not hostIp:
1220 hostIp = main.Network.getIPAddress( hostName, proto='IPV6' )
1221 if not hostIp:
1222 main.log.warn( "Failed to find IP address for host {}, skipping location verification".format( hostName ) )
1223 result = main.FALSE
1224 continue
1225 locationResult = utilities.retry( main.Cluster.active( 0 ).CLI.verifyHostLocation,
1226 main.FALSE,
1227 args=( hostIp, locations ),
1228 attempts=retry + 1,
1229 sleep=10 )
1230 if not locationResult:
1231 result = main.FALSE
1232 main.log.warn( "location verification for host {} failed".format( hostName ) )
You Wang547893e2018-05-08 13:34:59 -07001233 utilities.assert_equals( expect=main.TRUE, actual=result,
You Wang85747762018-05-11 15:51:50 -07001234 onpass="Location verification passed",
1235 onfail="Location verification failed" )
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001236
1237 @staticmethod
1238 def moveHost( main, hostName, srcSw, dstSw, gw, macAddr=None, prefixLen=None, cfg='', ipv6=False ):
1239 """
1240 Move specified host from srcSw to dstSw.
1241 If srcSw and dstSw are same, the host will be moved from current port to
1242 next available port.
1243 Required:
1244 hostName: name of the host. e.g., "h1"
1245 srcSw: name of the switch that the host is attached to. e.g., "leaf1"
1246 dstSw: name of the switch that the host will be moved to. e.g., "leaf2"
1247 gw: ip address of the gateway of the new location
1248 Optional:
1249 macAddr: if specified, change MAC address of the host to the specified MAC address.
1250 prefixLen: prefix length
1251 cfg: port configuration as JSON string
1252 ipv6: Use True to move IPv6 host
1253 """
1254
1255 if not hasattr( main, 'Mininet1' ):
1256 main.log.warn( "moveHost is supposed to be used only in Mininet." )
1257 return
1258
1259 if ipv6:
1260 main.Mininet1.moveHostv6( hostName, srcSw, dstSw, macAddr )
1261 else:
1262 main.Mininet1.moveHost( hostName, srcSw, dstSw, macAddr, prefixLen )
1263
1264 main.Mininet1.changeDefaultGateway( hostName, gw )
1265 if cfg:
1266 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( cfg ),
1267 subjectClass="ports" )
1268
1269 main.Mininet1.discoverHosts( [ hostName, ] )
1270
1271 # Update expectedHost when MAC address is changed.
1272 if macAddr is not None:
1273 ipAddr = main.expectedHosts[ "network" ][ hostName ]
1274 if ipAddr is not None:
1275 for hostName, ip in main.expectedHosts[ "onos" ].items():
1276 if ip == ipAddr:
1277 vlan = hostName.split( "/" )[ -1 ]
1278 del main.expectedHosts[ "onos" ][ hostName ]
1279 main.expectedHosts[ "onos" ][ "{}/{}".format( macAddr, vlan ) ] = ip
1280 break