blob: 6d1d21f224139a307afb34ae14eb0075427ba8b2 [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 Hallf6aeda22020-07-28 09:12:56 -070026import pexpect
Jon Hall1efcb3f2016-08-23 13:42:15 -070027from core import utilities
28
29
30class Testcaselib:
Pierfb719b12016-09-19 14:51:44 -070031
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070032 useSSH = True
Pierfb719b12016-09-19 14:51:44 -070033
Jon Hall1efcb3f2016-08-23 13:42:15 -070034 @staticmethod
35 def initTest( main ):
36 """
37 - Construct tests variables
38 - GIT ( optional )
39 - Checkout ONOS master branch
40 - Pull latest ONOS code
41 - Building ONOS ( optional )
42 - Install ONOS package
43 - Build ONOS package
44 """
Devin Lim58046fa2017-07-05 16:55:00 -070045 try:
46 from tests.dependencies.ONOSSetup import ONOSSetup
47 main.testSetUp = ONOSSetup()
48 except ImportError:
49 main.log.error( "ONOSSetup not found. exiting the test" )
Devin Lim44075962017-08-11 10:56:37 -070050 main.cleanAndExit()
You Wangd5873482018-01-24 12:30:00 -080051 from tests.dependencies.Network import Network
Jon Hall627b1572020-12-01 12:01:15 -080052 main.persistentSetup = main.params.get( "persistent_setup" )
You Wangd5873482018-01-24 12:30:00 -080053 main.Network = Network()
Jon Hall43060f62020-06-23 13:13:33 -070054 main.physicalNet = False
Devin Lim0c972b72018-02-08 14:53:59 -080055 main.testSetUp.envSetupDescription( False )
Jon Hall39570262020-11-17 12:18:19 -080056 main.logdirBase = main.logdir
Devin Lim58046fa2017-07-05 16:55:00 -070057 stepResult = main.FALSE
58 try:
Devin Lim58046fa2017-07-05 16:55:00 -070059 # Test variables
60 main.cellName = main.params[ 'ENV' ][ 'cellName' ]
61 main.apps = main.params[ 'ENV' ][ 'cellApps' ]
Devin Lim58046fa2017-07-05 16:55:00 -070062 main.path = os.path.dirname( main.testFile )
Devin Lim57221b02018-02-14 15:45:36 -080063 main.useCommonTopo = main.params[ 'DEPENDENCY' ][ 'useCommonTopo' ] == 'True'
64 main.topoPath = main.path + ( "/.." if main.useCommonTopo else "" ) + "/dependencies/"
65 main.useCommonConf = main.params[ 'DEPENDENCY' ][ 'useCommonConf' ] == 'True'
You Wang68568b12019-03-04 11:49:57 -080066 if main.params[ 'DEPENDENCY' ].get( 'useBmv2' ):
67 main.useBmv2 = main.params[ 'DEPENDENCY' ][ 'useBmv2' ] == 'True'
68 else:
69 main.useBmv2 = False
Jon Hall43060f62020-06-23 13:13:33 -070070 if main.useBmv2:
71 main.switchType = main.params[ 'DEPENDENCY' ].get( 'bmv2SwitchType', 'stratum' )
72 else:
73 main.switchType = "ovs"
74
Devin Lim57221b02018-02-14 15:45:36 -080075 main.configPath = main.path + ( "/.." if main.useCommonConf else "" ) + "/dependencies/"
Jon Hallbc1c1c92020-05-27 09:29:30 -070076 main.bmv2Path = "/tools/dev/mininet/"
Devin Lim57221b02018-02-14 15:45:36 -080077 main.forJson = "json/"
Siddesh606bd872021-06-29 23:42:36 +000078 main.forcfg = "netcfg/"
Devin Lim57221b02018-02-14 15:45:36 -080079 main.forChart = "chart/"
80 main.forConfig = "conf/"
81 main.forHost = "host/"
You Wang27317572018-03-06 12:13:11 -080082 main.forSwitchFailure = "switchFailure/"
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -080083 main.forLinkFailure = "linkFailure/"
You Wange24d6272018-03-27 21:18:50 -070084 main.forMulticast = "multicast/"
Devin Lim58046fa2017-07-05 16:55:00 -070085 main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
You Wangd87b2312018-01-30 12:47:17 -080086 main.topologyLib = main.params[ 'DEPENDENCY' ][ 'lib' ] if 'lib' in main.params[ 'DEPENDENCY' ] else None
87 main.topologyConf = main.params[ 'DEPENDENCY' ][ 'conf' ] if 'conf' in main.params[ 'DEPENDENCY' ] else None
You Wang68568b12019-03-04 11:49:57 -080088 main.bmv2 = "bmv2.py"
Jon Halldac3eae2020-06-05 12:04:06 -070089 main.stratumRoot = main.params[ 'DEPENDENCY'][ 'stratumRoot'] if 'stratumRoot' in main.params[ 'DEPENDENCY' ] else None
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070090 main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
Devin Lim58046fa2017-07-05 16:55:00 -070091 main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
Jon Hall3c0114c2020-08-11 15:07:42 -070092 main.trellisOar = main.params[ 'DEPENDENCY' ][ 'trellisOar' ] if 'trellisOar' in main.params[ 'DEPENDENCY' ] else None
You Wang5bf49592020-07-08 18:47:46 -070093 main.t3Oar = main.params[ 'DEPENDENCY' ][ 't3Oar' ] if 't3Oar' in main.params[ 'DEPENDENCY' ] else None
Jon Hall1efcb3f2016-08-23 13:42:15 -070094
Devin Lim0c972b72018-02-08 14:53:59 -080095 stepResult = main.testSetUp.envSetup( False )
Devin Lim58046fa2017-07-05 16:55:00 -070096 except Exception as e:
97 main.testSetUp.envSetupException( e )
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -070098
Jon Hallaa1d9b82020-07-30 13:49:42 -070099 main.testSetUp.envSetupConclusion( stepResult )
Jon Hall32c90f32021-06-24 16:32:44 -0700100
Siddesh167bc882021-03-23 21:03:43 +0000101 @staticmethod
102 def getTopo():
103 topo = dict()
104 # TODO: Check minFlowCount of leaf for BMv2 switch
105 # (number of spine switch, number of leaf switch, dual-homed, description, minFlowCount - leaf (OvS), minFlowCount - leaf (BMv2))
106 topo[ '0x1' ] = { 'spines': 0,'leaves': 1, 'mininetArgs': "--leaf=1 --spine=0", 'dual-homed': False,'description': 'single ToR','minFlow-OvS': 28,'minFlow-Stratum': 20,'dual-linked': False }
107 topo[ '0x2' ] = {'spines': 0,'leaves': 2, 'mininetArgs': "--leaf=2 --spine=0", 'dual-homed': True,'description': 'dual-homed ToR','minFlow-OvS': 37,'minFlow-Stratum': 37,'dual-linked': True }
108 topo[ '2x2' ] = {'spines': 2,'leaves': 2, 'mininetArgs': "--leaf=2 --spine=2", 'dual-homed': False,'description': '2x2 leaf-spine topology','minFlow-OvS': 37,'minFlow-Stratum': 32,'dual-linked': False }
109 topo[ '2x2 dual-linked' ] = {'spines': 2, 'leaves': 2, 'mininetArgs': "--leaf=2 --spine=2", 'dual-homed': False,'description': '2x2 aether dual-linked','minFlow-OvS': 37,'minFlow-Stratum': 32,'dual-linked': True }
110 topo[ '2x4' ] = { 'spines':2,'leaves': 4, 'mininetArgs': "--leaf=4 --spine=2",'dual-homed': True,'description': '2x4 dual-homed leaf-spine topology','minFlow-OvS': 53,'minFlow-Stratum': 53, 'dual-linked': False }
111 topo[ '4x4' ] = {'spines': 4,'leaves': 4, 'dual-homed': True, 'description': '4x4 dual-homed leaf-spine topology','dual-linked': True }
112 topo[ '2x2staging' ] = { 'spines': 2, 'leaves': 2,'dual-homed': True, 'description': '2x2 leaf-spine topology', 'minFlowOvS': 37, 'minFlow-Stratum': 32 }
113 return topo
Jon Hall1efcb3f2016-08-23 13:42:15 -0700114 @staticmethod
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800115 def installOnos( main, vlanCfg=True, skipPackage=False, cliSleep=10,
116 parallel=True ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700117 """
118 - Set up cell
119 - Create cell file
120 - Set cell file
121 - Verify cell file
122 - Kill ONOS process
123 - Uninstall ONOS cluster
124 - Verify ONOS start up
125 - Install ONOS cluster
126 - Connect to cli
127 """
Siddesh13492972021-03-12 21:09:32 +0000128 # Check params file for local repos on external apps. cd to repos, run the build command, potentially move o/p file to a different location
129
Jon Hall1efcb3f2016-08-23 13:42:15 -0700130 # main.scale[ 0 ] determines the current number of ONOS controller
Jon Hall43060f62020-06-23 13:13:33 -0700131 try:
Jon Hall627b1572020-12-01 12:01:15 -0800132 if not main.persistentSetup and main.params.get( 'EXTERNAL_APPS' ):
Jon Hall43060f62020-06-23 13:13:33 -0700133 for app, url in main.params[ 'EXTERNAL_APPS' ].iteritems():
Jon Hall39570262020-11-17 12:18:19 -0800134 main.log.info( "Downloading %s app from %s" % ( app, url ) )
Jon Hall43060f62020-06-23 13:13:33 -0700135 main.ONOSbench.onosFetchApp( url )
136 if not main.apps:
137 main.log.error( "App list is empty" )
138 except Exception as e:
139 main.log.debug( e )
140 main.cleanAndExit()
Jon Hall3c910162018-03-07 14:42:16 -0800141 main.log.info( "Cluster size: " + str( main.Cluster.numCtrls ) )
142 main.log.info( "Cluster ips: " + ', '.join( main.Cluster.getIps() ) )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700143 main.dynamicHosts = [ 'in1', 'out1' ]
You Wanga0f6ff62018-01-11 15:46:30 -0800144 main.testSetUp.ONOSSetUp( main.Cluster, newCell=True, cellName=main.cellName,
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800145 skipPack=skipPackage,
146 useSSH=Testcaselib.useSSH,
Devin Lim0c972b72018-02-08 14:53:59 -0800147 installParallel=parallel, includeCaseDesc=False )
Devin Lim142b5342017-07-20 15:22:39 -0700148 ready = utilities.retry( main.Cluster.active( 0 ).CLI.summary,
You Wang5bf49592020-07-08 18:47:46 -0700149 [ None, main.FALSE ],
You Wang1cdc5f52017-12-19 16:47:51 -0800150 sleep=cliSleep,
Devin Lim142b5342017-07-20 15:22:39 -0700151 attempts=10 )
152 if ready:
153 ready = main.TRUE
154 utilities.assert_equals( expect=main.TRUE, actual=ready,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700155 onpass="ONOS summary command succeded",
156 onfail="ONOS summary command failed" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700157 if not ready:
158 main.log.error( "ONOS startup failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700159 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700160
You Wang5bf49592020-07-08 18:47:46 -0700161 # Install segmentrouting and t3 app
Jon Hall3c0114c2020-08-11 15:07:42 -0700162 appInstallResult = main.TRUE
163 if main.trellisOar:
164 appInstallResult = appInstallResult and main.ONOSbench.onosAppInstall( main.Cluster.runningNodes[0].ipAddress, main.trellisOar)
You Wang5bf49592020-07-08 18:47:46 -0700165 if main.t3Oar:
166 appInstallResult = appInstallResult and main.ONOSbench.onosAppInstall( main.Cluster.runningNodes[0].ipAddress, main.t3Oar)
167 utilities.assert_equals( expect=main.TRUE, actual=appInstallResult,
168 onpass="SR app installation succeded",
169 onfail="SR app installation failed" )
170 if not appInstallResult:
171 main.cleanAndExit()
172
Jon Hall43060f62020-06-23 13:13:33 -0700173 # FIXME: move to somewhere else?
174 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix' )
175 # TODO: Support other pipeconfs/making this configurable
176 if switchPrefix == "tofino":
177 # It seems to take some time for the pipeconfs to be loaded
178 ctrl = main.Cluster.next()
179 for i in range( 120 ):
180 try:
181 main.log.debug( "Checking to see if pipeconfs are loaded" )
182 output = ctrl.CLI.sendline( "pipeconfs" )
183 if "tofino" in output:
184 main.log.debug( "Took around %s seconds for the pipeconf to be loaded" % i )
185 break
186 time.sleep( 1 )
187 except Exception as e:
188 main.log.error( e )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700189
Jon Hall627b1572020-12-01 12:01:15 -0800190 # Install segmentrouting and t3 app
191 appInstallResult = main.TRUE
192 if not main.persistentSetup:
193 if main.trellisOar:
194 appInstallResult = appInstallResult and main.ONOSbench.onosAppInstall( main.Cluster.runningNodes[0].ipAddress, main.trellisOar)
195 if main.t3Oar:
196 appInstallResult = appInstallResult and main.ONOSbench.onosAppInstall( main.Cluster.runningNodes[0].ipAddress, main.t3Oar)
197 utilities.assert_equals( expect=main.TRUE, actual=appInstallResult,
198 onpass="SR app installation succeded",
199 onfail="SR app installation failed" )
200 if not appInstallResult:
201 main.cleanAndExit()
202
Jon Hall43060f62020-06-23 13:13:33 -0700203 Testcaselib.setOnosLogLevels( main )
204 Testcaselib.setOnosConfig( main )
Jon Halldac3eae2020-06-05 12:04:06 -0700205
Jon Hall1efcb3f2016-08-23 13:42:15 -0700206 @staticmethod
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800207 def loadCount( main ):
Jon Hall43060f62020-06-23 13:13:33 -0700208 with open( "%s/count/%s.count" % ( main.configPath, main.cfgName ) ) as count:
209 main.count = json.load( count )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800210
211 @staticmethod
Jon Hall43060f62020-06-23 13:13:33 -0700212 def loadJson( main, suffix='' ):
213 with open( "%s%s.json%s" % ( main.configPath + main.forJson,
214 main.cfgName, suffix ) ) as cfg:
Devin Lim57221b02018-02-14 15:45:36 -0800215 main.Cluster.active( 0 ).REST.setNetCfg( json.load( cfg ) )
216
217 @staticmethod
Siddesh606bd872021-06-29 23:42:36 +0000218 def loadNewJson( main, suffix='' ):
219 returnValue = main.TRUE
220 with open( "%s%s.cfg%s" % ( main.configPath + main.forcfg,
221 main.cfgName, suffix ) ) as cfg:
222 desiredJSON = json.load ( cfg )
223 for device in desiredJSON ["ports"].keys():
224 deviceCfg = desiredJSON[ "ports" ][ device ]
225 currentJSON = main.Cluster.active( 0 ).REST.getNetCfg( subjectClass = "ports", subjectKey = device )
226
227 currentJSON = json.loads( currentJSON )
228 if currentJSON['interfaces'][0]['ips'] != deviceCfg['interfaces'][0]['ips']:
229 currentJSON['interfaces'][0]['ips'] == deviceCfg['interfaces'][0]['ips']
230 data = { 'interfaces': currentJSON['interfaces'] }
231 A = main.Cluster.active( 0 ).REST.setNetCfg( data , subjectClass = "ports", subjectKey = device )
232 returnValue = returnValue and A
233 currentJSON['interfaces'] = deviceCfg['interfaces']
234 data = { 'interfaces': currentJSON['interfaces'] }
235 B = main.Cluster.active( 0 ).REST.setNetCfg( data , subjectClass = "ports", subjectKey = device )
236 returnValue = returnValue and B
237 return returnValue
238
239 @staticmethod
Jon Hall10e2ab82020-09-15 17:14:54 -0700240 def loadXconnects( main, suffix='' ):
241 with open( "%s%s-xconnects.json%s" % ( main.configPath + main.forJson,
242 main.cfgName, suffix ) ) as cfg:
243 for xconnect in json.load( cfg ).get('xconnects'):
244 main.Cluster.active( 0 ).REST.setXconnectJson( xconnect )
245
246 @staticmethod
Devin Lim57221b02018-02-14 15:45:36 -0800247 def loadChart( main ):
248 try:
Jon Hall32c90f32021-06-24 16:32:44 -0700249 filename = "%s%s.chart" % ( main.configPath + main.forChart,
250 main.cfgName )
251 with open( filename ) as chart:
Jon Hall43060f62020-06-23 13:13:33 -0700252 main.pingChart = json.load( chart )
Devin Lim57221b02018-02-14 15:45:36 -0800253 except IOError:
Jon Hall32c90f32021-06-24 16:32:44 -0700254 main.log.warn( "No chart file found at %s" % filename )
Devin Lim57221b02018-02-14 15:45:36 -0800255
256 @staticmethod
257 def loadHost( main ):
258 with open( "%s%s.host" % ( main.configPath + main.forHost,
259 main.cfgName ) ) as host:
260 main.expectedHosts = json.load( host )
261
262 @staticmethod
You Wang27317572018-03-06 12:13:11 -0800263 def loadSwitchFailureChart( main ):
264 with open( "%s%s.switchFailureChart" % ( main.configPath + main.forSwitchFailure,
265 main.cfgName ) ) as sfc:
266 main.switchFailureChart = json.load( sfc )
267
268 @staticmethod
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800269 def loadLinkFailureChart( main ):
270 with open( "%s%s.linkFailureChart" % ( main.configPath + main.forLinkFailure,
You Wange24d6272018-03-27 21:18:50 -0700271 main.cfgName ) ) as lfc:
272 main.linkFailureChart = json.load( lfc )
273
274 @staticmethod
275 def loadMulticastConfig( main ):
276 with open( "%s%s.multicastConfig" % ( main.configPath + main.forMulticast,
277 main.cfgName ) ) as cfg:
278 main.multicastConfig = json.load( cfg )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800279
280 @staticmethod
Jon Hall1efcb3f2016-08-23 13:42:15 -0700281 def startMininet( main, topology, args="" ):
Jon Hall43060f62020-06-23 13:13:33 -0700282 main.log.info( "Copying mininet topology file to mininet machine" )
You Wangd87b2312018-01-30 12:47:17 -0800283 copyResult = main.ONOSbench.scp( main.Mininet1,
284 main.topoPath + main.topology,
You Wang5da39c82018-04-26 22:55:08 -0700285 main.Mininet1.home + "custom",
You Wangd87b2312018-01-30 12:47:17 -0800286 direction="to" )
287 if main.topologyLib:
288 for lib in main.topologyLib.split(","):
289 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
290 main.topoPath + lib,
You Wang5da39c82018-04-26 22:55:08 -0700291 main.Mininet1.home + "custom",
You Wangd87b2312018-01-30 12:47:17 -0800292 direction="to" )
293 if main.topologyConf:
You Wanga877ea42018-04-05 15:27:40 -0700294 import re
295 controllerIPs = [ ctrl.ipAddress for ctrl in main.Cluster.runningNodes ]
296 index = 0
Jon Hall43060f62020-06-23 13:13:33 -0700297 destDir = "~/"
298 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
299 destDir = "/tmp/mn_conf/"
300 # Try to ensure the destination exists
You Wangd87b2312018-01-30 12:47:17 -0800301 for conf in main.topologyConf.split(","):
You Wanga877ea42018-04-05 15:27:40 -0700302 # Update zebra configurations with correct ONOS instance IP
303 if conf in [ "zebradbgp1.conf", "zebradbgp2.conf" ]:
304 ip = controllerIPs[ index ]
305 index = ( index + 1 ) % len( controllerIPs )
306 with open( main.configPath + main.forConfig + conf ) as f:
307 s = f.read()
308 s = re.sub( r"(fpm connection ip).*(port 2620)", r"\1 " + ip + r" \2", s )
309 with open( main.configPath + main.forConfig + conf, "w" ) as f:
310 f.write( s )
You Wangd87b2312018-01-30 12:47:17 -0800311 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
Devin Lim57221b02018-02-14 15:45:36 -0800312 main.configPath + main.forConfig + conf,
Jon Hall43060f62020-06-23 13:13:33 -0700313 destDir,
You Wangd87b2312018-01-30 12:47:17 -0800314 direction="to" )
You Wang68568b12019-03-04 11:49:57 -0800315 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
Jon Hallbc1c1c92020-05-27 09:29:30 -0700316 main.ONOSbench.home + main.bmv2Path + main.bmv2,
You Wang68568b12019-03-04 11:49:57 -0800317 main.Mininet1.home + "custom",
318 direction="to" )
Jon Hall9b0de1f2020-08-24 15:38:04 -0700319
320 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
321 # move the config files into home
322 main.Mininet1.handle.sendline( "cp config/* . " )
323 main.Mininet1.handle.expect( main.Mininet1.Prompt() )
324 main.log.debug( main.Mininet1.handle.before + main.Mininet1.handle.after )
325 main.Mininet1.handle.sendline( "ls -al " )
326 main.Mininet1.handle.expect( main.Mininet1.Prompt() )
327 main.log.debug( main.Mininet1.handle.before + main.Mininet1.handle.after )
328
You Wangd87b2312018-01-30 12:47:17 -0800329 stepResult = copyResult
330 utilities.assert_equals( expect=main.TRUE,
331 actual=stepResult,
332 onpass="Successfully copied topo files",
333 onfail="Failed to copy topo files" )
Jon Halldac3eae2020-06-05 12:04:06 -0700334 if main.stratumRoot:
335 main.Mininet1.handle.sendline( "export STRATUM_ROOT=" + str( main.stratumRoot ) )
Jon Hall3c0114c2020-08-11 15:07:42 -0700336 main.Mininet1.handle.expect( main.Mininet1.Prompt() )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700337 main.step( "Starting Mininet Topology" )
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -0700338 arg = "--onos-ip=%s %s" % (",".join([ctrl.ipAddress for ctrl in main.Cluster.runningNodes]), args)
Jon Hall1efcb3f2016-08-23 13:42:15 -0700339 main.topology = topology
340 topoResult = main.Mininet1.startNet(
You Wang5da39c82018-04-26 22:55:08 -0700341 topoFile=main.Mininet1.home + "custom/" + main.topology, args=arg )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700342 stepResult = topoResult
343 utilities.assert_equals( expect=main.TRUE,
344 actual=stepResult,
345 onpass="Successfully loaded topology",
346 onfail="Failed to load topology" )
347 # Exit if topology did not load properly
348 if not topoResult:
Devin Lim44075962017-08-11 10:56:37 -0700349 main.cleanAndExit()
Jon Hall43060f62020-06-23 13:13:33 -0700350 if main.useBmv2:
Jon Hall3c0114c2020-08-11 15:07:42 -0700351 main.step( "Configure switches in ONOS" )
Jon Hall43060f62020-06-23 13:13:33 -0700352 # Upload the net-cfg file created for each switch
353 filename = "onos-netcfg.json"
354 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700355 switchNetCfg = main.TRUE
Jon Hall43060f62020-06-23 13:13:33 -0700356 for switch in main.Mininet1.getSwitches( switchRegex=r"(StratumBmv2Switch)|(Bmv2Switch)" ).keys():
357 path = "/tmp/mn-stratum/%s/" % switch
358 dstPath = "/tmp/"
359 dstFileName = "%s-onos-netcfg.json" % switch
360 main.ONOSbench1.scp( main.Mininet1,
361 "%s%s" % ( path, filename ),
362 "%s%s" % ( dstPath, dstFileName ),
363 "from" )
364 main.ONOSbench1.handle.sendline( "sudo sed -i 's/localhost/%s/g' %s%s" % ( main.Mininet1.ip_address, dstPath, dstFileName ) )
Jon Hall3c0114c2020-08-11 15:07:42 -0700365 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
Jon Hall43060f62020-06-23 13:13:33 -0700366 # Configure managementAddress
367 main.ONOSbench1.handle.sendline( "sudo sed -i 's/localhost/%s/g' %s%s" % ( main.Mininet1.ip_address, dstPath, dstFileName ) )
368 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
369 main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
370 # Configure device id
371 main.ONOSbench1.handle.sendline( "sudo sed -i 's/device:%s/device:%s:%s/g' %s%s" % ( switch, switchPrefix, switch, dstPath, dstFileName ) )
372 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
373 main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
374 # Configure device name
Jon Hall39570262020-11-17 12:18:19 -0800375 main.ONOSbench1.handle.sendline( "sudo sed -i '/\"basic\"/a\ \"name\": \"%s:%s\",' %s%s" % ( switchPrefix, switch, dstPath, dstFileName ) )
Jon Hall43060f62020-06-23 13:13:33 -0700376 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
377 main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
Jon Hall3c0114c2020-08-11 15:07:42 -0700378 node = main.Cluster.active(0)
379 switchNetCfg = switchNetCfg and node.onosNetCfg( node.server.ip_address,
380 dstPath,
381 dstFileName,
382 user=node.REST.user_name,
383 password=node.REST.pwd )
384 # Stop test if we fail to push switch netcfg
385 utilities.assert_equals( expect=main.TRUE,
386 actual=switchNetCfg,
387 onpass="Successfully pushed switch netcfg",
388 onfail="Failed to configure switches in onos" )
389 if not switchNetCfg:
390 main.cleanAndExit()
Jon Hall43060f62020-06-23 13:13:33 -0700391 # Make sure hosts make some noise
392 Testcaselib.discoverHosts( main )
393
394 @staticmethod
395 def discoverHosts( main ):
396 # TODO add option to only select specific hosts
397 if hasattr( main, "Mininet1" ):
398 network = main.Mininet1
399 elif hasattr( main, "NetworkBench" ):
400 network = main.NetworkBench
401 else:
402 main.log.warn( "Could not find component for test network, skipping host discovery" )
403 return
404 network.discoverHosts()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700405
406 @staticmethod
Jon Hall06fd0df2021-01-25 15:50:06 -0800407 def connectToPhysicalNetwork( main, hostDiscovery=True ):
You Wang84f981d2018-01-12 16:11:50 -0800408 main.step( "Connecting to physical netowrk" )
Jon Hall43060f62020-06-23 13:13:33 -0700409 main.physicalNet = True
You Wang84f981d2018-01-12 16:11:50 -0800410 topoResult = main.NetworkBench.connectToNet()
411 stepResult = topoResult
412 utilities.assert_equals( expect=main.TRUE,
413 actual=stepResult,
Jon Hall43060f62020-06-23 13:13:33 -0700414 onpass="Successfully connected to topology",
415 onfail="Failed to connect to topology" )
You Wang84f981d2018-01-12 16:11:50 -0800416 # Exit if topology did not load properly
417 if not topoResult:
418 main.cleanAndExit()
419
Jon Hall627b1572020-12-01 12:01:15 -0800420 if not main.persistentSetup:
421 # Perform any optional setup
422 for switch in main.NetworkBench.switches:
423 if hasattr( switch, "setup" ):
424 switch.setup() # We might not need this
Jon Hall43060f62020-06-23 13:13:33 -0700425
Jon Hall627b1572020-12-01 12:01:15 -0800426 main.step( "Assign switches to controllers." )
427 stepResult = main.TRUE
428 switches = main.NetworkBench.getSwitches()
429 pool = []
430 for name in switches.keys():
431 # NOTE: although this terminology is ovsdb centric, we can use this function for other switches too
432 # e.g. push onos net-cfg for stratum switches
433 thread = main.Thread( target=main.NetworkBench.assignSwController,
434 name="assignSwitchToController",
435 args=[ name, main.Cluster.getIps(), '6653' ] )
436 pool.append( thread )
437 thread.start()
438 for thread in pool:
439 thread.join( 300 )
440 if not thread.result:
441 stepResult = main.FALSE
442 utilities.assert_equals( expect=main.TRUE,
443 actual=stepResult,
444 onpass="Successfully assign switches to controllers",
445 onfail="Failed to assign switches to controllers" )
You Wang84f981d2018-01-12 16:11:50 -0800446
You Wang4cc61912018-08-28 10:10:58 -0700447 # Check devices
448 Testcaselib.checkDevices( main, switches=int( main.params[ 'TOPO' ][ 'switchNum' ] ) )
You Wang4cc61912018-08-28 10:10:58 -0700449 # Connecting to hosts that only have data plane connectivity
450 main.step( "Connecting inband hosts" )
451 stepResult = main.Network.connectInbandHosts()
452 utilities.assert_equals( expect=main.TRUE,
453 actual=stepResult,
454 onpass="Successfully connected inband hosts",
455 onfail="Failed to connect inband hosts" )
Jon Hall06fd0df2021-01-25 15:50:06 -0800456 if hostDiscovery:
457 Testcaselib.discoverHosts( main )
You Wang4cc61912018-08-28 10:10:58 -0700458
You Wang84f981d2018-01-12 16:11:50 -0800459 @staticmethod
You Wang5df1c6d2018-04-06 18:02:02 -0700460 def saveOnosDiagnostics( main ):
461 """
462 Get onos-diags.tar.gz and save it to the log directory.
463 suffix: suffix string of the file name. E.g. onos-diags-case1.tar.gz
464 """
465 main.log.info( "Collecting onos-diags..." )
Siddesha2938fe2021-04-06 02:46:06 +0000466 for ctrl in main.Cluster.runningNodes:
467 main.ONOSbench.onosDiagnostics( [ctrl.ipAddress], main.logdir,"-CASE%d" % main.CurrentTestCaseNumber, onosPortnumber=ctrl.REST.port )
You Wang5df1c6d2018-04-06 18:02:02 -0700468
469 @staticmethod
Devin Lim142b5342017-07-20 15:22:39 -0700470 def config( main, cfgName ):
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700471 main.spines = []
Piera2a7e1b2016-10-04 11:51:43 -0700472
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700473 main.failures = int( main.params[ 'failures' ] )
474 main.cfgName = cfgName
Piera2a7e1b2016-10-04 11:51:43 -0700475
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700476 if main.cfgName == '2x2':
477 spine = {}
478 spine[ 'name' ] = main.params[ 'switches' ][ 'spine1' ]
479 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid1' ]
480 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700481
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700482 spine = {}
483 spine[ 'name' ] = main.params[ 'switches' ][ 'spine2' ]
484 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid2' ]
485 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700486
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700487 elif main.cfgName == '4x4':
488 spine = {}
489 spine[ 'name' ] = main.params[ 'switches' ][ 'spine1' ]
490 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid1' ]
491 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700492
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700493 spine = {}
494 spine[ 'name' ] = main.params[ 'switches' ][ 'spine2' ]
495 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid2' ]
496 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700497
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700498 spine = {}
499 spine[ 'name' ] = main.params[ 'switches' ][ 'spine3' ]
500 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid3' ]
501 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700502
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700503 spine = {}
504 spine[ 'name' ] = main.params[ 'switches' ][ 'spine4' ]
505 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid4' ]
506 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700507
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700508 else:
Piera2a7e1b2016-10-04 11:51:43 -0700509 main.log.error( "Configuration failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700510 main.cleanAndExit()
You Wang27317572018-03-06 12:13:11 -0800511
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -0800512 @staticmethod
513 def addStaticOnosRoute( main, subnet, intf):
514 """
515 Adds an ONOS static route with the use route-add command.
516 """
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -0800517 routeResult = main.Cluster.active( 0 ).addStaticRoute(subnet, intf)
518
Piera2a7e1b2016-10-04 11:51:43 -0700519 @staticmethod
You Wangc02f3be2018-05-18 12:14:23 -0700520 def checkGroupsForBuckets( main, deviceId, subnetDict, routingTable=30 ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700521 """
522 Check number of groups for each subnet on device deviceId and matches
523 it with an expected value. subnetDict is a dictionarty containing values
524 of the type "10.0.1.0/24" : 5.
525 """
You Wangc02f3be2018-05-18 12:14:23 -0700526 main.step( "Checking if number of groups for subnets in device {0} is as expected.".format( deviceId ) )
527 groups = main.Cluster.active( 0 ).CLI.getGroups( deviceId, groupType="select" )
528 flows = main.Cluster.active( 0 ).CLI.flows( jsonFormat=False, device=deviceId )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700529
You Wangc02f3be2018-05-18 12:14:23 -0700530 result = main.TRUE
531 for subnet, numberInSelect in subnetDict.iteritems():
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700532 for flow in flows.splitlines():
You Wangc02f3be2018-05-18 12:14:23 -0700533 if "tableId={0}".format( routingTable ) in flow and subnet in flow:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700534 # this will match the group id that this flow entry points to, for example :
535 # 0x70000041 in flow entry which contains "deferred=[GROUP:0x70000041], transition=TABLE:60,"
You Wangc02f3be2018-05-18 12:14:23 -0700536 groupId = re.search( r".*GROUP:(0x.*)], transition.*", flow ).groups()[0]
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700537 count = 0
538 for group in groups.splitlines():
You Wangc02f3be2018-05-18 12:14:23 -0700539 if 'id={0}'.format( groupId ) in group:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700540 count += 1
You Wangc02f3be2018-05-18 12:14:23 -0700541 if count - 1 != numberInSelect:
542 result = main.FALSE
543 main.log.warn( "Mismatch in number of buckets of select group, found {0}, expected {1} for subnet {2} on device {3}".format( count - 1, numberInSelect, subnet, deviceId ) )
544 utilities.assert_equals( expect=main.TRUE, actual=result,
545 onpass="All bucket numbers are as expected",
546 onfail="Some bucket numbers are not as expected" )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700547
548 @staticmethod
Jon Hall32c90f32021-06-24 16:32:44 -0700549 def checkFlows( main, minFlowCount, tag="", dumpFlows=True, sleep=10 ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700550 main.step(
Jon Hall39570262020-11-17 12:18:19 -0800551 "Check whether the flow count is >= %s" % minFlowCount )
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900552 if tag == "":
553 tag = 'CASE%d' % main.CurrentTestCaseNumber
Devin Lim142b5342017-07-20 15:22:39 -0700554 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowCount,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700555 main.FALSE,
556 kwargs={ 'min': minFlowCount },
557 attempts=10,
You Wang1cdc5f52017-12-19 16:47:51 -0800558 sleep=sleep )
steven30801eccfe212019-01-24 13:00:42 +0800559 if count == main.FALSE:
560 count = main.Cluster.active( 0 ).CLI.checkFlowCount()
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700561 utilities.assertEquals(
Jon Hall1efcb3f2016-08-23 13:42:15 -0700562 expect=True,
Jon Hall39570262020-11-17 12:18:19 -0800563 actual=( count >= minFlowCount ),
Jon Hall43060f62020-06-23 13:13:33 -0700564 onpass="Flow count looks correct; found %s, expecting at least %s" % ( count, minFlowCount ),
565 onfail="Flow count looks wrong; found %s, expecting at least %s" % ( count, minFlowCount ) )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700566
567 main.step( "Check whether all flow status are ADDED" )
Devin Lim142b5342017-07-20 15:22:39 -0700568 flowCheck = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowsState,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700569 main.FALSE,
570 kwargs={ 'isPENDING': False },
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800571 attempts=5,
You Wang1cdc5f52017-12-19 16:47:51 -0800572 sleep=sleep )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700573 utilities.assertEquals(
Jon Hall1efcb3f2016-08-23 13:42:15 -0700574 expect=main.TRUE,
575 actual=flowCheck,
576 onpass="Flow status is correct!",
577 onfail="Flow status is wrong!" )
Jon Hall32c90f32021-06-24 16:32:44 -0700578 if dumpFlows:
Devin Lim142b5342017-07-20 15:22:39 -0700579 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
Pier50f0bc62016-09-07 17:53:40 -0700580 "flows",
581 main.logdir,
Jon Hall06fd0df2021-01-25 15:50:06 -0800582 tag + "_FlowsBefore",
583 cliPort=main.Cluster.active(0).CLI.karafPort )
Devin Lim142b5342017-07-20 15:22:39 -0700584 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
Pier50f0bc62016-09-07 17:53:40 -0700585 "groups",
586 main.logdir,
Jon Hall06fd0df2021-01-25 15:50:06 -0800587 tag + "_GroupsBefore",
588 cliPort=main.Cluster.active(0).CLI.karafPort )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700589
590 @staticmethod
Pier6a0c4de2018-03-18 16:01:30 -0700591 def checkDevices( main, switches, tag="", sleep=10 ):
592 main.step(
593 "Check whether the switches count is equal to %s" % switches )
594 if tag == "":
595 tag = 'CASE%d' % main.CurrentTestCaseNumber
596 result = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
597 main.FALSE,
598 kwargs={ 'numoswitch': switches},
599 attempts=10,
600 sleep=sleep )
601 utilities.assert_equals( expect=main.TRUE, actual=result,
602 onpass="Device up successful",
603 onfail="Failed to boot up devices?" )
604
605 @staticmethod
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800606 def checkFlowsByDpid( main, dpid, minFlowCount, sleep=10 ):
607 main.step(
Jon Hall39570262020-11-17 12:18:19 -0800608 "Check whether the flow count of device %s >= than %s" % ( dpid, minFlowCount ) )
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800609 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
610 main.FALSE,
611 args=( dpid, minFlowCount ),
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800612 attempts=5,
613 sleep=sleep )
steven30801eccfe212019-01-24 13:00:42 +0800614 if count == main.FALSE:
615 count = main.Cluster.active( 0 ).CLI.checkFlowAddedCount( dpid )
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800616 utilities.assertEquals(
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800617 expect=True,
Jon Hall39570262020-11-17 12:18:19 -0800618 actual=( count >= minFlowCount ),
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800619 onpass="Flow count looks correct: " + str( count ),
steven30801eccfe212019-01-24 13:00:42 +0800620 onfail="Flow count looks wrong: " + str( count ) )
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800621
622 @staticmethod
Jon Hall9677ed32018-04-24 11:16:23 -0700623 def checkFlowEqualityByDpid( main, dpid, flowCount, sleep=10 ):
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800624 main.step(
Jon Hall43060f62020-06-23 13:13:33 -0700625 "Check whether the flow count of device %s is equal to %s" % ( dpid, flowCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800626 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
627 main.FALSE,
Jon Hall9677ed32018-04-24 11:16:23 -0700628 args=( dpid, flowCount, False, 1 ),
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800629 attempts=5,
630 sleep=sleep )
steven30801eccfe212019-01-24 13:00:42 +0800631 if count == main.FALSE:
632 count = main.Cluster.active( 0 ).CLI.checkFlowAddedCount( dpid )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800633 utilities.assertEquals(
634 expect=True,
steven30801eccfe212019-01-24 13:00:42 +0800635 actual=( count == flowCount ),
Jon Hall9677ed32018-04-24 11:16:23 -0700636 onpass="Flow count looks correct: " + str( count ) ,
637 onfail="Flow count looks wrong. found {}, should be {}.".format( count, flowCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800638
639 @staticmethod
640 def checkGroupEqualityByDpid( main, dpid, groupCount, sleep=10):
641 main.step(
Jon Hall43060f62020-06-23 13:13:33 -0700642 "Check whether the group count of device %s is equal to %s" % ( dpid, groupCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800643 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkGroupAddedCount,
644 main.FALSE,
645 args=( dpid, groupCount, False, 1),
646 attempts=5,
647 sleep=sleep )
steven30801eccfe212019-01-24 13:00:42 +0800648 if count == main.FALSE:
steven3080123997972019-01-29 17:01:40 +0800649 count = main.Cluster.active( 0 ).CLI.checkGroupAddedCount( dpid )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800650 utilities.assertEquals(
651 expect=True,
652 actual=( count == groupCount ),
Jon Hall9677ed32018-04-24 11:16:23 -0700653 onpass="Group count looks correct: " + str( count ) ,
654 onfail="Group count looks wrong. found {}, should be {}.".format( count, groupCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800655
656 @staticmethod
Jon Hall9677ed32018-04-24 11:16:23 -0700657 def checkFlowsGroupsFromFile( main ):
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800658
659 for dpid, values in main.count.items():
660 flowCount = values["flows"]
661 groupCount = values["groups"]
Jon Hall9677ed32018-04-24 11:16:23 -0700662 main.log.report( "Check flow count for dpid " + str( dpid ) +
663 ", should be " + str( flowCount ) )
664 Testcaselib.checkFlowEqualityByDpid( main, dpid, flowCount )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800665
Jon Hall9677ed32018-04-24 11:16:23 -0700666 main.log.report( "Check group count for dpid " + str( dpid ) +
667 ", should be " + str( groupCount ) )
668 Testcaselib.checkGroupEqualityByDpid( main, dpid, groupCount )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800669
670 return
671
672 @staticmethod
Jon Hall32c90f32021-06-24 16:32:44 -0700673 def pingAll( main, tag="", dumpFlows=True, acceptableFailed=0, basedOnIp=False,
Jon Hall06fd0df2021-01-25 15:50:06 -0800674 sleep=10, retryAttempts=1, skipOnFail=False, useScapy=True ):
You Wangf19d9f42018-02-23 16:34:19 -0800675 '''
You Wangba231e72018-03-01 13:18:21 -0800676 Verify connectivity between hosts according to the ping chart
677 acceptableFailed: max number of acceptable failed pings.
You Wangf19d9f42018-02-23 16:34:19 -0800678 basedOnIp: if True, run ping or ping6 based on suffix of host names
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800679 retryAttempts: the number of retry ping. Only works for IPv4 hosts.
You Wangf19d9f42018-02-23 16:34:19 -0800680 '''
You Wangba231e72018-03-01 13:18:21 -0800681 main.log.report( "Check host connectivity" )
682 main.log.debug( "Ping chart: %s" % main.pingChart )
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800683 if tag == "":
684 tag = 'CASE%d' % main.CurrentTestCaseNumber
685 for entry in main.pingChart.itervalues():
You Wangba231e72018-03-01 13:18:21 -0800686 main.log.debug( "Entry in ping chart: %s" % entry )
687 expect = entry[ 'expect' ]
688 if expect == "Unidirectional":
689 # Verify ping from each src host to each dst host
690 src = entry[ 'src' ]
691 dst = entry[ 'dst' ]
692 expect = main.TRUE
693 main.step( "Verify unidirectional connectivity from %s to %s with tag %s" % ( str( src ), str( dst ), tag ) )
694 if basedOnIp:
695 if ("v4" in src[0]):
696 pa = main.Network.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed )
697 utilities.assert_equals( expect=expect, actual=pa,
698 onpass="IPv4 connectivity successfully tested",
699 onfail="IPv4 connectivity failed" )
700 if ("v6" in src[0]):
701 pa = main.Network.pingallHostsUnidirectional( src, dst, ipv6=True, acceptableFailed=acceptableFailed )
702 utilities.assert_equals( expect=expect, actual=pa,
703 onpass="IPv6 connectivity successfully tested",
704 onfail="IPv6 connectivity failed" )
Jon Hall43060f62020-06-23 13:13:33 -0700705 elif main.physicalNet:
706 pa = main.NetworkBench.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed, useScapy=True )
707 utilities.assert_equals( expect=expect, actual=pa,
708 onpass="IP connectivity successfully tested",
709 onfail="IP connectivity failed" )
710
You Wangba231e72018-03-01 13:18:21 -0800711 else:
712 pa = main.Network.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed )
713 utilities.assert_equals( expect=expect, actual=pa,
714 onpass="IP connectivity successfully tested",
715 onfail="IP connectivity failed" )
716 else:
717 # Verify ping between each host pair
718 hosts = entry[ 'hosts' ]
719 try:
720 expect = main.TRUE if str(expect).lower() == 'true' else main.FALSE
721 except:
722 expect = main.FALSE
723 main.step( "Verify full connectivity for %s with tag %s" % ( str( hosts ), tag ) )
724 if basedOnIp:
725 if ("v4" in hosts[0]):
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800726 pa = utilities.retry( main.Network.pingallHosts,
727 main.FALSE if expect else main.TRUE,
Jon Hall43060f62020-06-23 13:13:33 -0700728 args=(hosts, ),
729 kwargs={ 'ipv6': False },
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800730 attempts=retryAttempts,
731 sleep=sleep )
You Wangba231e72018-03-01 13:18:21 -0800732 utilities.assert_equals( expect=expect, actual=pa,
733 onpass="IPv4 connectivity successfully tested",
734 onfail="IPv4 connectivity failed" )
735 if ("v6" in hosts[0]):
736 pa = main.Network.pingIpv6Hosts( hosts, acceptableFailed=acceptableFailed )
737 utilities.assert_equals( expect=expect, actual=pa,
738 onpass="IPv6 connectivity successfully tested",
739 onfail="IPv6 connectivity failed" )
Jon Hall43060f62020-06-23 13:13:33 -0700740 elif main.physicalNet:
Jon Hall06fd0df2021-01-25 15:50:06 -0800741 pa = main.Network.pingallHosts( hosts, ipv6=True, useScapy=useScapy )
Jon Hall43060f62020-06-23 13:13:33 -0700742 utilities.assert_equals( expect=expect, actual=pa,
743 onpass="IP connectivity successfully tested",
744 onfail="IP connectivity failed" )
You Wangba231e72018-03-01 13:18:21 -0800745 else:
You Wangf19d9f42018-02-23 16:34:19 -0800746 pa = main.Network.pingallHosts( hosts )
747 utilities.assert_equals( expect=expect, actual=pa,
You Wangba231e72018-03-01 13:18:21 -0800748 onpass="IP connectivity successfully tested",
749 onfail="IP connectivity failed" )
Jon Hall43060f62020-06-23 13:13:33 -0700750 if pa != expect:
You Wang5df1c6d2018-04-06 18:02:02 -0700751 Testcaselib.saveOnosDiagnostics( main )
Jon Hall43060f62020-06-23 13:13:33 -0700752 if skipOnFail and pa != expect:
You Wang24ad2f52018-04-10 10:47:12 -0700753 Testcaselib.cleanup( main, copyKarafLog=False )
You Wang5df1c6d2018-04-06 18:02:02 -0700754 main.skipCase()
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800755
Jon Hall32c90f32021-06-24 16:32:44 -0700756 if dumpFlows:
757 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
758 "flows",
759 main.logdir,
760 tag + "_FlowsOn",
761 cliPort=main.Cluster.active(0).CLI.karafPort )
762 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
763 "groups",
764 main.logdir,
765 tag + "_GroupsOn",
766 cliPort=main.Cluster.active(0).CLI.karafPort )
767
768 @staticmethod
769 def pingAllFabricIntfs( main, srcList, tag="", dumpFlows=True, skipOnFail=False ):
770 '''
771 Verify connectivity between hosts and their fabric interfaces
772 '''
773 main.log.report( "Check host connectivity with fabric" )
774 if tag == "":
775 tag = 'CASE%d' % main.CurrentTestCaseNumber
776 expect = main.TRUE
777 import json
778 import re
779 hostsJson = json.loads( main.Cluster.active( 0 ).hosts() )
780 netcfgJson = json.loads( main.Cluster.active( 0 ).getNetCfg( subjectClass='ports') )
781 for hostname in srcList:
782 try:
783 hostComponent = main.Network.hosts[ str( hostname ) ]
784 srcIface = hostComponent.interfaces[0].get( 'name' )
785 main.step( "Verify fabric connectivity for %s with tag %s" % ( str( hostname ), tag ) )
786 #Get host location, check netcfg for that port's ip
787 hostIp = hostComponent.getIPAddress( iface=srcIface )
788 main.log.warn( "Looking for %s" % hostIp )
789 ips = []
790 for obj in hostsJson:
791 if hostIp in obj['ipAddresses']:
792 for location in obj['locations']:
793 main.log.debug( location )
794 did = location['elementId'].encode( 'utf-8' )
795 port = location['port'].encode( 'utf-8' )
796 m = re.search( '\((\d+)\)', port )
797 if m:
798 port = m.group(1)
799 portId = "%s/%s" % ( did, port )
800 # Lookup ip assigned to this network port
801 ips.extend( [ x.encode( 'utf-8' ) for x in netcfgJson[ portId ][ 'interfaces' ][0][ 'ips' ] ] )
802 ips = set( ips )
803 ipRE = r'(\d+\.\d+\.\d+\.\d+)/\d+|([\w,:]*)/\d+'
804 for ip in ips:
805 ipMatch = re.search( ipRE, ip )
806 if ipMatch:
807 fabricIntfIp = ipMatch.group(1)
808 main.log.debug( "Found %s as gateway ip for %s" % ( fabricIntfIp, hostname ) )
809 pa = hostComponent.ping( fabricIntfIp, interface=srcIface )
810 utilities.assert_equals( expect=expect, actual=pa,
811 onpass="IP connectivity successfully tested",
812 onfail="IP connectivity failed" )
813 if pa != expect:
814 Testcaselib.saveOnosDiagnostics( main )
815 if skipOnFail:
816 Testcaselib.cleanup( main, copyKarafLog=False )
817 main.skipCase()
818 except ValueError:
819 main.log.exception( "Could not get gateway ip for %s" % hostname )
820
821 if dumpFlows:
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800822 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
823 "flows",
824 main.logdir,
Jon Hall06fd0df2021-01-25 15:50:06 -0800825 tag + "_FlowsOn",
826 cliPort=main.Cluster.active(0).CLI.karafPort )
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800827 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
828 "groups",
829 main.logdir,
Jon Hall06fd0df2021-01-25 15:50:06 -0800830 tag + "_GroupsOn",
831 cliPort=main.Cluster.active(0).CLI.karafPort )
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800832
833 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700834 def killLink( main, end1, end2, switches, links, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700835 """
836 end1,end2: identify the switches, ex.: 'leaf1', 'spine1'
837 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
838 Kill a link and verify ONOS can see the proper link change
839 """
Jon Halla604fd42018-05-04 14:27:27 -0700840 if sleep is None:
841 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
842 else:
843 sleep = float( sleep )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700844 main.step( "Kill link between %s and %s" % ( end1, end2 ) )
Jon Halla604fd42018-05-04 14:27:27 -0700845 linkDown = main.Network.link( END1=end1, END2=end2, OPTION="down" )
846 linkDown = linkDown and main.Network.link( END2=end1, END1=end2, OPTION="down" )
Jon Hall214f88b2020-09-21 10:21:42 -0700847 utilities.assert_equals( expect=main.TRUE, actual=linkDown,
848 onpass="Link down successful",
849 onfail="Failed to turn off link?" )
Jon Halla604fd42018-05-04 14:27:27 -0700850 # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
Jon Hall1efcb3f2016-08-23 13:42:15 -0700851 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700852 "Waiting %s seconds for link down to be discovered" % sleep )
853 time.sleep( sleep )
Jon Hall214f88b2020-09-21 10:21:42 -0700854 main.step( "Checking topology after link down" )
Devin Lim142b5342017-07-20 15:22:39 -0700855 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700856 main.FALSE,
857 kwargs={ 'numoswitch': switches,
858 'numolink': links },
859 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700860 sleep=sleep )
Jon Hall214f88b2020-09-21 10:21:42 -0700861 utilities.assert_equals( expect=main.TRUE, actual=topology,
862 onpass="Topology after link down is correct",
863 onfail="Topology after link down is incorrect" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700864
865 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700866 def killLinkBatch( main, links, linksAfter, switches, sleep=None ):
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800867 """
868 links = list of links (src, dst) to bring down.
869 """
870
871 main.step("Killing a batch of links {0}".format(links))
Jon Halla604fd42018-05-04 14:27:27 -0700872 if sleep is None:
873 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
874 else:
875 sleep = float( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800876
877 for end1, end2 in links:
878 main.Network.link( END1=end1, END2=end2, OPTION="down")
879 main.Network.link( END1=end2, END2=end1, OPTION="down")
880
Jon Halla604fd42018-05-04 14:27:27 -0700881 # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800882 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700883 "Waiting %s seconds for links down to be discovered" % sleep )
884 time.sleep( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800885
886 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
887 main.FALSE,
888 kwargs={ 'numoswitch': switches,
889 'numolink': linksAfter },
890 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700891 sleep=sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800892
You Wang2854bce2018-03-30 10:15:32 -0700893 utilities.assert_equals( expect=main.TRUE, actual=topology,
894 onpass="Link batch down successful",
895 onfail="Link batch down failed" )
896
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800897 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700898 def restoreLinkBatch( main, links, linksAfter, switches, sleep=None ):
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800899 """
900 links = list of link (src, dst) to bring up again.
901 """
902
903 main.step("Restoring a batch of links {0}".format(links))
Jon Halla604fd42018-05-04 14:27:27 -0700904 if sleep is None:
905 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
906 else:
907 sleep = float( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800908
909 for end1, end2 in links:
910 main.Network.link( END1=end1, END2=end2, OPTION="up")
911 main.Network.link( END1=end2, END2=end1, OPTION="up")
912
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800913 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700914 "Waiting %s seconds for links up to be discovered" % sleep )
915 time.sleep( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800916
917 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
918 main.FALSE,
919 kwargs={ 'numoswitch': switches,
920 'numolink': linksAfter },
921 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700922 sleep=sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800923
You Wang2854bce2018-03-30 10:15:32 -0700924 utilities.assert_equals( expect=main.TRUE, actual=topology,
925 onpass="Link batch up successful",
926 onfail="Link batch up failed" )
927
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800928 @staticmethod
You Wang85747762018-05-11 15:51:50 -0700929 def disablePortBatch( main, ports, switches=None, links=None, sleep=None ):
930 """
931 Disable a list of switch ports using 'portstate' and verify ONOS can see the proper link change
932 ports: a list of ports to disable ex. [ [ "of:0000000000000001", 1 ] ]
933 switches, links: number of expected switches and links after link change, ex.: '4', '6'
934 """
935 if sleep is None:
936 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
937 else:
938 sleep = float( sleep )
939 main.step( "Disable a batch of ports" )
940 for dpid, port in ports:
941 main.Cluster.active( 0 ).CLI.portstate( dpid=dpid, port=port, state="disable" )
942 main.log.info( "Waiting {} seconds for port down to be discovered".format( sleep ) )
943 time.sleep( sleep )
944 if switches and links:
945 result = main.Cluster.active( 0 ).CLI.checkStatus( numoswitch=switches,
946 numolink=links )
947 utilities.assert_equals( expect=main.TRUE, actual=result,
948 onpass="Port down successful",
949 onfail="Port down failed" )
950
951 @staticmethod
952 def enablePortBatch( main, ports, switches, links, sleep=None ):
953 """
954 Enable a list of switch ports using 'portstate' and verify ONOS can see the proper link change
955 ports: a list of ports to enable ex. [ [ "of:0000000000000001", 1 ] ]
956 switches, links: number of expected switches and links after link change, ex.: '4', '6'
957 """
958 if sleep is None:
959 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
960 else:
961 sleep = float( sleep )
962 main.step( "Enable a batch of ports" )
963 for dpid, port in ports:
964 main.Cluster.active( 0 ).CLI.portstate( dpid=dpid, port=port, state="enable" )
965 main.log.info( "Waiting {} seconds for port up to be discovered".format( sleep ) )
966 time.sleep( sleep )
967 if switches and links:
968 result = main.Cluster.active( 0 ).CLI.checkStatus( numoswitch=switches,
969 numolink=links )
970 utilities.assert_equals( expect=main.TRUE, actual=result,
971 onpass="Port up successful",
972 onfail="Port up failed" )
973
974 @staticmethod
You Wangc02d8352018-04-17 16:42:10 -0700975 def restoreLink( main, end1, end2, switches, links,
Jon Halla604fd42018-05-04 14:27:27 -0700976 portUp=False, dpid1='', dpid2='', port1='', port2='', sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700977 """
978 Params:
979 end1,end2: identify the end switches, ex.: 'leaf1', 'spine1'
You Wangc02d8352018-04-17 16:42:10 -0700980 portUp: enable portstate after restoring link
Jon Hall1efcb3f2016-08-23 13:42:15 -0700981 dpid1, dpid2: dpid of the end switches respectively, ex.: 'of:0000000000000002'
982 port1, port2: respective port of the end switches that connects to the link, ex.:'1'
983 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
984 Kill a link and verify ONOS can see the proper link change
985 """
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700986 main.step( "Restore link between %s and %s" % ( end1, end2 ) )
Jon Halla604fd42018-05-04 14:27:27 -0700987 if sleep is None:
988 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
989 else:
990 sleep = float( sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700991 result = False
992 count = 0
993 while True:
994 count += 1
Jon Halla604fd42018-05-04 14:27:27 -0700995 ctrl = main.Cluster.next()
You Wangd5873482018-01-24 12:30:00 -0800996 main.Network.link( END1=end1, END2=end2, OPTION="up" )
997 main.Network.link( END2=end1, END1=end2, OPTION="up" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700998 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700999 "Waiting %s seconds for link up to be discovered" % sleep )
1000 time.sleep( sleep )
Pierfb719b12016-09-19 14:51:44 -07001001
You Wangc02d8352018-04-17 16:42:10 -07001002 if portUp:
1003 ctrl.CLI.portstate( dpid=dpid1, port=port1, state='Enable' )
1004 ctrl.CLI.portstate( dpid=dpid2, port=port2, state='Enable' )
Jon Hall43060f62020-06-23 13:13:33 -07001005 main.log.info(
1006 "Waiting %s seconds for link up to be discovered" % sleep )
Jon Halla604fd42018-05-04 14:27:27 -07001007 time.sleep( sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001008
Jon Halla604fd42018-05-04 14:27:27 -07001009 result = ctrl.CLI.checkStatus( numoswitch=switches,
1010 numolink=links )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001011 if count > 5 or result:
1012 break
1013 utilities.assert_equals( expect=main.TRUE, actual=result,
1014 onpass="Link up successful",
1015 onfail="Failed to bring link up" )
1016
1017 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -07001018 def killSwitch( main, switch, switches, links, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -07001019 """
1020 Params: switches, links: number of expected switches and links after SwitchDown, ex.: '4', '6'
1021 Completely kill a switch and verify ONOS can see the proper change
1022 """
Jon Halla604fd42018-05-04 14:27:27 -07001023 if sleep is None:
1024 sleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
1025 else:
1026 sleep = float( sleep )
You Wangc02d8352018-04-17 16:42:10 -07001027 switch = switch if isinstance( switch, list ) else [ switch ]
1028 main.step( "Kill " + str( switch ) )
1029 for s in switch:
1030 main.log.info( "Stopping " + s )
1031 main.Network.switch( SW=s, OPTION="stop" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001032 # todo make this repeatable
Jon Halla604fd42018-05-04 14:27:27 -07001033
1034 # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
Jon Hall1efcb3f2016-08-23 13:42:15 -07001035 main.log.info( "Waiting %s seconds for switch down to be discovered" % (
Jon Halla604fd42018-05-04 14:27:27 -07001036 sleep ) )
1037 time.sleep( sleep )
Devin Lim142b5342017-07-20 15:22:39 -07001038 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -07001039 main.FALSE,
1040 kwargs={ 'numoswitch': switches,
1041 'numolink': links },
1042 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -07001043 sleep=sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001044 utilities.assert_equals( expect=main.TRUE, actual=topology,
1045 onpass="Kill switch successful",
1046 onfail="Failed to kill switch?" )
1047
1048 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -07001049 def recoverSwitch( main, switch, switches, links, rediscoverHosts=False, hostsToDiscover=[], sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -07001050 """
1051 Params: switches, links: number of expected switches and links after SwitchUp, ex.: '4', '6'
1052 Recover a switch and verify ONOS can see the proper change
1053 """
Jon Halla604fd42018-05-04 14:27:27 -07001054 if sleep is None:
1055 sleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
1056 else:
1057 sleep = float( sleep )
1058 # TODO make this repeatable
You Wangc02d8352018-04-17 16:42:10 -07001059 switch = switch if isinstance( switch, list ) else [ switch ]
1060 main.step( "Recovering " + str( switch ) )
1061 for s in switch:
1062 main.log.info( "Starting " + s )
1063 main.Network.switch( SW=s, OPTION="start" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001064 main.log.info( "Waiting %s seconds for switch up to be discovered" % (
Jon Halla604fd42018-05-04 14:27:27 -07001065 sleep ) )
1066 time.sleep( sleep )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -07001067 if rediscoverHosts:
You Wang48381752018-05-07 13:50:57 -07001068 main.Network.discoverHosts( hostList=hostsToDiscover )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -07001069 main.log.info( "Waiting %s seconds for hosts to get re-discovered" % (
Jon Halla604fd42018-05-04 14:27:27 -07001070 sleep ) )
1071 time.sleep( sleep )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -07001072
Devin Lim142b5342017-07-20 15:22:39 -07001073 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -07001074 main.FALSE,
1075 kwargs={ 'numoswitch': switches,
1076 'numolink': links },
1077 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -07001078 sleep=sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001079 utilities.assert_equals( expect=main.TRUE, actual=topology,
1080 onpass="Switch recovery successful",
1081 onfail="Failed to recover switch?" )
1082
Jonghwan Hyun25c98a62018-05-04 13:59:09 -07001083 @staticmethod
You Wang0f745de2018-07-27 15:49:22 -07001084 def killRouter( main, router, sleep=None ):
1085 """
1086 Kill bgpd process on a quagga router
1087 router: name of the router to be killed. E.g. "bgp1"
1088 """
1089 sleep = float( sleep )
1090 main.step( "Kill " + str( router ) )
1091 if hasattr( main, 'Mininet1' ):
1092 main.Mininet1.handle.sendline( "px {}.stopProtocols()".format( router ) )
1093 main.Mininet1.handle.expect( "mininet>" )
1094 else:
1095 # TODO: support killing router in physical network
1096 pass
1097 main.log.info( "Waiting %s seconds for router down to be discovered" % ( sleep ) )
1098 time.sleep( sleep )
1099
1100 @staticmethod
1101 def recoverRouter( main, router, sleep=None ):
1102 """
1103 Restart bgpd process on a quagga router
1104 router: name of the router to be recovered. E.g. "bgp1"
1105 """
1106 sleep = float( sleep )
1107 main.step( "Recovering " + str( router ) )
1108 if hasattr( main, 'Mininet1' ):
1109 main.Mininet1.handle.sendline( "px {}.startProtocols()".format( router ) )
1110 main.Mininet1.handle.expect( "mininet>" )
1111 else:
1112 # TODO: support recovering router in physical network
1113 pass
1114 main.log.info( "Waiting %s seconds for router up to be discovered" % ( sleep ) )
1115 time.sleep( sleep )
1116
1117 @staticmethod
You Wang5da39c82018-04-26 22:55:08 -07001118 def cleanup( main, copyKarafLog=True, removeHostComponent=False ):
Jon Hall1efcb3f2016-08-23 13:42:15 -07001119 """
1120 Stop Onos-cluster.
1121 Stops Mininet
1122 Copies ONOS log
1123 """
You Wang4cc61912018-08-28 10:10:58 -07001124 from tests.dependencies.utils import Utils
1125 main.utils = Utils()
Jon Hall627b1572020-12-01 12:01:15 -08001126 if not main.persistentSetup:
1127 for ctrl in main.Cluster.active():
1128 ctrl.CLI.log( "\"Ending Test - Shutting down ONOS and Network\"", level="INFO" )
You Wang4cc61912018-08-28 10:10:58 -07001129 # Clean up scapy hosts
You Wange24d6272018-03-27 21:18:50 -07001130 if hasattr( main, "scapyHosts" ):
1131 scapyResult = main.TRUE
1132 for host in main.scapyHosts:
1133 scapyResult = host.stopScapy() and scapyResult
1134 main.log.info( "Stopped Scapy Host: {0}".format( host.name ) )
1135 for host in main.scapyHosts:
You Wang4cc61912018-08-28 10:10:58 -07001136 if hasattr( main, 'Mininet1' ):
1137 scapyResult = main.Scapy.removeHostComponent( host.name ) and scapyResult
1138 else:
1139 scapyResult = main.Network.removeHostComponent( host.name ) and scapyResult
You Wange24d6272018-03-27 21:18:50 -07001140 main.log.info( "Removed Scapy Host Component: {0}".format( host.name ) )
1141 main.scapyHosts = []
1142
You Wang5da39c82018-04-26 22:55:08 -07001143 if removeHostComponent:
1144 for host in main.internalIpv4Hosts + main.internalIpv6Hosts + main.externalIpv4Hosts + main.externalIpv6Hosts:
1145 if hasattr( main, host ):
You Wang4cc61912018-08-28 10:10:58 -07001146 if hasattr( main, 'Mininet1' ):
1147 pass
1148 else:
1149 getattr( main, host ).disconnectInband()
You Wang5da39c82018-04-26 22:55:08 -07001150 main.Network.removeHostComponent( host )
1151
You Wang5df1c6d2018-04-06 18:02:02 -07001152 if hasattr( main, 'Mininet1' ):
Pier6a0c4de2018-03-18 16:01:30 -07001153 main.utils.mininetCleanup( main.Mininet1 )
You Wang4cc61912018-08-28 10:10:58 -07001154 else:
1155 main.Network.disconnectInbandHosts()
1156 main.Network.disconnectFromNet()
Devin Lim58046fa2017-07-05 16:55:00 -07001157
You Wang5df1c6d2018-04-06 18:02:02 -07001158 if copyKarafLog:
1159 main.utils.copyKarafLog( "CASE%d" % main.CurrentTestCaseNumber, before=True, includeCaseDesc=False )
Devin Lim58046fa2017-07-05 16:55:00 -07001160
Jon Hall627b1572020-12-01 12:01:15 -08001161 if not main.persistentSetup:
1162 for ctrl in main.Cluster.active():
1163 main.ONOSbench.onosStop( ctrl.ipAddress )
Jon Hall06fd0df2021-01-25 15:50:06 -08001164 else:
1165 Testcaselib.resetOnosLogLevels( main )
Jon Hall43060f62020-06-23 13:13:33 -07001166 Testcaselib.mnDockerTeardown( main )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001167
1168 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -07001169 def verifyNodes( main ):
1170 """
1171 Verifies Each active node in the cluster has an accurate view of other node's and their status
1172
1173 Params:
1174 nodes, integer array with position of the ONOS nodes in the CLIs array
1175 """
1176 nodeResults = utilities.retry( main.Cluster.nodesCheck,
1177 False,
1178 attempts=10,
1179 sleep=10 )
1180 utilities.assert_equals( expect=True, actual=nodeResults,
1181 onpass="Nodes check successful",
1182 onfail="Nodes check NOT successful" )
1183
1184 if not nodeResults:
1185 for ctrl in main.Cluster.runningNodes:
1186 main.log.debug( "{} components not ACTIVE: \n{}".format(
1187 ctrl.name,
Jon Hall6c9e2da2018-11-06 12:01:23 -08001188 ctrl.CLI.sendline( "onos:scr-list | grep -v ACTIVE" ) ) )
You Wang0bed5932018-12-11 14:45:41 -08001189 main.log.error( "Failed to verify nodes, stopping test" )
Jon Halla604fd42018-05-04 14:27:27 -07001190 main.cleanAndExit()
1191
1192 @staticmethod
Jon Hall39570262020-11-17 12:18:19 -08001193 def verifyTopology( main, switches, links, expNodes, SCCs=1 ):
Jon Halla604fd42018-05-04 14:27:27 -07001194 """
1195 Verifies that the ONOS cluster has an acuurate view of the topology
1196
1197 Params:
1198 switches, links, expNodes: number of expected switches, links, and nodes at this point in the test ex.: '4', '6', '2'
Jon Hall39570262020-11-17 12:18:19 -08001199 SCCs = Number of connected topology clusters within the control plane, defaults to 1
Jon Halla604fd42018-05-04 14:27:27 -07001200 """
1201 main.step( "Check number of topology elements" )
1202 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
1203 main.FALSE,
1204 kwargs={ 'numoswitch': switches,
1205 'numolink': links,
Jon Hall39570262020-11-17 12:18:19 -08001206 'numoctrl': expNodes,
1207 'numoSCCs': SCCs },
Jon Halla604fd42018-05-04 14:27:27 -07001208 attempts=10,
1209 sleep=12 )
1210 utilities.assert_equals( expect=main.TRUE, actual=topology,
1211 onpass="Number of topology elements are correct",
Jon Hall39570262020-11-17 12:18:19 -08001212 onfail="Unexpected number of links, switches, and/or controllers: " + main.TOPOOUTPUT )
Jon Halla604fd42018-05-04 14:27:27 -07001213
1214 @staticmethod
1215 def killOnos( main, nodes, switches, links, expNodes, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -07001216 """
1217 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
1218 switches, links, nodes: number of expected switches, links and nodes after KillOnos, ex.: '4', '6'
1219 Completely Kill an ONOS instance and verify the ONOS cluster can see the proper change
1220 """
Jon Halla604fd42018-05-04 14:27:27 -07001221 # TODO: We have enough information in the Cluster instance to remove expNodes from here and verifyTopology
Jon Hall3c910162018-03-07 14:42:16 -08001222 main.step( "Killing ONOS instances with index(es): {}".format( nodes ) )
Jon Halla604fd42018-05-04 14:27:27 -07001223 if sleep is None:
1224 sleep = float( main.params[ 'timers' ][ 'OnosDiscovery' ] )
1225 else:
1226 sleep = float( sleep )
Pier3b58c652016-09-26 12:03:31 -07001227
Jon Hall214f88b2020-09-21 10:21:42 -07001228 stepResult = main.TRUE
Jon Hall1efcb3f2016-08-23 13:42:15 -07001229 for i in nodes:
Jon Hall214f88b2020-09-21 10:21:42 -07001230 node = main.Cluster.runningNodes[ i ]
1231 if node.inDocker:
1232 killResult = node.server.dockerStop( node.name )
1233 else:
1234 killResult = main.ONOSbench.onosDie( node.ipAddress )
1235 stepResult = stepResult and killResult
Devin Lim142b5342017-07-20 15:22:39 -07001236 main.Cluster.runningNodes[ i ].active = False
Jon Hall214f88b2020-09-21 10:21:42 -07001237 utilities.assert_equals( expect=main.TRUE, actual=stepResult,
1238 onpass="ONOS instance Killed",
1239 onfail="Error killing ONOS instance" )
Jon Halla604fd42018-05-04 14:27:27 -07001240 main.Cluster.reset()
Jon Hall43060f62020-06-23 13:13:33 -07001241 main.log.debug( "sleeping %i seconds" % ( sleep ) )
Jon Halla604fd42018-05-04 14:27:27 -07001242 time.sleep( sleep )
Pier3b58c652016-09-26 12:03:31 -07001243
Devin Lim142b5342017-07-20 15:22:39 -07001244 if len( nodes ) < main.Cluster.numCtrls:
Jon Halla604fd42018-05-04 14:27:27 -07001245 Testcaselib.verifyNodes( main )
1246 Testcaselib.verifyTopology( main, switches, links, expNodes )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001247
1248 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -07001249 def recoverOnos( main, nodes, switches, links, expNodes, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -07001250 """
1251 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
1252 switches, links, nodes: number of expected switches, links and nodes after recoverOnos, ex.: '4', '6'
1253 Recover an ONOS instance and verify the ONOS cluster can see the proper change
1254 """
Jon Hall3c910162018-03-07 14:42:16 -08001255 main.step( "Recovering ONOS instances with index(es): {}".format( nodes ) )
Jon Halla604fd42018-05-04 14:27:27 -07001256 if sleep is None:
1257 sleep = float( main.params[ 'timers' ][ 'OnosDiscovery' ] )
1258 else:
1259 sleep = float( sleep )
Jon Hall214f88b2020-09-21 10:21:42 -07001260 for i in nodes:
1261 node = main.Cluster.runningNodes[ i ]
1262 if node.inDocker:
1263 main.Cluster.startONOSDockerNode( i )
1264 else:
1265 main.ONOSbench.onosStart( node.ipAddress )
Jon Hall43060f62020-06-23 13:13:33 -07001266 main.log.debug( "sleeping %i seconds" % ( sleep ) )
Jon Halla604fd42018-05-04 14:27:27 -07001267 time.sleep( sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001268 for i in nodes:
Jon Hall39570262020-11-17 12:18:19 -08001269 node = main.Cluster.runningNodes[ i ]
Jon Hall214f88b2020-09-21 10:21:42 -07001270 if node.inDocker:
1271 isUp = node.CLI.dockerExec( node.name, dockerPrompt=node.dockerPrompt )
1272 isUp = isUp and node.CLI.prepareForCLI()
1273 isUp = isUp and node.CLI.onosSecureSSH( userName=node.karafUser, userPWD=node.karafPass )
1274 else:
1275 isUp = main.ONOSbench.isup( node.ipAddress )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001276 utilities.assert_equals( expect=main.TRUE, actual=isUp,
1277 onpass="ONOS service is ready",
1278 onfail="ONOS service did not start properly" )
1279 for i in nodes:
1280 main.step( "Checking if ONOS CLI is ready" )
Devin Lim142b5342017-07-20 15:22:39 -07001281 ctrl = main.Cluster.runningNodes[ i ]
Jonghwan Hyun76a02b72018-01-30 16:40:48 +09001282 # ctrl.CLI.startCellCli()
Devin Lim142b5342017-07-20 15:22:39 -07001283 cliResult = ctrl.CLI.startOnosCli( ctrl.ipAddress,
1284 commandlineTimeout=60,
1285 onosStartTimeout=100 )
1286 ctrl.active = True
Jon Hall1efcb3f2016-08-23 13:42:15 -07001287 utilities.assert_equals( expect=main.TRUE,
1288 actual=cliResult,
1289 onpass="ONOS CLI is ready",
1290 onfail="ONOS CLI is not ready" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001291
Jon Halla604fd42018-05-04 14:27:27 -07001292 main.Cluster.reset()
Pier3b58c652016-09-26 12:03:31 -07001293 main.step( "Checking ONOS nodes" )
Jon Halla604fd42018-05-04 14:27:27 -07001294 Testcaselib.verifyNodes( main )
1295 Testcaselib.verifyTopology( main, switches, links, expNodes )
Pier3b58c652016-09-26 12:03:31 -07001296
Devin Lim142b5342017-07-20 15:22:39 -07001297 ready = utilities.retry( main.Cluster.active( 0 ).CLI.summary,
You Wang5bf49592020-07-08 18:47:46 -07001298 [ None, main.FALSE ],
Devin Lim142b5342017-07-20 15:22:39 -07001299 attempts=10,
1300 sleep=12 )
1301 if ready:
1302 ready = main.TRUE
1303 utilities.assert_equals( expect=main.TRUE, actual=ready,
Jon Hall1efcb3f2016-08-23 13:42:15 -07001304 onpass="ONOS summary command succeded",
1305 onfail="ONOS summary command failed" )
1306 if not ready:
1307 main.log.error( "ONOS startup failed!" )
Devin Lim44075962017-08-11 10:56:37 -07001308 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -07001309
1310 @staticmethod
1311 def addHostCfg( main ):
1312 """
1313 Adds Host Configuration to ONOS
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001314 Updates expected state of the network ( pingChart )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001315 """
1316 import json
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001317 hostCfg = {}
Devin Lim57221b02018-02-14 15:45:36 -08001318 with open( main.configPath + main.forJson + "extra.json" ) as template:
Jon Hall1efcb3f2016-08-23 13:42:15 -07001319 hostCfg = json.load( template )
1320 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'in1' ]
1321 main.step( "Pushing new configuration" )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001322 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -07001323 main.Cluster.active( 0 ).REST.setNetCfg( cfg[ 'basic' ],
1324 subjectClass="hosts",
1325 subjectKey=urllib.quote( mac,
1326 safe='' ),
1327 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001328 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'out1' ]
1329 main.step( "Pushing new configuration" )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001330 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -07001331 main.Cluster.active( 0 ).REST.setNetCfg( cfg[ 'basic' ],
1332 subjectClass="hosts",
1333 subjectKey=urllib.quote( mac,
1334 safe='' ),
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001335 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001336 main.pingChart.update( { 'vlan1': { "expect": "True",
1337 "hosts": [ "olt1", "vsg1" ] } } )
1338 main.pingChart[ 'vlan5' ][ 'expect' ] = 0
1339 main.pingChart[ 'vlan10' ][ 'expect' ] = 0
Jon Hall10e2ab82020-09-15 17:14:54 -07001340 main.Cluster.active( 0 ).REST.setXconnect( "of:0000000000000001",
1341 vlanId=1,
1342 port1=5,
1343 port2=6 )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001344
1345 @staticmethod
1346 def delHostCfg( main ):
1347 """
1348 Removest Host Configuration from ONOS
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001349 Updates expected state of the network ( pingChart )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001350 """
1351 import json
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001352 hostCfg = {}
Devin Lim57221b02018-02-14 15:45:36 -08001353 with open( main.configPath + main.forJson + "extra.json" ) as template:
Jon Hall1efcb3f2016-08-23 13:42:15 -07001354 hostCfg = json.load( template )
1355 main.step( "Removing host configuration" )
1356 main.pingChart[ 'ip' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001357 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -07001358 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="hosts",
1359 subjectKey=urllib.quote(
1360 mac,
1361 safe='' ),
1362 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001363 main.step( "Removing configuration" )
1364 main.pingChart[ 'ip' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001365 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -07001366 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="hosts",
1367 subjectKey=urllib.quote(
1368 mac,
1369 safe='' ),
1370 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001371 main.step( "Removing vlan configuration" )
1372 main.pingChart[ 'vlan1' ][ 'expect' ] = 0
Jon Hall10e2ab82020-09-15 17:14:54 -07001373 main.Cluster.active( 0 ).REST.deleteXconnect( "of:0000000000000001",
1374 vlanId=1 )
You Wang53dba1e2018-02-02 17:45:44 -08001375
1376 @staticmethod
1377 def verifyNetworkHostIp( main, attempts=10, sleep=10 ):
1378 """
1379 Verifies IP address assignment from the hosts
1380 """
1381 main.step( "Verify IP address assignment from hosts" )
1382 ipResult = main.TRUE
You Wangd66de192018-04-30 17:30:12 -07001383 main.Network.update()
You Wang6acb7a42018-05-04 15:12:25 -07001384 # Find out names of disconnected hosts
1385 disconnectedHosts = []
1386 if hasattr( main, "disconnectedIpv4Hosts" ):
1387 for host in main.disconnectedIpv4Hosts:
1388 disconnectedHosts.append( host )
1389 if hasattr( main, "disconnectedIpv6Hosts" ):
1390 for host in main.disconnectedIpv6Hosts:
1391 disconnectedHosts.append( host )
You Wang53dba1e2018-02-02 17:45:44 -08001392 for hostName, ip in main.expectedHosts[ "network" ].items():
You Wang6acb7a42018-05-04 15:12:25 -07001393 # Exclude disconnected hosts
1394 if hostName in disconnectedHosts:
1395 main.log.debug( "Skip verifying IP for {} as it's disconnected".format( hostName ) )
1396 continue
You Wang53dba1e2018-02-02 17:45:44 -08001397 ipResult = ipResult and utilities.retry( main.Network.verifyHostIp,
1398 main.FALSE,
1399 kwargs={ 'hostList': [ hostName ],
You Wangd66de192018-04-30 17:30:12 -07001400 'prefix': ip,
Jon Hall43060f62020-06-23 13:13:33 -07001401 'update': True },
You Wang53dba1e2018-02-02 17:45:44 -08001402 attempts=attempts,
1403 sleep=sleep )
1404 utilities.assert_equals( expect=main.TRUE, actual=ipResult,
1405 onpass="Verify network host IP succeded",
1406 onfail="Verify network host IP failed" )
1407
1408 @staticmethod
You Wangaec6a092018-08-06 15:36:31 -07001409 def verifyOnosHostIp( main, attempts=10, sleep=10, skipOnFail=True ):
You Wang53dba1e2018-02-02 17:45:44 -08001410 """
1411 Verifies host IP address assignment from ONOS
1412 """
1413 main.step( "Verify host IP address assignment in ONOS" )
1414 ipResult = main.TRUE
You Wang6acb7a42018-05-04 15:12:25 -07001415 # Find out IPs of disconnected hosts
1416 disconnectedIps = []
1417 if hasattr( main, "disconnectedIpv4Hosts" ):
1418 for host in main.disconnectedIpv4Hosts:
1419 disconnectedIps.append( main.expectedHosts[ "network" ][ host ] )
1420 if hasattr( main, "disconnectedIpv6Hosts" ):
1421 for host in main.disconnectedIpv6Hosts:
1422 disconnectedIps.append( main.expectedHosts[ "network" ][ host ] )
You Wang53dba1e2018-02-02 17:45:44 -08001423 for hostName, ip in main.expectedHosts[ "onos" ].items():
You Wang6acb7a42018-05-04 15:12:25 -07001424 # Exclude disconnected hosts
1425 if ip in disconnectedIps:
1426 main.log.debug( "Skip verifying IP for {} as it's disconnected".format( ip ) )
1427 continue
You Wang53dba1e2018-02-02 17:45:44 -08001428 ipResult = ipResult and utilities.retry( main.Cluster.active( 0 ).verifyHostIp,
1429 main.FALSE,
1430 kwargs={ 'hostList': [ hostName ],
1431 'prefix': ip },
1432 attempts=attempts,
1433 sleep=sleep )
1434 utilities.assert_equals( expect=main.TRUE, actual=ipResult,
1435 onpass="Verify ONOS host IP succeded",
1436 onfail="Verify ONOS host IP failed" )
You Wangaec6a092018-08-06 15:36:31 -07001437 if not ipResult and skipOnFail:
1438 Testcaselib.saveOnosDiagnostics( main )
You Wang89477152018-08-07 14:19:02 -07001439 Testcaselib.cleanup( main, copyKarafLog=False )
You Wangaec6a092018-08-06 15:36:31 -07001440 main.skipCase()
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08001441
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08001442 @staticmethod
1443 def updateIntfCfg( main, connectPoint, ips=[], untagged=0, tagged=[], native=0 ):
1444 """
1445 Description:
1446 Updates interface configuration in ONOS, with given IP and vlan parameters
1447 Required:
1448 * connectPoint: connect point to update configuration
1449 Optional:
1450 * ips: list of IP addresses, combined with '/xx' subnet representation,
1451 corresponding to 'ips' field in the configuration
1452 * untagged: vlan ID as an integer, corresponding to 'vlan-untagged' field in the configuration
1453 * tagged: integer list of vlan IDs, corresponding to 'vlan-tagged' field in the configuration
1454 * native: vlan ID as an integer, corresponding to 'vlan-native' field in the configuration
1455 """
1456 cfg = dict()
1457 cfg[ "ports" ] = dict()
1458 cfg[ "ports" ][ connectPoint ] = dict()
1459 cfg[ "ports" ][ connectPoint ][ "interfaces" ] = [ dict() ]
1460 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "ips" ] = ips
1461 if untagged > 0:
1462 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "vlan-untagged" ] = untagged
1463 else:
1464 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "vlan-tagged" ] = tagged
1465 if native > 0:
1466 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "vlan-native" ] = native
1467
1468 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( json.dumps( cfg ) ) )
You Wange24d6272018-03-27 21:18:50 -07001469
1470 @staticmethod
You Wang2cb70172018-07-25 16:44:13 -07001471 def startScapyHosts( main, scapyNames=[], mininetNames=[] ):
You Wange24d6272018-03-27 21:18:50 -07001472 """
1473 Create host components and start Scapy CLIs
You Wang2cb70172018-07-25 16:44:13 -07001474 scapyNames: list of names that will be used as component names for scapy hosts
1475 mininetNames: used when scapy host names are different from the host names
1476 in Mininet. E.g. when scapyNames=['h1Scapy'], it's required to specify the
1477 name of the corresponding Mininet host by mininetNames=['h1']
You Wange24d6272018-03-27 21:18:50 -07001478 """
1479 main.step( "Start Scapy CLIs" )
You Wang4cc61912018-08-28 10:10:58 -07001480 main.scapyNames = scapyNames if scapyNames else main.params[ 'SCAPY' ][ 'HOSTNAMES' ].split( ',' )
1481 main.scapyHosts = [] if not hasattr( main, "scapyHosts" ) else main.scapyHosts
You Wang2cb70172018-07-25 16:44:13 -07001482 for scapyName in main.scapyNames:
You Wang4cc61912018-08-28 10:10:58 -07001483 if hasattr( main, 'Mininet1' ):
1484 main.Scapy.createHostComponent( scapyName )
1485 scapyHandle = getattr( main, scapyName )
1486 if mininetNames:
1487 mininetName = mininetNames[ scapyNames.index( scapyName ) ]
1488 else:
1489 mininetName = None
Jon Hall43060f62020-06-23 13:13:33 -07001490 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
1491 scapyHandle.mExecDir = "/tmp"
1492 scapyHandle.hostHome = main.params[ "MN_DOCKER" ][ "home" ]
1493 main.log.debug( "start mn host component in docker" )
1494 scapyHandle.startHostCli( mininetName,
1495 execDir="/tmp",
1496 hostHome=main.params[ "MN_DOCKER" ][ "home" ] )
1497 else:
1498 main.log.debug( "start mn host component" )
1499 scapyHandle.startHostCli( mininetName )
You Wang2cb70172018-07-25 16:44:13 -07001500 else:
You Wang0fc21702018-11-02 17:49:18 -07001501 main.Network.createHostComponent( scapyName )
You Wang4cc61912018-08-28 10:10:58 -07001502 scapyHandle = getattr( main, scapyName )
1503 scapyHandle.connectInband()
1504 main.scapyHosts.append( scapyHandle )
You Wang2cb70172018-07-25 16:44:13 -07001505 scapyHandle.startScapy()
1506 scapyHandle.updateSelf()
1507 main.log.debug( scapyHandle.name )
1508 main.log.debug( scapyHandle.hostIp )
1509 main.log.debug( scapyHandle.hostMac )
1510
1511 @staticmethod
1512 def verifyTraffic( main, srcHosts, dstIp, dstHost, dstIntf, ipv6=False, expect=True, skipOnFail=True, maxRetry=2 ):
1513 """
1514 Verify unicast traffic by pinging from source hosts to the destination IP
1515 and capturing the packets at the destination host using Scapy.
1516 srcHosts: List of host names to send the ping packets
1517 dstIp: destination IP of the ping packets
1518 dstHost: host that runs Scapy to capture the packets
1519 dstIntf: name of the interface on the destination host
1520 expect: use True if the ping is expected to be captured at destination;
1521 Otherwise False
1522 skipOnFail: skip the rest of this test case if result is not expected
1523 maxRetry: number of retries allowed
1524 """
1525 from tests.dependencies.topology import Topology
1526 try:
1527 main.topo
1528 except ( NameError, AttributeError ):
1529 main.topo = Topology()
1530 main.step( "Verify traffic to {} by capturing packets on {}".format( dstIp, dstHost ) )
1531 result = main.TRUE
1532 for srcHost in srcHosts:
1533 trafficResult = main.topo.pingAndCapture( srcHost, dstIp, dstHost, dstIntf, ipv6,
1534 expect, maxRetry, True )
1535 if not trafficResult:
You Wang2cb70172018-07-25 16:44:13 -07001536 result = main.FALSE
1537 main.log.warn( "Scapy result from {} to {} is not as expected".format( srcHost, dstIp ) )
1538 utilities.assert_equals( expect=main.TRUE,
1539 actual=result,
1540 onpass="Verify traffic to {}: Pass".format( dstIp ),
1541 onfail="Verify traffic to {}: Fail".format( dstIp ) )
1542 if skipOnFail and result != main.TRUE:
1543 Testcaselib.saveOnosDiagnostics( main )
1544 Testcaselib.cleanup( main, copyKarafLog=False )
1545 main.skipCase()
You Wange24d6272018-03-27 21:18:50 -07001546
1547 @staticmethod
You Wang547893e2018-05-08 13:34:59 -07001548 def verifyMulticastTraffic( main, routeName, expect, skipOnFail=True, maxRetry=1 ):
You Wange24d6272018-03-27 21:18:50 -07001549 """
1550 Verify multicast traffic using scapy
1551 """
You Wangc564c6f2018-05-01 15:24:57 -07001552 from tests.dependencies.topology import Topology
1553 try:
1554 main.topo
1555 except ( NameError, AttributeError ):
1556 main.topo = Topology()
You Wang85747762018-05-11 15:51:50 -07001557 main.step( "Verify {} multicast traffic".format( routeName ) )
You Wangc02d8352018-04-17 16:42:10 -07001558 routeData = main.multicastConfig[ routeName ]
1559 srcs = main.mcastRoutes[ routeName ][ "src" ]
1560 dsts = main.mcastRoutes[ routeName ][ "dst" ]
1561 main.log.info( "Sending multicast traffic from {} to {}".format( [ routeData[ "src" ][ i ][ "host" ] for i in srcs ],
1562 [ routeData[ "dst" ][ i ][ "host" ] for i in dsts ] ) )
You Wang85747762018-05-11 15:51:50 -07001563 result = main.TRUE
You Wangc02d8352018-04-17 16:42:10 -07001564 for src in srcs:
1565 srcEntry = routeData[ "src" ][ src ]
1566 for dst in dsts:
1567 dstEntry = routeData[ "dst" ][ dst ]
1568 sender = getattr( main, srcEntry[ "host" ] )
1569 receiver = getattr( main, dstEntry[ "host" ] )
1570 main.Network.addRoute( str( srcEntry[ "host" ] ),
1571 str( routeData[ "group" ] ),
1572 str( srcEntry[ "interface" ] ),
1573 True if routeData[ "ipVersion" ] == 6 else False )
1574 # Build the packet
1575 sender.buildEther( dst=str( srcEntry[ "Ether" ] ) )
1576 if routeData[ "ipVersion" ] == 4:
1577 sender.buildIP( dst=str( routeData[ "group" ] ) )
1578 elif routeData[ "ipVersion" ] == 6:
1579 sender.buildIPv6( dst=str( routeData[ "group" ] ) )
1580 sender.buildUDP( ipVersion=routeData[ "ipVersion" ], dport=srcEntry[ "UDP" ] )
1581 sIface = srcEntry[ "interface" ]
1582 dIface = dstEntry[ "interface" ] if "interface" in dstEntry.keys() else None
1583 pktFilter = srcEntry[ "filter" ]
1584 pkt = srcEntry[ "packet" ]
1585 # Send packet and check received packet
1586 expectedResult = expect.pop( 0 ) if isinstance( expect, list ) else expect
You Wangc564c6f2018-05-01 15:24:57 -07001587 t3Cmd = "t3-troubleshoot -vv -sp {} -et ipv{} -d {} -dm {}".format( srcEntry[ "port" ], routeData[ "ipVersion" ],
Jon Halla604fd42018-05-04 14:27:27 -07001588 routeData[ "group" ], srcEntry[ "Ether" ] )
You Wangc564c6f2018-05-01 15:24:57 -07001589 trafficResult = main.topo.sendScapyPackets( sender, receiver, pktFilter, pkt, sIface, dIface,
1590 expectedResult, maxRetry, True, t3Cmd )
You Wang85747762018-05-11 15:51:50 -07001591 if not trafficResult:
1592 result = main.FALSE
1593 main.log.warn( "Scapy result from {} to {} is not as expected".format( srcEntry[ "host" ],
1594 dstEntry[ "host" ] ) )
1595 utilities.assert_equals( expect=main.TRUE,
1596 actual=result,
1597 onpass="Verify {} multicast traffic: Pass".format( routeName ),
1598 onfail="Verify {} multicast traffic: Fail".format( routeName ) )
You Wangba823f02018-05-17 13:54:08 -07001599 if skipOnFail and result != main.TRUE:
You Wang85747762018-05-11 15:51:50 -07001600 Testcaselib.saveOnosDiagnostics( main )
1601 Testcaselib.cleanup( main, copyKarafLog=False )
1602 main.skipCase()
You Wangc02d8352018-04-17 16:42:10 -07001603
1604 @staticmethod
You Wang85747762018-05-11 15:51:50 -07001605 def verifyPing( main, srcList, dstList, ipv6=False, expect=True, wait=1,
You Wang54b1d672018-06-11 16:44:13 -07001606 acceptableFailed=0, skipOnFail=True, stepMsg="Verify Ping",
1607 t3Simple=True ):
You Wang5da39c82018-04-26 22:55:08 -07001608 """
1609 Verify reachability from each host in srcList to each host in dstList
1610 """
1611 from tests.dependencies.topology import Topology
1612 try:
1613 main.topo
1614 except ( NameError, AttributeError ):
1615 main.topo = Topology()
You Wang85747762018-05-11 15:51:50 -07001616 main.step( stepMsg )
You Wang54b1d672018-06-11 16:44:13 -07001617 pingResult = main.topo.ping( srcList, dstList, ipv6, expect, wait, acceptableFailed, skipOnFail, t3Simple )
You Wang85747762018-05-11 15:51:50 -07001618 utilities.assert_equals( expect=main.TRUE,
1619 actual=pingResult,
1620 onpass="{}: Pass".format( stepMsg ),
1621 onfail="{}: Fail".format( stepMsg ) )
You Wang5da39c82018-04-26 22:55:08 -07001622 if not pingResult and skipOnFail:
1623 Testcaselib.saveOnosDiagnostics( main )
1624 Testcaselib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
1625 main.skipCase()
You Wangbc898b82018-05-03 16:22:34 -07001626
1627 @staticmethod
You Wang85747762018-05-11 15:51:50 -07001628 def verifyHostLocations( main, locationDict, retry=2 ):
You Wangbc898b82018-05-03 16:22:34 -07001629 """
1630 Verify if the specified host is discovered by ONOS on the given locations
1631 Required:
You Wang85747762018-05-11 15:51:50 -07001632 locationDict: a dictionary that maps host names to expected locations.
1633 locations could be a string or a list.
1634 ex. { "h1v4": ["of:0000000000000005/8"] }
You Wangbc898b82018-05-03 16:22:34 -07001635 Returns:
1636 main.TRUE if host is discovered on all locations provided, otherwise main.FALSE
1637 """
You Wang85747762018-05-11 15:51:50 -07001638 main.step( "Verify locations of hosts {}".format( locationDict.keys() ) )
1639 result = main.TRUE
1640 for hostName, locations in locationDict.items():
1641 main.log.info( "Verify host {} is discovered at {}".format( hostName, locations ) )
1642 hostIp = main.Network.getIPAddress( hostName, proto='IPV4' )
1643 if not hostIp:
1644 hostIp = main.Network.getIPAddress( hostName, proto='IPV6' )
1645 if not hostIp:
1646 main.log.warn( "Failed to find IP address for host {}, skipping location verification".format( hostName ) )
1647 result = main.FALSE
1648 continue
1649 locationResult = utilities.retry( main.Cluster.active( 0 ).CLI.verifyHostLocation,
1650 main.FALSE,
1651 args=( hostIp, locations ),
1652 attempts=retry + 1,
1653 sleep=10 )
1654 if not locationResult:
1655 result = main.FALSE
1656 main.log.warn( "location verification for host {} failed".format( hostName ) )
You Wang547893e2018-05-08 13:34:59 -07001657 utilities.assert_equals( expect=main.TRUE, actual=result,
You Wang85747762018-05-11 15:51:50 -07001658 onpass="Location verification passed",
1659 onfail="Location verification failed" )
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001660
1661 @staticmethod
You Wang6e5b48e2018-07-23 16:17:38 -07001662 def moveHost( main, hostName, srcSw, dstSw, gw, macAddr=None, prefixLen=None, cfg='', ipv6=False, vlan=None ):
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001663 """
1664 Move specified host from srcSw to dstSw.
1665 If srcSw and dstSw are same, the host will be moved from current port to
1666 next available port.
1667 Required:
1668 hostName: name of the host. e.g., "h1"
1669 srcSw: name of the switch that the host is attached to. e.g., "leaf1"
1670 dstSw: name of the switch that the host will be moved to. e.g., "leaf2"
1671 gw: ip address of the gateway of the new location
1672 Optional:
1673 macAddr: if specified, change MAC address of the host to the specified MAC address.
1674 prefixLen: prefix length
1675 cfg: port configuration as JSON string
1676 ipv6: Use True to move IPv6 host
You Wang6e5b48e2018-07-23 16:17:38 -07001677 vlan: vlan number of the host
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001678 """
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001679 if not hasattr( main, 'Mininet1' ):
1680 main.log.warn( "moveHost is supposed to be used only in Mininet." )
1681 return
1682
You Wang6e5b48e2018-07-23 16:17:38 -07001683 main.step( "Moving {} host {} from {} to {}".format( 'tagged' if vlan else 'untagged', hostName, srcSw, dstSw ) )
1684 main.Mininet1.moveHost( hostName, srcSw, dstSw, macAddr, prefixLen, ipv6, vlan=vlan )
1685 if not ipv6:
You Wang6260ed52018-07-18 17:54:25 -07001686 main.Mininet1.changeDefaultGateway( hostName, gw )
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001687 if cfg:
1688 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( cfg ),
1689 subjectClass="ports" )
You Wang6260ed52018-07-18 17:54:25 -07001690 # Wait for the host to get RA for setting up default gateway
Jon Hall43060f62020-06-23 13:13:33 -07001691 main.log.debug( "sleeping %i seconds" % ( 5 ) )
You Wang6260ed52018-07-18 17:54:25 -07001692 time.sleep( 5 )
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001693
1694 main.Mininet1.discoverHosts( [ hostName, ] )
1695
1696 # Update expectedHost when MAC address is changed.
1697 if macAddr is not None:
1698 ipAddr = main.expectedHosts[ "network" ][ hostName ]
1699 if ipAddr is not None:
1700 for hostName, ip in main.expectedHosts[ "onos" ].items():
1701 if ip == ipAddr:
1702 vlan = hostName.split( "/" )[ -1 ]
1703 del main.expectedHosts[ "onos" ][ hostName ]
You Wang7ea90582018-07-19 15:27:58 -07001704 main.expectedHosts[ "onos" ][ "{}/{}".format( macAddr.upper(), vlan ) ] = ip
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001705 break
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001706
1707 @staticmethod
1708 def moveDualHomedHost( main, hostName, srcSw, srcPairSw, dstSw, dstPairSw, gw,
You Wang6e5b48e2018-07-23 16:17:38 -07001709 macAddr=None, prefixLen=24, cfg='', ipv6=False, vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001710 """
1711 Move specified dual-homed host from srcSw-srcPairSw to dstSw-dstPairSw.
1712 If srcSw-srcPairSw and dstSw-dstPairSw are same, the host will be moved from current port
1713 to next available port.
1714 Required:
1715 hostName: name of the host. e.g., "h1"
1716 srcSw: name of the switch that the host is attached to. e.g., "leaf1"
1717 srcPairSw: name of the paired-switch that the host is attached to. e.g., "leaf2"
1718 dstSw: name of the switch that the host will be moved to. e.g., "leaf1"
1719 dstPairSw: name of the paired-switch that the host will be moved to. e.g., "leaf2"
1720 gw: ip address of the gateway of the new location
1721 Optional:
1722 macAddr: if specified, change MAC address of the host to the specified MAC address.
1723 prefixLen: prefix length
1724 cfg: port configurations as JSON string
You Wang7ea90582018-07-19 15:27:58 -07001725 ipv6: Use True to move IPv6 host
You Wang6e5b48e2018-07-23 16:17:38 -07001726 vlan: vlan number of the host
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001727 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001728 if not hasattr( main, 'Mininet1' ):
1729 main.log.warn( "moveDualHomedHost is supposed to be used only in Mininet." )
1730 return
1731
You Wang6e5b48e2018-07-23 16:17:38 -07001732 main.step( "Moving {} host {} from {} and {} to {} and {}".format( 'tagged' if vlan else 'untagged', hostName,
1733 srcSw, srcPairSw, dstSw, dstPairSw ) )
1734 main.Mininet1.moveDualHomedHost( hostName, srcSw, srcPairSw, dstSw, dstPairSw,
1735 macAddr=macAddr, prefixLen=prefixLen, ipv6=ipv6, vlan=vlan )
1736 if not ipv6:
You Wang7ea90582018-07-19 15:27:58 -07001737 main.Mininet1.changeDefaultGateway( hostName, gw )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001738 if cfg:
1739 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( cfg ),
1740 subjectClass="ports" )
You Wang7ea90582018-07-19 15:27:58 -07001741 # Wait for the host to get RA for setting up default gateway
Jon Hall43060f62020-06-23 13:13:33 -07001742 main.log.debug( "sleeping %i seconds" % ( 5 ) )
You Wang7ea90582018-07-19 15:27:58 -07001743 time.sleep( 5 )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001744
1745 main.Mininet1.discoverHosts( [ hostName, ] )
1746
1747 # Update expectedHost when MAC address is changed.
1748 if macAddr is not None:
1749 ipAddr = main.expectedHosts[ "network" ][ hostName ]
1750 if ipAddr is not None:
1751 for hostName, ip in main.expectedHosts[ "onos" ].items():
1752 if ip == ipAddr:
1753 vlan = hostName.split( "/" )[ -1 ]
1754 del main.expectedHosts[ "onos" ][ hostName ]
You Wang7ea90582018-07-19 15:27:58 -07001755 main.expectedHosts[ "onos" ][ "{}/{}".format( macAddr.upper(), vlan ) ] = ip
Jon Hall43060f62020-06-23 13:13:33 -07001756
1757 @staticmethod
1758 def mnDockerSetup( main ):
1759 """
1760 Optionally start and setup docker image for mininet
1761 """
Jon Hall9b0de1f2020-08-24 15:38:04 -07001762 try:
1763 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
Jon Hall43060f62020-06-23 13:13:33 -07001764
Jon Hall9b0de1f2020-08-24 15:38:04 -07001765 main.log.info( "Creating Mininet Docker" )
1766 handle = main.Mininet1.handle
1767 # build docker image
1768 dockerFilePath = "%s/../dependencies/" % main.testDir
1769 dockerName = "trellis_mininet"
1770 # Stop any leftover container
1771 main.Mininet1.dockerStop( dockerName )
1772 # TODO: assert on these docker calls
Jon Hall39570262020-11-17 12:18:19 -08001773 main.Mininet1.dockerBuild( dockerFilePath, dockerName, pull=True )
Jon Hallf6aeda22020-07-28 09:12:56 -07001774
Jon Hall9b0de1f2020-08-24 15:38:04 -07001775 confDir = "/tmp/mn_conf/"
1776 # Try to ensure the destination exists
1777 main.log.info( "Create folder for network config files" )
1778 handle.sendline( "rm -rf %s" % confDir )
1779 handle.expect( main.Mininet1.Prompt() )
1780 main.log.debug( handle.before + handle.after )
1781 handle.sendline( "mkdir -p %s" % confDir )
1782 handle.expect( main.Mininet1.Prompt() )
1783 main.log.debug( handle.before + handle.after )
Jon Hall39570262020-11-17 12:18:19 -08001784 handle.sendline( "sudo rm -rf /tmp/mn-stratum/*" )
1785 handle.expect( main.Mininet1.Prompt() )
Jon Hall9b0de1f2020-08-24 15:38:04 -07001786 # Make sure permissions are correct
1787 handle.sendline( "sudo chown %s:%s %s" % ( main.Mininet1.user_name, main.Mininet1.user_name, confDir ) )
1788 handle.expect( main.Mininet1.Prompt() )
1789 handle.sendline( "sudo chmod -R a+rwx %s" % ( confDir ) )
1790 handle.expect( main.Mininet1.Prompt() )
1791 main.log.debug( handle.before + handle.after )
1792 # Start docker container
1793 runResponse = main.Mininet1.dockerRun( main.params[ 'MN_DOCKER' ][ 'name' ],
1794 dockerName,
1795 main.params[ 'MN_DOCKER' ][ 'args' ] )
1796 if runResponse == main.FALSE:
1797 main.log.error( "Docker container already running, aborting test" )
1798 main.cleanup()
1799 main.exit()
Jon Hall43060f62020-06-23 13:13:33 -07001800
Jon Hall9b0de1f2020-08-24 15:38:04 -07001801 main.Mininet1.dockerAttach( dockerName, dockerPrompt='~#' )
1802 main.Mininet1.sudoRequired = False
Jon Hall43060f62020-06-23 13:13:33 -07001803
Jon Hall9b0de1f2020-08-24 15:38:04 -07001804 # Fow when we create component handles
1805 main.Mininet1.mExecDir = "/tmp"
1806 main.Mininet1.hostHome = main.params[ "MN_DOCKER" ][ "home" ]
1807 main.Mininet1.hostPrompt = "/home/root#"
1808
1809 # For some reason docker isn't doing this
1810 main.Mininet1.handle.sendline( "echo \"127.0.0.1 $(cat /etc/hostname)\" >> /etc/hosts" )
1811 main.Mininet1.handle.expect( "etc/hosts" )
1812 main.Mininet1.handle.expect( main.Mininet1.Prompt() )
1813 except Exception as e:
1814 main.log.exception( "Error seting up mininet" )
Jon Hall39570262020-11-17 12:18:19 -08001815 main.skipCase( result="FAIL", msg=e )
Jon Hall43060f62020-06-23 13:13:33 -07001816
1817 @staticmethod
1818 def mnDockerTeardown( main ):
1819 """
1820 Optionally stop and cleanup docker image for mininet
1821 """
1822
1823 if hasattr( main, 'Mininet1' ):
1824 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
Jon Hall3c0114c2020-08-11 15:07:42 -07001825 main.log.info( "Exiting from Mininet Docker" )
Jon Hall43060f62020-06-23 13:13:33 -07001826
1827 # Detach from container
Jon Hall43060f62020-06-23 13:13:33 -07001828 try:
Jon Hall3c0114c2020-08-11 15:07:42 -07001829 main.Mininet1.dockerDisconnect()
Jon Hall43060f62020-06-23 13:13:33 -07001830 main.Mininet1.sudoRequired = True
1831 except Exception as e:
1832 main.log.error( e )
1833
Jon Hall39570262020-11-17 12:18:19 -08001834 # Save docker logs
1835 copyResult = main.ONOSbench.scp( main.Mininet1,
1836 "/tmp/mn-stratum/*",
1837 main.logdir,
1838 direction="from",
1839 options="-rp" )
1840
1841
Jon Hall43060f62020-06-23 13:13:33 -07001842 @staticmethod
1843 def setOnosConfig( main ):
1844 """
1845 Read and Set onos configurations from the params file
1846 """
1847 main.step( "Set ONOS configurations" )
1848 config = main.params.get( 'ONOS_Configuration' )
1849 if config:
1850 main.log.debug( config )
1851 checkResult = main.TRUE
1852 for component in config:
1853 for setting in config[ component ]:
1854 value = config[ component ][ setting ]
1855 check = main.Cluster.next().setCfg( component, setting, value )
1856 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
1857 checkResult = check and checkResult
1858 utilities.assert_equals( expect=main.TRUE,
1859 actual=checkResult,
1860 onpass="Successfully set config",
1861 onfail="Failed to set config" )
1862 else:
1863 main.log.warn( "No configurations were specified to be changed after startup" )
1864
1865 @staticmethod
1866 def setOnosLogLevels( main ):
1867 """
1868 Read and Set onos log levels from the params file
1869 """
1870 main.step( 'Set logging levels' )
Jon Hall06fd0df2021-01-25 15:50:06 -08001871 # Get original values incase we want to reset them
1872 ctrl = main.Cluster.active(0)
Jon Halla7b27e62021-06-29 12:13:51 -07001873 ctrl.CLI.clearBuffer( timeout=1 )
Jon Hall06fd0df2021-01-25 15:50:06 -08001874 ctrl.CLI.logList()
1875
Jon Hall43060f62020-06-23 13:13:33 -07001876 logging = True
1877 try:
1878 logs = main.params.get( 'ONOS_Logging', False )
1879 if logs:
1880 for namespace, level in logs.items():
1881 for ctrl in main.Cluster.active():
1882 ctrl.CLI.logSet( level, namespace )
1883 except AttributeError:
1884 logging = False
1885 utilities.assert_equals( expect=True, actual=logging,
1886 onpass="Set log levels",
1887 onfail="Failed to set log levels" )
Jon Hall06fd0df2021-01-25 15:50:06 -08001888
1889 @staticmethod
1890 def resetOnosLogLevels( main ):
1891 """
1892 Read and reset onos log levels to a previously read set of values
1893 """
1894 main.step( 'Reset logging levels' )
1895 # Get original values incase we want to reset them
1896 ctrl = main.Cluster.active(0)
Jon Halla7b27e62021-06-29 12:13:51 -07001897 ctrl.CLI.clearBuffer( timeout=1 )
Jon Hall06fd0df2021-01-25 15:50:06 -08001898 currentLevels = ctrl.CLI.logList( saveValues=False )
1899 origLevels = ctrl.CLI.logLevels
1900 toBeSet = {}
1901 for logger, level in currentLevels.iteritems():
1902 if logger not in origLevels:
1903 toBeSet[ logger ] = origLevels[ 'ROOT' ]
1904 else:
1905 oldLevel = origLevels[ logger ]
1906 if level != oldLevel:
1907 toBeSet[ logger ] = oldLevel
Jon Hallef1480b2021-03-31 13:37:41 -07001908 # In case a previous test didn't reset
1909 logs = main.params.get( 'ONOS_Logging_Reset', False )
1910 if logs:
1911 for namespace, level in logs.items():
1912 toBeSet[ namespace ] = level
Jon Hall06fd0df2021-01-25 15:50:06 -08001913 logging = True
1914 try:
1915 for logger, level in toBeSet.iteritems():
1916 for ctrl in main.Cluster.active():
1917 ctrl.CLI.logSet( level, logger )
1918 except AttributeError:
1919 logging = False
1920 utilities.assert_equals( expect=True, actual=logging,
1921 onpass="Reset log levels",
1922 onfail="Failed to reset log levels" )