blob: bc4bea607c7353dd114d5da63ab38e120bdca206 [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/"
78 main.forChart = "chart/"
79 main.forConfig = "conf/"
80 main.forHost = "host/"
You Wang27317572018-03-06 12:13:11 -080081 main.forSwitchFailure = "switchFailure/"
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -080082 main.forLinkFailure = "linkFailure/"
You Wange24d6272018-03-27 21:18:50 -070083 main.forMulticast = "multicast/"
Devin Lim58046fa2017-07-05 16:55:00 -070084 main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
You Wangd87b2312018-01-30 12:47:17 -080085 main.topologyLib = main.params[ 'DEPENDENCY' ][ 'lib' ] if 'lib' in main.params[ 'DEPENDENCY' ] else None
86 main.topologyConf = main.params[ 'DEPENDENCY' ][ 'conf' ] if 'conf' in main.params[ 'DEPENDENCY' ] else None
You Wang68568b12019-03-04 11:49:57 -080087 main.bmv2 = "bmv2.py"
Jon Halldac3eae2020-06-05 12:04:06 -070088 main.stratumRoot = main.params[ 'DEPENDENCY'][ 'stratumRoot'] if 'stratumRoot' in main.params[ 'DEPENDENCY' ] else None
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070089 main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
Devin Lim58046fa2017-07-05 16:55:00 -070090 main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
Jon Hall3c0114c2020-08-11 15:07:42 -070091 main.trellisOar = main.params[ 'DEPENDENCY' ][ 'trellisOar' ] if 'trellisOar' in main.params[ 'DEPENDENCY' ] else None
You Wang5bf49592020-07-08 18:47:46 -070092 main.t3Oar = main.params[ 'DEPENDENCY' ][ 't3Oar' ] if 't3Oar' in main.params[ 'DEPENDENCY' ] else None
Jon Hall1efcb3f2016-08-23 13:42:15 -070093
Devin Lim0c972b72018-02-08 14:53:59 -080094 stepResult = main.testSetUp.envSetup( False )
Devin Lim58046fa2017-07-05 16:55:00 -070095 except Exception as e:
96 main.testSetUp.envSetupException( e )
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -070097
Jon Hallaa1d9b82020-07-30 13:49:42 -070098 main.testSetUp.envSetupConclusion( stepResult )
Jon Hall32c90f32021-06-24 16:32:44 -070099
Siddesh167bc882021-03-23 21:03:43 +0000100 @staticmethod
101 def getTopo():
102 topo = dict()
103 # TODO: Check minFlowCount of leaf for BMv2 switch
104 # (number of spine switch, number of leaf switch, dual-homed, description, minFlowCount - leaf (OvS), minFlowCount - leaf (BMv2))
105 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 }
106 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 }
107 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 }
108 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 }
109 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 }
110 topo[ '4x4' ] = {'spines': 4,'leaves': 4, 'dual-homed': True, 'description': '4x4 dual-homed leaf-spine topology','dual-linked': True }
111 topo[ '2x2staging' ] = { 'spines': 2, 'leaves': 2,'dual-homed': True, 'description': '2x2 leaf-spine topology', 'minFlowOvS': 37, 'minFlow-Stratum': 32 }
112 return topo
Jon Hall1efcb3f2016-08-23 13:42:15 -0700113 @staticmethod
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800114 def installOnos( main, vlanCfg=True, skipPackage=False, cliSleep=10,
115 parallel=True ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700116 """
117 - Set up cell
118 - Create cell file
119 - Set cell file
120 - Verify cell file
121 - Kill ONOS process
122 - Uninstall ONOS cluster
123 - Verify ONOS start up
124 - Install ONOS cluster
125 - Connect to cli
126 """
Siddesh13492972021-03-12 21:09:32 +0000127 # 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
128
Jon Hall1efcb3f2016-08-23 13:42:15 -0700129 # main.scale[ 0 ] determines the current number of ONOS controller
Jon Hall43060f62020-06-23 13:13:33 -0700130 try:
Jon Hall627b1572020-12-01 12:01:15 -0800131 if not main.persistentSetup and main.params.get( 'EXTERNAL_APPS' ):
Jon Hall43060f62020-06-23 13:13:33 -0700132 for app, url in main.params[ 'EXTERNAL_APPS' ].iteritems():
Jon Hall39570262020-11-17 12:18:19 -0800133 main.log.info( "Downloading %s app from %s" % ( app, url ) )
Jon Hall43060f62020-06-23 13:13:33 -0700134 main.ONOSbench.onosFetchApp( url )
135 if not main.apps:
136 main.log.error( "App list is empty" )
137 except Exception as e:
138 main.log.debug( e )
139 main.cleanAndExit()
Jon Hall3c910162018-03-07 14:42:16 -0800140 main.log.info( "Cluster size: " + str( main.Cluster.numCtrls ) )
141 main.log.info( "Cluster ips: " + ', '.join( main.Cluster.getIps() ) )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700142 main.dynamicHosts = [ 'in1', 'out1' ]
You Wanga0f6ff62018-01-11 15:46:30 -0800143 main.testSetUp.ONOSSetUp( main.Cluster, newCell=True, cellName=main.cellName,
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800144 skipPack=skipPackage,
145 useSSH=Testcaselib.useSSH,
Devin Lim0c972b72018-02-08 14:53:59 -0800146 installParallel=parallel, includeCaseDesc=False )
Devin Lim142b5342017-07-20 15:22:39 -0700147 ready = utilities.retry( main.Cluster.active( 0 ).CLI.summary,
You Wang5bf49592020-07-08 18:47:46 -0700148 [ None, main.FALSE ],
You Wang1cdc5f52017-12-19 16:47:51 -0800149 sleep=cliSleep,
Devin Lim142b5342017-07-20 15:22:39 -0700150 attempts=10 )
151 if ready:
152 ready = main.TRUE
153 utilities.assert_equals( expect=main.TRUE, actual=ready,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700154 onpass="ONOS summary command succeded",
155 onfail="ONOS summary command failed" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700156 if not ready:
157 main.log.error( "ONOS startup failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700158 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700159
You Wang5bf49592020-07-08 18:47:46 -0700160 # Install segmentrouting and t3 app
Jon Hall3c0114c2020-08-11 15:07:42 -0700161 appInstallResult = main.TRUE
162 if main.trellisOar:
163 appInstallResult = appInstallResult and main.ONOSbench.onosAppInstall( main.Cluster.runningNodes[0].ipAddress, main.trellisOar)
You Wang5bf49592020-07-08 18:47:46 -0700164 if main.t3Oar:
165 appInstallResult = appInstallResult and main.ONOSbench.onosAppInstall( main.Cluster.runningNodes[0].ipAddress, main.t3Oar)
166 utilities.assert_equals( expect=main.TRUE, actual=appInstallResult,
167 onpass="SR app installation succeded",
168 onfail="SR app installation failed" )
169 if not appInstallResult:
170 main.cleanAndExit()
171
Jon Hall43060f62020-06-23 13:13:33 -0700172 # FIXME: move to somewhere else?
173 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix' )
174 # TODO: Support other pipeconfs/making this configurable
175 if switchPrefix == "tofino":
176 # It seems to take some time for the pipeconfs to be loaded
177 ctrl = main.Cluster.next()
178 for i in range( 120 ):
179 try:
180 main.log.debug( "Checking to see if pipeconfs are loaded" )
181 output = ctrl.CLI.sendline( "pipeconfs" )
182 if "tofino" in output:
183 main.log.debug( "Took around %s seconds for the pipeconf to be loaded" % i )
184 break
185 time.sleep( 1 )
186 except Exception as e:
187 main.log.error( e )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700188
Jon Hall627b1572020-12-01 12:01:15 -0800189 # Install segmentrouting and t3 app
190 appInstallResult = main.TRUE
191 if not main.persistentSetup:
192 if main.trellisOar:
193 appInstallResult = appInstallResult and main.ONOSbench.onosAppInstall( main.Cluster.runningNodes[0].ipAddress, main.trellisOar)
194 if main.t3Oar:
195 appInstallResult = appInstallResult and main.ONOSbench.onosAppInstall( main.Cluster.runningNodes[0].ipAddress, main.t3Oar)
196 utilities.assert_equals( expect=main.TRUE, actual=appInstallResult,
197 onpass="SR app installation succeded",
198 onfail="SR app installation failed" )
199 if not appInstallResult:
200 main.cleanAndExit()
201
Jon Hall43060f62020-06-23 13:13:33 -0700202 Testcaselib.setOnosLogLevels( main )
203 Testcaselib.setOnosConfig( main )
Jon Halldac3eae2020-06-05 12:04:06 -0700204
Jon Hall1efcb3f2016-08-23 13:42:15 -0700205 @staticmethod
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800206 def loadCount( main ):
Jon Hall43060f62020-06-23 13:13:33 -0700207 with open( "%s/count/%s.count" % ( main.configPath, main.cfgName ) ) as count:
208 main.count = json.load( count )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800209
210 @staticmethod
Jon Hall43060f62020-06-23 13:13:33 -0700211 def loadJson( main, suffix='' ):
212 with open( "%s%s.json%s" % ( main.configPath + main.forJson,
213 main.cfgName, suffix ) ) as cfg:
Devin Lim57221b02018-02-14 15:45:36 -0800214 main.Cluster.active( 0 ).REST.setNetCfg( json.load( cfg ) )
215
216 @staticmethod
Jon Hall10e2ab82020-09-15 17:14:54 -0700217 def loadXconnects( main, suffix='' ):
218 with open( "%s%s-xconnects.json%s" % ( main.configPath + main.forJson,
219 main.cfgName, suffix ) ) as cfg:
220 for xconnect in json.load( cfg ).get('xconnects'):
221 main.Cluster.active( 0 ).REST.setXconnectJson( xconnect )
222
223 @staticmethod
Devin Lim57221b02018-02-14 15:45:36 -0800224 def loadChart( main ):
225 try:
Jon Hall32c90f32021-06-24 16:32:44 -0700226 filename = "%s%s.chart" % ( main.configPath + main.forChart,
227 main.cfgName )
228 with open( filename ) as chart:
Jon Hall43060f62020-06-23 13:13:33 -0700229 main.pingChart = json.load( chart )
Devin Lim57221b02018-02-14 15:45:36 -0800230 except IOError:
Jon Hall32c90f32021-06-24 16:32:44 -0700231 main.log.warn( "No chart file found at %s" % filename )
Devin Lim57221b02018-02-14 15:45:36 -0800232
233 @staticmethod
234 def loadHost( main ):
235 with open( "%s%s.host" % ( main.configPath + main.forHost,
236 main.cfgName ) ) as host:
237 main.expectedHosts = json.load( host )
238
239 @staticmethod
You Wang27317572018-03-06 12:13:11 -0800240 def loadSwitchFailureChart( main ):
241 with open( "%s%s.switchFailureChart" % ( main.configPath + main.forSwitchFailure,
242 main.cfgName ) ) as sfc:
243 main.switchFailureChart = json.load( sfc )
244
245 @staticmethod
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800246 def loadLinkFailureChart( main ):
247 with open( "%s%s.linkFailureChart" % ( main.configPath + main.forLinkFailure,
You Wange24d6272018-03-27 21:18:50 -0700248 main.cfgName ) ) as lfc:
249 main.linkFailureChart = json.load( lfc )
250
251 @staticmethod
252 def loadMulticastConfig( main ):
253 with open( "%s%s.multicastConfig" % ( main.configPath + main.forMulticast,
254 main.cfgName ) ) as cfg:
255 main.multicastConfig = json.load( cfg )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800256
257 @staticmethod
Jon Hall1efcb3f2016-08-23 13:42:15 -0700258 def startMininet( main, topology, args="" ):
Jon Hall43060f62020-06-23 13:13:33 -0700259 main.log.info( "Copying mininet topology file to mininet machine" )
You Wangd87b2312018-01-30 12:47:17 -0800260 copyResult = main.ONOSbench.scp( main.Mininet1,
261 main.topoPath + main.topology,
You Wang5da39c82018-04-26 22:55:08 -0700262 main.Mininet1.home + "custom",
You Wangd87b2312018-01-30 12:47:17 -0800263 direction="to" )
264 if main.topologyLib:
265 for lib in main.topologyLib.split(","):
266 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
267 main.topoPath + lib,
You Wang5da39c82018-04-26 22:55:08 -0700268 main.Mininet1.home + "custom",
You Wangd87b2312018-01-30 12:47:17 -0800269 direction="to" )
270 if main.topologyConf:
You Wanga877ea42018-04-05 15:27:40 -0700271 import re
272 controllerIPs = [ ctrl.ipAddress for ctrl in main.Cluster.runningNodes ]
273 index = 0
Jon Hall43060f62020-06-23 13:13:33 -0700274 destDir = "~/"
275 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
276 destDir = "/tmp/mn_conf/"
277 # Try to ensure the destination exists
You Wangd87b2312018-01-30 12:47:17 -0800278 for conf in main.topologyConf.split(","):
You Wanga877ea42018-04-05 15:27:40 -0700279 # Update zebra configurations with correct ONOS instance IP
280 if conf in [ "zebradbgp1.conf", "zebradbgp2.conf" ]:
281 ip = controllerIPs[ index ]
282 index = ( index + 1 ) % len( controllerIPs )
283 with open( main.configPath + main.forConfig + conf ) as f:
284 s = f.read()
285 s = re.sub( r"(fpm connection ip).*(port 2620)", r"\1 " + ip + r" \2", s )
286 with open( main.configPath + main.forConfig + conf, "w" ) as f:
287 f.write( s )
You Wangd87b2312018-01-30 12:47:17 -0800288 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
Devin Lim57221b02018-02-14 15:45:36 -0800289 main.configPath + main.forConfig + conf,
Jon Hall43060f62020-06-23 13:13:33 -0700290 destDir,
You Wangd87b2312018-01-30 12:47:17 -0800291 direction="to" )
You Wang68568b12019-03-04 11:49:57 -0800292 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
Jon Hallbc1c1c92020-05-27 09:29:30 -0700293 main.ONOSbench.home + main.bmv2Path + main.bmv2,
You Wang68568b12019-03-04 11:49:57 -0800294 main.Mininet1.home + "custom",
295 direction="to" )
Jon Hall9b0de1f2020-08-24 15:38:04 -0700296
297 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
298 # move the config files into home
299 main.Mininet1.handle.sendline( "cp config/* . " )
300 main.Mininet1.handle.expect( main.Mininet1.Prompt() )
301 main.log.debug( main.Mininet1.handle.before + main.Mininet1.handle.after )
302 main.Mininet1.handle.sendline( "ls -al " )
303 main.Mininet1.handle.expect( main.Mininet1.Prompt() )
304 main.log.debug( main.Mininet1.handle.before + main.Mininet1.handle.after )
305
You Wangd87b2312018-01-30 12:47:17 -0800306 stepResult = copyResult
307 utilities.assert_equals( expect=main.TRUE,
308 actual=stepResult,
309 onpass="Successfully copied topo files",
310 onfail="Failed to copy topo files" )
Jon Halldac3eae2020-06-05 12:04:06 -0700311 if main.stratumRoot:
312 main.Mininet1.handle.sendline( "export STRATUM_ROOT=" + str( main.stratumRoot ) )
Jon Hall3c0114c2020-08-11 15:07:42 -0700313 main.Mininet1.handle.expect( main.Mininet1.Prompt() )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700314 main.step( "Starting Mininet Topology" )
Jonghwan Hyun3731d6a2017-10-19 11:59:31 -0700315 arg = "--onos-ip=%s %s" % (",".join([ctrl.ipAddress for ctrl in main.Cluster.runningNodes]), args)
Jon Hall1efcb3f2016-08-23 13:42:15 -0700316 main.topology = topology
317 topoResult = main.Mininet1.startNet(
You Wang5da39c82018-04-26 22:55:08 -0700318 topoFile=main.Mininet1.home + "custom/" + main.topology, args=arg )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700319 stepResult = topoResult
320 utilities.assert_equals( expect=main.TRUE,
321 actual=stepResult,
322 onpass="Successfully loaded topology",
323 onfail="Failed to load topology" )
324 # Exit if topology did not load properly
325 if not topoResult:
Devin Lim44075962017-08-11 10:56:37 -0700326 main.cleanAndExit()
Jon Hall43060f62020-06-23 13:13:33 -0700327 if main.useBmv2:
Jon Hall3c0114c2020-08-11 15:07:42 -0700328 main.step( "Configure switches in ONOS" )
Jon Hall43060f62020-06-23 13:13:33 -0700329 # Upload the net-cfg file created for each switch
330 filename = "onos-netcfg.json"
331 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700332 switchNetCfg = main.TRUE
Jon Hall43060f62020-06-23 13:13:33 -0700333 for switch in main.Mininet1.getSwitches( switchRegex=r"(StratumBmv2Switch)|(Bmv2Switch)" ).keys():
334 path = "/tmp/mn-stratum/%s/" % switch
335 dstPath = "/tmp/"
336 dstFileName = "%s-onos-netcfg.json" % switch
337 main.ONOSbench1.scp( main.Mininet1,
338 "%s%s" % ( path, filename ),
339 "%s%s" % ( dstPath, dstFileName ),
340 "from" )
341 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 -0700342 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
Jon Hall43060f62020-06-23 13:13:33 -0700343 # Configure managementAddress
344 main.ONOSbench1.handle.sendline( "sudo sed -i 's/localhost/%s/g' %s%s" % ( main.Mininet1.ip_address, dstPath, dstFileName ) )
345 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
346 main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
347 # Configure device id
348 main.ONOSbench1.handle.sendline( "sudo sed -i 's/device:%s/device:%s:%s/g' %s%s" % ( switch, switchPrefix, switch, dstPath, dstFileName ) )
349 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
350 main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
351 # Configure device name
Jon Hall39570262020-11-17 12:18:19 -0800352 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 -0700353 main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
354 main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
Jon Hall3c0114c2020-08-11 15:07:42 -0700355 node = main.Cluster.active(0)
356 switchNetCfg = switchNetCfg and node.onosNetCfg( node.server.ip_address,
357 dstPath,
358 dstFileName,
359 user=node.REST.user_name,
360 password=node.REST.pwd )
361 # Stop test if we fail to push switch netcfg
362 utilities.assert_equals( expect=main.TRUE,
363 actual=switchNetCfg,
364 onpass="Successfully pushed switch netcfg",
365 onfail="Failed to configure switches in onos" )
366 if not switchNetCfg:
367 main.cleanAndExit()
Jon Hall43060f62020-06-23 13:13:33 -0700368 # Make sure hosts make some noise
369 Testcaselib.discoverHosts( main )
370
371 @staticmethod
372 def discoverHosts( main ):
373 # TODO add option to only select specific hosts
374 if hasattr( main, "Mininet1" ):
375 network = main.Mininet1
376 elif hasattr( main, "NetworkBench" ):
377 network = main.NetworkBench
378 else:
379 main.log.warn( "Could not find component for test network, skipping host discovery" )
380 return
381 network.discoverHosts()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700382
383 @staticmethod
Jon Hall06fd0df2021-01-25 15:50:06 -0800384 def connectToPhysicalNetwork( main, hostDiscovery=True ):
You Wang84f981d2018-01-12 16:11:50 -0800385 main.step( "Connecting to physical netowrk" )
Jon Hall43060f62020-06-23 13:13:33 -0700386 main.physicalNet = True
You Wang84f981d2018-01-12 16:11:50 -0800387 topoResult = main.NetworkBench.connectToNet()
388 stepResult = topoResult
389 utilities.assert_equals( expect=main.TRUE,
390 actual=stepResult,
Jon Hall43060f62020-06-23 13:13:33 -0700391 onpass="Successfully connected to topology",
392 onfail="Failed to connect to topology" )
You Wang84f981d2018-01-12 16:11:50 -0800393 # Exit if topology did not load properly
394 if not topoResult:
395 main.cleanAndExit()
396
Jon Hall627b1572020-12-01 12:01:15 -0800397 if not main.persistentSetup:
398 # Perform any optional setup
399 for switch in main.NetworkBench.switches:
400 if hasattr( switch, "setup" ):
401 switch.setup() # We might not need this
Jon Hall43060f62020-06-23 13:13:33 -0700402
Jon Hall627b1572020-12-01 12:01:15 -0800403 main.step( "Assign switches to controllers." )
404 stepResult = main.TRUE
405 switches = main.NetworkBench.getSwitches()
406 pool = []
407 for name in switches.keys():
408 # NOTE: although this terminology is ovsdb centric, we can use this function for other switches too
409 # e.g. push onos net-cfg for stratum switches
410 thread = main.Thread( target=main.NetworkBench.assignSwController,
411 name="assignSwitchToController",
412 args=[ name, main.Cluster.getIps(), '6653' ] )
413 pool.append( thread )
414 thread.start()
415 for thread in pool:
416 thread.join( 300 )
417 if not thread.result:
418 stepResult = main.FALSE
419 utilities.assert_equals( expect=main.TRUE,
420 actual=stepResult,
421 onpass="Successfully assign switches to controllers",
422 onfail="Failed to assign switches to controllers" )
You Wang84f981d2018-01-12 16:11:50 -0800423
You Wang4cc61912018-08-28 10:10:58 -0700424 # Check devices
425 Testcaselib.checkDevices( main, switches=int( main.params[ 'TOPO' ][ 'switchNum' ] ) )
You Wang4cc61912018-08-28 10:10:58 -0700426 # Connecting to hosts that only have data plane connectivity
427 main.step( "Connecting inband hosts" )
428 stepResult = main.Network.connectInbandHosts()
429 utilities.assert_equals( expect=main.TRUE,
430 actual=stepResult,
431 onpass="Successfully connected inband hosts",
432 onfail="Failed to connect inband hosts" )
Jon Hall06fd0df2021-01-25 15:50:06 -0800433 if hostDiscovery:
434 Testcaselib.discoverHosts( main )
You Wang4cc61912018-08-28 10:10:58 -0700435
You Wang84f981d2018-01-12 16:11:50 -0800436 @staticmethod
You Wang5df1c6d2018-04-06 18:02:02 -0700437 def saveOnosDiagnostics( main ):
438 """
439 Get onos-diags.tar.gz and save it to the log directory.
440 suffix: suffix string of the file name. E.g. onos-diags-case1.tar.gz
441 """
442 main.log.info( "Collecting onos-diags..." )
Siddesha2938fe2021-04-06 02:46:06 +0000443 for ctrl in main.Cluster.runningNodes:
444 main.ONOSbench.onosDiagnostics( [ctrl.ipAddress], main.logdir,"-CASE%d" % main.CurrentTestCaseNumber, onosPortnumber=ctrl.REST.port )
You Wang5df1c6d2018-04-06 18:02:02 -0700445
446 @staticmethod
Devin Lim142b5342017-07-20 15:22:39 -0700447 def config( main, cfgName ):
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700448 main.spines = []
Piera2a7e1b2016-10-04 11:51:43 -0700449
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700450 main.failures = int( main.params[ 'failures' ] )
451 main.cfgName = cfgName
Piera2a7e1b2016-10-04 11:51:43 -0700452
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700453 if main.cfgName == '2x2':
454 spine = {}
455 spine[ 'name' ] = main.params[ 'switches' ][ 'spine1' ]
456 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid1' ]
457 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700458
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700459 spine = {}
460 spine[ 'name' ] = main.params[ 'switches' ][ 'spine2' ]
461 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid2' ]
462 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700463
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700464 elif main.cfgName == '4x4':
465 spine = {}
466 spine[ 'name' ] = main.params[ 'switches' ][ 'spine1' ]
467 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid1' ]
468 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700469
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700470 spine = {}
471 spine[ 'name' ] = main.params[ 'switches' ][ 'spine2' ]
472 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid2' ]
473 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700474
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700475 spine = {}
476 spine[ 'name' ] = main.params[ 'switches' ][ 'spine3' ]
477 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid3' ]
478 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700479
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700480 spine = {}
481 spine[ 'name' ] = main.params[ 'switches' ][ 'spine4' ]
482 spine[ 'dpid' ] = main.params[ 'switches' ][ 'spinedpid4' ]
483 main.spines.append( spine )
Piera2a7e1b2016-10-04 11:51:43 -0700484
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700485 else:
Piera2a7e1b2016-10-04 11:51:43 -0700486 main.log.error( "Configuration failed!" )
Devin Lim44075962017-08-11 10:56:37 -0700487 main.cleanAndExit()
You Wang27317572018-03-06 12:13:11 -0800488
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -0800489 @staticmethod
490 def addStaticOnosRoute( main, subnet, intf):
491 """
492 Adds an ONOS static route with the use route-add command.
493 """
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -0800494 routeResult = main.Cluster.active( 0 ).addStaticRoute(subnet, intf)
495
Piera2a7e1b2016-10-04 11:51:43 -0700496 @staticmethod
You Wangc02f3be2018-05-18 12:14:23 -0700497 def checkGroupsForBuckets( main, deviceId, subnetDict, routingTable=30 ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700498 """
499 Check number of groups for each subnet on device deviceId and matches
500 it with an expected value. subnetDict is a dictionarty containing values
501 of the type "10.0.1.0/24" : 5.
502 """
You Wangc02f3be2018-05-18 12:14:23 -0700503 main.step( "Checking if number of groups for subnets in device {0} is as expected.".format( deviceId ) )
504 groups = main.Cluster.active( 0 ).CLI.getGroups( deviceId, groupType="select" )
505 flows = main.Cluster.active( 0 ).CLI.flows( jsonFormat=False, device=deviceId )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700506
You Wangc02f3be2018-05-18 12:14:23 -0700507 result = main.TRUE
508 for subnet, numberInSelect in subnetDict.iteritems():
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700509 for flow in flows.splitlines():
You Wangc02f3be2018-05-18 12:14:23 -0700510 if "tableId={0}".format( routingTable ) in flow and subnet in flow:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700511 # this will match the group id that this flow entry points to, for example :
512 # 0x70000041 in flow entry which contains "deferred=[GROUP:0x70000041], transition=TABLE:60,"
You Wangc02f3be2018-05-18 12:14:23 -0700513 groupId = re.search( r".*GROUP:(0x.*)], transition.*", flow ).groups()[0]
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700514 count = 0
515 for group in groups.splitlines():
You Wangc02f3be2018-05-18 12:14:23 -0700516 if 'id={0}'.format( groupId ) in group:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700517 count += 1
You Wangc02f3be2018-05-18 12:14:23 -0700518 if count - 1 != numberInSelect:
519 result = main.FALSE
520 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 ) )
521 utilities.assert_equals( expect=main.TRUE, actual=result,
522 onpass="All bucket numbers are as expected",
523 onfail="Some bucket numbers are not as expected" )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -0700524
525 @staticmethod
Jon Hall32c90f32021-06-24 16:32:44 -0700526 def checkFlows( main, minFlowCount, tag="", dumpFlows=True, sleep=10 ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700527 main.step(
Jon Hall39570262020-11-17 12:18:19 -0800528 "Check whether the flow count is >= %s" % minFlowCount )
Jonghwan Hyun76a02b72018-01-30 16:40:48 +0900529 if tag == "":
530 tag = 'CASE%d' % main.CurrentTestCaseNumber
Devin Lim142b5342017-07-20 15:22:39 -0700531 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowCount,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700532 main.FALSE,
533 kwargs={ 'min': minFlowCount },
534 attempts=10,
You Wang1cdc5f52017-12-19 16:47:51 -0800535 sleep=sleep )
steven30801eccfe212019-01-24 13:00:42 +0800536 if count == main.FALSE:
537 count = main.Cluster.active( 0 ).CLI.checkFlowCount()
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700538 utilities.assertEquals(
Jon Hall1efcb3f2016-08-23 13:42:15 -0700539 expect=True,
Jon Hall39570262020-11-17 12:18:19 -0800540 actual=( count >= minFlowCount ),
Jon Hall43060f62020-06-23 13:13:33 -0700541 onpass="Flow count looks correct; found %s, expecting at least %s" % ( count, minFlowCount ),
542 onfail="Flow count looks wrong; found %s, expecting at least %s" % ( count, minFlowCount ) )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700543
544 main.step( "Check whether all flow status are ADDED" )
Devin Lim142b5342017-07-20 15:22:39 -0700545 flowCheck = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowsState,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700546 main.FALSE,
547 kwargs={ 'isPENDING': False },
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800548 attempts=5,
You Wang1cdc5f52017-12-19 16:47:51 -0800549 sleep=sleep )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700550 utilities.assertEquals(
Jon Hall1efcb3f2016-08-23 13:42:15 -0700551 expect=main.TRUE,
552 actual=flowCheck,
553 onpass="Flow status is correct!",
554 onfail="Flow status is wrong!" )
Jon Hall32c90f32021-06-24 16:32:44 -0700555 if dumpFlows:
Devin Lim142b5342017-07-20 15:22:39 -0700556 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
Pier50f0bc62016-09-07 17:53:40 -0700557 "flows",
558 main.logdir,
Jon Hall06fd0df2021-01-25 15:50:06 -0800559 tag + "_FlowsBefore",
560 cliPort=main.Cluster.active(0).CLI.karafPort )
Devin Lim142b5342017-07-20 15:22:39 -0700561 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
Pier50f0bc62016-09-07 17:53:40 -0700562 "groups",
563 main.logdir,
Jon Hall06fd0df2021-01-25 15:50:06 -0800564 tag + "_GroupsBefore",
565 cliPort=main.Cluster.active(0).CLI.karafPort )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700566
567 @staticmethod
Pier6a0c4de2018-03-18 16:01:30 -0700568 def checkDevices( main, switches, tag="", sleep=10 ):
569 main.step(
570 "Check whether the switches count is equal to %s" % switches )
571 if tag == "":
572 tag = 'CASE%d' % main.CurrentTestCaseNumber
573 result = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
574 main.FALSE,
575 kwargs={ 'numoswitch': switches},
576 attempts=10,
577 sleep=sleep )
578 utilities.assert_equals( expect=main.TRUE, actual=result,
579 onpass="Device up successful",
580 onfail="Failed to boot up devices?" )
581
582 @staticmethod
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800583 def checkFlowsByDpid( main, dpid, minFlowCount, sleep=10 ):
584 main.step(
Jon Hall39570262020-11-17 12:18:19 -0800585 "Check whether the flow count of device %s >= than %s" % ( dpid, minFlowCount ) )
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800586 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
587 main.FALSE,
588 args=( dpid, minFlowCount ),
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800589 attempts=5,
590 sleep=sleep )
steven30801eccfe212019-01-24 13:00:42 +0800591 if count == main.FALSE:
592 count = main.Cluster.active( 0 ).CLI.checkFlowAddedCount( dpid )
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800593 utilities.assertEquals(
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800594 expect=True,
Jon Hall39570262020-11-17 12:18:19 -0800595 actual=( count >= minFlowCount ),
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -0800596 onpass="Flow count looks correct: " + str( count ),
steven30801eccfe212019-01-24 13:00:42 +0800597 onfail="Flow count looks wrong: " + str( count ) )
Jonghwan Hyun98fb40a2018-01-04 16:16:28 -0800598
599 @staticmethod
Jon Hall9677ed32018-04-24 11:16:23 -0700600 def checkFlowEqualityByDpid( main, dpid, flowCount, sleep=10 ):
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800601 main.step(
Jon Hall43060f62020-06-23 13:13:33 -0700602 "Check whether the flow count of device %s is equal to %s" % ( dpid, flowCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800603 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
604 main.FALSE,
Jon Hall9677ed32018-04-24 11:16:23 -0700605 args=( dpid, flowCount, False, 1 ),
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800606 attempts=5,
607 sleep=sleep )
steven30801eccfe212019-01-24 13:00:42 +0800608 if count == main.FALSE:
609 count = main.Cluster.active( 0 ).CLI.checkFlowAddedCount( dpid )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800610 utilities.assertEquals(
611 expect=True,
steven30801eccfe212019-01-24 13:00:42 +0800612 actual=( count == flowCount ),
Jon Hall9677ed32018-04-24 11:16:23 -0700613 onpass="Flow count looks correct: " + str( count ) ,
614 onfail="Flow count looks wrong. found {}, should be {}.".format( count, flowCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800615
616 @staticmethod
617 def checkGroupEqualityByDpid( main, dpid, groupCount, sleep=10):
618 main.step(
Jon Hall43060f62020-06-23 13:13:33 -0700619 "Check whether the group count of device %s is equal to %s" % ( dpid, groupCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800620 count = utilities.retry( main.Cluster.active( 0 ).CLI.checkGroupAddedCount,
621 main.FALSE,
622 args=( dpid, groupCount, False, 1),
623 attempts=5,
624 sleep=sleep )
steven30801eccfe212019-01-24 13:00:42 +0800625 if count == main.FALSE:
steven3080123997972019-01-29 17:01:40 +0800626 count = main.Cluster.active( 0 ).CLI.checkGroupAddedCount( dpid )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800627 utilities.assertEquals(
628 expect=True,
629 actual=( count == groupCount ),
Jon Hall9677ed32018-04-24 11:16:23 -0700630 onpass="Group count looks correct: " + str( count ) ,
631 onfail="Group count looks wrong. found {}, should be {}.".format( count, groupCount ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800632
633 @staticmethod
Jon Hall9677ed32018-04-24 11:16:23 -0700634 def checkFlowsGroupsFromFile( main ):
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800635
636 for dpid, values in main.count.items():
637 flowCount = values["flows"]
638 groupCount = values["groups"]
Jon Hall9677ed32018-04-24 11:16:23 -0700639 main.log.report( "Check flow count for dpid " + str( dpid ) +
640 ", should be " + str( flowCount ) )
641 Testcaselib.checkFlowEqualityByDpid( main, dpid, flowCount )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800642
Jon Hall9677ed32018-04-24 11:16:23 -0700643 main.log.report( "Check group count for dpid " + str( dpid ) +
644 ", should be " + str( groupCount ) )
645 Testcaselib.checkGroupEqualityByDpid( main, dpid, groupCount )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -0800646
647 return
648
649 @staticmethod
Jon Hall32c90f32021-06-24 16:32:44 -0700650 def pingAll( main, tag="", dumpFlows=True, acceptableFailed=0, basedOnIp=False,
Jon Hall06fd0df2021-01-25 15:50:06 -0800651 sleep=10, retryAttempts=1, skipOnFail=False, useScapy=True ):
You Wangf19d9f42018-02-23 16:34:19 -0800652 '''
You Wangba231e72018-03-01 13:18:21 -0800653 Verify connectivity between hosts according to the ping chart
654 acceptableFailed: max number of acceptable failed pings.
You Wangf19d9f42018-02-23 16:34:19 -0800655 basedOnIp: if True, run ping or ping6 based on suffix of host names
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800656 retryAttempts: the number of retry ping. Only works for IPv4 hosts.
You Wangf19d9f42018-02-23 16:34:19 -0800657 '''
You Wangba231e72018-03-01 13:18:21 -0800658 main.log.report( "Check host connectivity" )
659 main.log.debug( "Ping chart: %s" % main.pingChart )
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800660 if tag == "":
661 tag = 'CASE%d' % main.CurrentTestCaseNumber
662 for entry in main.pingChart.itervalues():
You Wangba231e72018-03-01 13:18:21 -0800663 main.log.debug( "Entry in ping chart: %s" % entry )
664 expect = entry[ 'expect' ]
665 if expect == "Unidirectional":
666 # Verify ping from each src host to each dst host
667 src = entry[ 'src' ]
668 dst = entry[ 'dst' ]
669 expect = main.TRUE
670 main.step( "Verify unidirectional connectivity from %s to %s with tag %s" % ( str( src ), str( dst ), tag ) )
671 if basedOnIp:
672 if ("v4" in src[0]):
673 pa = main.Network.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed )
674 utilities.assert_equals( expect=expect, actual=pa,
675 onpass="IPv4 connectivity successfully tested",
676 onfail="IPv4 connectivity failed" )
677 if ("v6" in src[0]):
678 pa = main.Network.pingallHostsUnidirectional( src, dst, ipv6=True, acceptableFailed=acceptableFailed )
679 utilities.assert_equals( expect=expect, actual=pa,
680 onpass="IPv6 connectivity successfully tested",
681 onfail="IPv6 connectivity failed" )
Jon Hall43060f62020-06-23 13:13:33 -0700682 elif main.physicalNet:
683 pa = main.NetworkBench.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed, useScapy=True )
684 utilities.assert_equals( expect=expect, actual=pa,
685 onpass="IP connectivity successfully tested",
686 onfail="IP connectivity failed" )
687
You Wangba231e72018-03-01 13:18:21 -0800688 else:
689 pa = main.Network.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed )
690 utilities.assert_equals( expect=expect, actual=pa,
691 onpass="IP connectivity successfully tested",
692 onfail="IP connectivity failed" )
693 else:
694 # Verify ping between each host pair
695 hosts = entry[ 'hosts' ]
696 try:
697 expect = main.TRUE if str(expect).lower() == 'true' else main.FALSE
698 except:
699 expect = main.FALSE
700 main.step( "Verify full connectivity for %s with tag %s" % ( str( hosts ), tag ) )
701 if basedOnIp:
702 if ("v4" in hosts[0]):
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800703 pa = utilities.retry( main.Network.pingallHosts,
704 main.FALSE if expect else main.TRUE,
Jon Hall43060f62020-06-23 13:13:33 -0700705 args=(hosts, ),
706 kwargs={ 'ipv6': False },
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800707 attempts=retryAttempts,
708 sleep=sleep )
You Wangba231e72018-03-01 13:18:21 -0800709 utilities.assert_equals( expect=expect, actual=pa,
710 onpass="IPv4 connectivity successfully tested",
711 onfail="IPv4 connectivity failed" )
712 if ("v6" in hosts[0]):
713 pa = main.Network.pingIpv6Hosts( hosts, acceptableFailed=acceptableFailed )
714 utilities.assert_equals( expect=expect, actual=pa,
715 onpass="IPv6 connectivity successfully tested",
716 onfail="IPv6 connectivity failed" )
Jon Hall43060f62020-06-23 13:13:33 -0700717 elif main.physicalNet:
Jon Hall06fd0df2021-01-25 15:50:06 -0800718 pa = main.Network.pingallHosts( hosts, ipv6=True, useScapy=useScapy )
Jon Hall43060f62020-06-23 13:13:33 -0700719 utilities.assert_equals( expect=expect, actual=pa,
720 onpass="IP connectivity successfully tested",
721 onfail="IP connectivity failed" )
You Wangba231e72018-03-01 13:18:21 -0800722 else:
You Wangf19d9f42018-02-23 16:34:19 -0800723 pa = main.Network.pingallHosts( hosts )
724 utilities.assert_equals( expect=expect, actual=pa,
You Wangba231e72018-03-01 13:18:21 -0800725 onpass="IP connectivity successfully tested",
726 onfail="IP connectivity failed" )
Jon Hall43060f62020-06-23 13:13:33 -0700727 if pa != expect:
You Wang5df1c6d2018-04-06 18:02:02 -0700728 Testcaselib.saveOnosDiagnostics( main )
Jon Hall43060f62020-06-23 13:13:33 -0700729 if skipOnFail and pa != expect:
You Wang24ad2f52018-04-10 10:47:12 -0700730 Testcaselib.cleanup( main, copyKarafLog=False )
You Wang5df1c6d2018-04-06 18:02:02 -0700731 main.skipCase()
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800732
Jon Hall32c90f32021-06-24 16:32:44 -0700733 if dumpFlows:
734 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
735 "flows",
736 main.logdir,
737 tag + "_FlowsOn",
738 cliPort=main.Cluster.active(0).CLI.karafPort )
739 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
740 "groups",
741 main.logdir,
742 tag + "_GroupsOn",
743 cliPort=main.Cluster.active(0).CLI.karafPort )
744
745 @staticmethod
746 def pingAllFabricIntfs( main, srcList, tag="", dumpFlows=True, skipOnFail=False ):
747 '''
748 Verify connectivity between hosts and their fabric interfaces
749 '''
750 main.log.report( "Check host connectivity with fabric" )
751 if tag == "":
752 tag = 'CASE%d' % main.CurrentTestCaseNumber
753 expect = main.TRUE
754 import json
755 import re
756 hostsJson = json.loads( main.Cluster.active( 0 ).hosts() )
757 netcfgJson = json.loads( main.Cluster.active( 0 ).getNetCfg( subjectClass='ports') )
758 for hostname in srcList:
759 try:
760 hostComponent = main.Network.hosts[ str( hostname ) ]
761 srcIface = hostComponent.interfaces[0].get( 'name' )
762 main.step( "Verify fabric connectivity for %s with tag %s" % ( str( hostname ), tag ) )
763 #Get host location, check netcfg for that port's ip
764 hostIp = hostComponent.getIPAddress( iface=srcIface )
765 main.log.warn( "Looking for %s" % hostIp )
766 ips = []
767 for obj in hostsJson:
768 if hostIp in obj['ipAddresses']:
769 for location in obj['locations']:
770 main.log.debug( location )
771 did = location['elementId'].encode( 'utf-8' )
772 port = location['port'].encode( 'utf-8' )
773 m = re.search( '\((\d+)\)', port )
774 if m:
775 port = m.group(1)
776 portId = "%s/%s" % ( did, port )
777 # Lookup ip assigned to this network port
778 ips.extend( [ x.encode( 'utf-8' ) for x in netcfgJson[ portId ][ 'interfaces' ][0][ 'ips' ] ] )
779 ips = set( ips )
780 ipRE = r'(\d+\.\d+\.\d+\.\d+)/\d+|([\w,:]*)/\d+'
781 for ip in ips:
782 ipMatch = re.search( ipRE, ip )
783 if ipMatch:
784 fabricIntfIp = ipMatch.group(1)
785 main.log.debug( "Found %s as gateway ip for %s" % ( fabricIntfIp, hostname ) )
786 pa = hostComponent.ping( fabricIntfIp, interface=srcIface )
787 utilities.assert_equals( expect=expect, actual=pa,
788 onpass="IP connectivity successfully tested",
789 onfail="IP connectivity failed" )
790 if pa != expect:
791 Testcaselib.saveOnosDiagnostics( main )
792 if skipOnFail:
793 Testcaselib.cleanup( main, copyKarafLog=False )
794 main.skipCase()
795 except ValueError:
796 main.log.exception( "Could not get gateway ip for %s" % hostname )
797
798 if dumpFlows:
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800799 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
800 "flows",
801 main.logdir,
Jon Hall06fd0df2021-01-25 15:50:06 -0800802 tag + "_FlowsOn",
803 cliPort=main.Cluster.active(0).CLI.karafPort )
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800804 main.ONOSbench.dumpONOSCmd( main.Cluster.active( 0 ).ipAddress,
805 "groups",
806 main.logdir,
Jon Hall06fd0df2021-01-25 15:50:06 -0800807 tag + "_GroupsOn",
808 cliPort=main.Cluster.active(0).CLI.karafPort )
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800809
810 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700811 def killLink( main, end1, end2, switches, links, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700812 """
813 end1,end2: identify the switches, ex.: 'leaf1', 'spine1'
814 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
815 Kill a link and verify ONOS can see the proper link change
816 """
Jon Halla604fd42018-05-04 14:27:27 -0700817 if sleep is None:
818 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
819 else:
820 sleep = float( sleep )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700821 main.step( "Kill link between %s and %s" % ( end1, end2 ) )
Jon Halla604fd42018-05-04 14:27:27 -0700822 linkDown = main.Network.link( END1=end1, END2=end2, OPTION="down" )
823 linkDown = linkDown and main.Network.link( END2=end1, END1=end2, OPTION="down" )
Jon Hall214f88b2020-09-21 10:21:42 -0700824 utilities.assert_equals( expect=main.TRUE, actual=linkDown,
825 onpass="Link down successful",
826 onfail="Failed to turn off link?" )
Jon Halla604fd42018-05-04 14:27:27 -0700827 # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
Jon Hall1efcb3f2016-08-23 13:42:15 -0700828 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700829 "Waiting %s seconds for link down to be discovered" % sleep )
830 time.sleep( sleep )
Jon Hall214f88b2020-09-21 10:21:42 -0700831 main.step( "Checking topology after link down" )
Devin Lim142b5342017-07-20 15:22:39 -0700832 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -0700833 main.FALSE,
834 kwargs={ 'numoswitch': switches,
835 'numolink': links },
836 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700837 sleep=sleep )
Jon Hall214f88b2020-09-21 10:21:42 -0700838 utilities.assert_equals( expect=main.TRUE, actual=topology,
839 onpass="Topology after link down is correct",
840 onfail="Topology after link down is incorrect" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700841
842 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700843 def killLinkBatch( main, links, linksAfter, switches, sleep=None ):
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800844 """
845 links = list of links (src, dst) to bring down.
846 """
847
848 main.step("Killing a batch of links {0}".format(links))
Jon Halla604fd42018-05-04 14:27:27 -0700849 if sleep is None:
850 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
851 else:
852 sleep = float( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800853
854 for end1, end2 in links:
855 main.Network.link( END1=end1, END2=end2, OPTION="down")
856 main.Network.link( END1=end2, END2=end1, OPTION="down")
857
Jon Halla604fd42018-05-04 14:27:27 -0700858 # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800859 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700860 "Waiting %s seconds for links down to be discovered" % sleep )
861 time.sleep( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800862
863 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
864 main.FALSE,
865 kwargs={ 'numoswitch': switches,
866 'numolink': linksAfter },
867 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700868 sleep=sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800869
You Wang2854bce2018-03-30 10:15:32 -0700870 utilities.assert_equals( expect=main.TRUE, actual=topology,
871 onpass="Link batch down successful",
872 onfail="Link batch down failed" )
873
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800874 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700875 def restoreLinkBatch( main, links, linksAfter, switches, sleep=None ):
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800876 """
877 links = list of link (src, dst) to bring up again.
878 """
879
880 main.step("Restoring a batch of links {0}".format(links))
Jon Halla604fd42018-05-04 14:27:27 -0700881 if sleep is None:
882 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
883 else:
884 sleep = float( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800885
886 for end1, end2 in links:
887 main.Network.link( END1=end1, END2=end2, OPTION="up")
888 main.Network.link( END1=end2, END2=end1, OPTION="up")
889
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800890 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700891 "Waiting %s seconds for links up to be discovered" % sleep )
892 time.sleep( sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800893
894 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
895 main.FALSE,
896 kwargs={ 'numoswitch': switches,
897 'numolink': linksAfter },
898 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -0700899 sleep=sleep )
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800900
You Wang2854bce2018-03-30 10:15:32 -0700901 utilities.assert_equals( expect=main.TRUE, actual=topology,
902 onpass="Link batch up successful",
903 onfail="Link batch up failed" )
904
Andreas Pantelopoulosfab6bf32018-03-06 18:56:35 -0800905 @staticmethod
You Wang85747762018-05-11 15:51:50 -0700906 def disablePortBatch( main, ports, switches=None, links=None, sleep=None ):
907 """
908 Disable a list of switch ports using 'portstate' and verify ONOS can see the proper link change
909 ports: a list of ports to disable ex. [ [ "of:0000000000000001", 1 ] ]
910 switches, links: number of expected switches and links after link change, ex.: '4', '6'
911 """
912 if sleep is None:
913 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
914 else:
915 sleep = float( sleep )
916 main.step( "Disable a batch of ports" )
917 for dpid, port in ports:
918 main.Cluster.active( 0 ).CLI.portstate( dpid=dpid, port=port, state="disable" )
919 main.log.info( "Waiting {} seconds for port down to be discovered".format( sleep ) )
920 time.sleep( sleep )
921 if switches and links:
922 result = main.Cluster.active( 0 ).CLI.checkStatus( numoswitch=switches,
923 numolink=links )
924 utilities.assert_equals( expect=main.TRUE, actual=result,
925 onpass="Port down successful",
926 onfail="Port down failed" )
927
928 @staticmethod
929 def enablePortBatch( main, ports, switches, links, sleep=None ):
930 """
931 Enable a list of switch ports using 'portstate' and verify ONOS can see the proper link change
932 ports: a list of ports to enable 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( "Enable a batch of ports" )
940 for dpid, port in ports:
941 main.Cluster.active( 0 ).CLI.portstate( dpid=dpid, port=port, state="enable" )
942 main.log.info( "Waiting {} seconds for port up 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 up successful",
949 onfail="Port up failed" )
950
951 @staticmethod
You Wangc02d8352018-04-17 16:42:10 -0700952 def restoreLink( main, end1, end2, switches, links,
Jon Halla604fd42018-05-04 14:27:27 -0700953 portUp=False, dpid1='', dpid2='', port1='', port2='', sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700954 """
955 Params:
956 end1,end2: identify the end switches, ex.: 'leaf1', 'spine1'
You Wangc02d8352018-04-17 16:42:10 -0700957 portUp: enable portstate after restoring link
Jon Hall1efcb3f2016-08-23 13:42:15 -0700958 dpid1, dpid2: dpid of the end switches respectively, ex.: 'of:0000000000000002'
959 port1, port2: respective port of the end switches that connects to the link, ex.:'1'
960 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
961 Kill a link and verify ONOS can see the proper link change
962 """
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700963 main.step( "Restore link between %s and %s" % ( end1, end2 ) )
Jon Halla604fd42018-05-04 14:27:27 -0700964 if sleep is None:
965 sleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
966 else:
967 sleep = float( sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700968 result = False
969 count = 0
970 while True:
971 count += 1
Jon Halla604fd42018-05-04 14:27:27 -0700972 ctrl = main.Cluster.next()
You Wangd5873482018-01-24 12:30:00 -0800973 main.Network.link( END1=end1, END2=end2, OPTION="up" )
974 main.Network.link( END2=end1, END1=end2, OPTION="up" )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700975 main.log.info(
Jon Halla604fd42018-05-04 14:27:27 -0700976 "Waiting %s seconds for link up to be discovered" % sleep )
977 time.sleep( sleep )
Pierfb719b12016-09-19 14:51:44 -0700978
You Wangc02d8352018-04-17 16:42:10 -0700979 if portUp:
980 ctrl.CLI.portstate( dpid=dpid1, port=port1, state='Enable' )
981 ctrl.CLI.portstate( dpid=dpid2, port=port2, state='Enable' )
Jon Hall43060f62020-06-23 13:13:33 -0700982 main.log.info(
983 "Waiting %s seconds for link up to be discovered" % sleep )
Jon Halla604fd42018-05-04 14:27:27 -0700984 time.sleep( sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700985
Jon Halla604fd42018-05-04 14:27:27 -0700986 result = ctrl.CLI.checkStatus( numoswitch=switches,
987 numolink=links )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700988 if count > 5 or result:
989 break
990 utilities.assert_equals( expect=main.TRUE, actual=result,
991 onpass="Link up successful",
992 onfail="Failed to bring link up" )
993
994 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -0700995 def killSwitch( main, switch, switches, links, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -0700996 """
997 Params: switches, links: number of expected switches and links after SwitchDown, ex.: '4', '6'
998 Completely kill a switch and verify ONOS can see the proper change
999 """
Jon Halla604fd42018-05-04 14:27:27 -07001000 if sleep is None:
1001 sleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
1002 else:
1003 sleep = float( sleep )
You Wangc02d8352018-04-17 16:42:10 -07001004 switch = switch if isinstance( switch, list ) else [ switch ]
1005 main.step( "Kill " + str( switch ) )
1006 for s in switch:
1007 main.log.info( "Stopping " + s )
1008 main.Network.switch( SW=s, OPTION="stop" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001009 # todo make this repeatable
Jon Halla604fd42018-05-04 14:27:27 -07001010
1011 # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
Jon Hall1efcb3f2016-08-23 13:42:15 -07001012 main.log.info( "Waiting %s seconds for switch down to be discovered" % (
Jon Halla604fd42018-05-04 14:27:27 -07001013 sleep ) )
1014 time.sleep( sleep )
Devin Lim142b5342017-07-20 15:22:39 -07001015 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -07001016 main.FALSE,
1017 kwargs={ 'numoswitch': switches,
1018 'numolink': links },
1019 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -07001020 sleep=sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001021 utilities.assert_equals( expect=main.TRUE, actual=topology,
1022 onpass="Kill switch successful",
1023 onfail="Failed to kill switch?" )
1024
1025 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -07001026 def recoverSwitch( main, switch, switches, links, rediscoverHosts=False, hostsToDiscover=[], sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -07001027 """
1028 Params: switches, links: number of expected switches and links after SwitchUp, ex.: '4', '6'
1029 Recover a switch and verify ONOS can see the proper change
1030 """
Jon Halla604fd42018-05-04 14:27:27 -07001031 if sleep is None:
1032 sleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
1033 else:
1034 sleep = float( sleep )
1035 # TODO make this repeatable
You Wangc02d8352018-04-17 16:42:10 -07001036 switch = switch if isinstance( switch, list ) else [ switch ]
1037 main.step( "Recovering " + str( switch ) )
1038 for s in switch:
1039 main.log.info( "Starting " + s )
1040 main.Network.switch( SW=s, OPTION="start" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001041 main.log.info( "Waiting %s seconds for switch up to be discovered" % (
Jon Halla604fd42018-05-04 14:27:27 -07001042 sleep ) )
1043 time.sleep( sleep )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -07001044 if rediscoverHosts:
You Wang48381752018-05-07 13:50:57 -07001045 main.Network.discoverHosts( hostList=hostsToDiscover )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -07001046 main.log.info( "Waiting %s seconds for hosts to get re-discovered" % (
Jon Halla604fd42018-05-04 14:27:27 -07001047 sleep ) )
1048 time.sleep( sleep )
Andreas Pantelopoulos74c7ff22018-05-01 15:42:02 -07001049
Devin Lim142b5342017-07-20 15:22:39 -07001050 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
Jon Hall1efcb3f2016-08-23 13:42:15 -07001051 main.FALSE,
1052 kwargs={ 'numoswitch': switches,
1053 'numolink': links },
1054 attempts=10,
Jon Halla604fd42018-05-04 14:27:27 -07001055 sleep=sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001056 utilities.assert_equals( expect=main.TRUE, actual=topology,
1057 onpass="Switch recovery successful",
1058 onfail="Failed to recover switch?" )
1059
Jonghwan Hyun25c98a62018-05-04 13:59:09 -07001060 @staticmethod
You Wang0f745de2018-07-27 15:49:22 -07001061 def killRouter( main, router, sleep=None ):
1062 """
1063 Kill bgpd process on a quagga router
1064 router: name of the router to be killed. E.g. "bgp1"
1065 """
1066 sleep = float( sleep )
1067 main.step( "Kill " + str( router ) )
1068 if hasattr( main, 'Mininet1' ):
1069 main.Mininet1.handle.sendline( "px {}.stopProtocols()".format( router ) )
1070 main.Mininet1.handle.expect( "mininet>" )
1071 else:
1072 # TODO: support killing router in physical network
1073 pass
1074 main.log.info( "Waiting %s seconds for router down to be discovered" % ( sleep ) )
1075 time.sleep( sleep )
1076
1077 @staticmethod
1078 def recoverRouter( main, router, sleep=None ):
1079 """
1080 Restart bgpd process on a quagga router
1081 router: name of the router to be recovered. E.g. "bgp1"
1082 """
1083 sleep = float( sleep )
1084 main.step( "Recovering " + str( router ) )
1085 if hasattr( main, 'Mininet1' ):
1086 main.Mininet1.handle.sendline( "px {}.startProtocols()".format( router ) )
1087 main.Mininet1.handle.expect( "mininet>" )
1088 else:
1089 # TODO: support recovering router in physical network
1090 pass
1091 main.log.info( "Waiting %s seconds for router up to be discovered" % ( sleep ) )
1092 time.sleep( sleep )
1093
1094 @staticmethod
You Wang5da39c82018-04-26 22:55:08 -07001095 def cleanup( main, copyKarafLog=True, removeHostComponent=False ):
Jon Hall1efcb3f2016-08-23 13:42:15 -07001096 """
1097 Stop Onos-cluster.
1098 Stops Mininet
1099 Copies ONOS log
1100 """
You Wang4cc61912018-08-28 10:10:58 -07001101 from tests.dependencies.utils import Utils
1102 main.utils = Utils()
Jon Hall627b1572020-12-01 12:01:15 -08001103 if not main.persistentSetup:
1104 for ctrl in main.Cluster.active():
1105 ctrl.CLI.log( "\"Ending Test - Shutting down ONOS and Network\"", level="INFO" )
You Wang4cc61912018-08-28 10:10:58 -07001106 # Clean up scapy hosts
You Wange24d6272018-03-27 21:18:50 -07001107 if hasattr( main, "scapyHosts" ):
1108 scapyResult = main.TRUE
1109 for host in main.scapyHosts:
1110 scapyResult = host.stopScapy() and scapyResult
1111 main.log.info( "Stopped Scapy Host: {0}".format( host.name ) )
1112 for host in main.scapyHosts:
You Wang4cc61912018-08-28 10:10:58 -07001113 if hasattr( main, 'Mininet1' ):
1114 scapyResult = main.Scapy.removeHostComponent( host.name ) and scapyResult
1115 else:
1116 scapyResult = main.Network.removeHostComponent( host.name ) and scapyResult
You Wange24d6272018-03-27 21:18:50 -07001117 main.log.info( "Removed Scapy Host Component: {0}".format( host.name ) )
1118 main.scapyHosts = []
1119
You Wang5da39c82018-04-26 22:55:08 -07001120 if removeHostComponent:
1121 for host in main.internalIpv4Hosts + main.internalIpv6Hosts + main.externalIpv4Hosts + main.externalIpv6Hosts:
1122 if hasattr( main, host ):
You Wang4cc61912018-08-28 10:10:58 -07001123 if hasattr( main, 'Mininet1' ):
1124 pass
1125 else:
1126 getattr( main, host ).disconnectInband()
You Wang5da39c82018-04-26 22:55:08 -07001127 main.Network.removeHostComponent( host )
1128
You Wang5df1c6d2018-04-06 18:02:02 -07001129 if hasattr( main, 'Mininet1' ):
Pier6a0c4de2018-03-18 16:01:30 -07001130 main.utils.mininetCleanup( main.Mininet1 )
You Wang4cc61912018-08-28 10:10:58 -07001131 else:
1132 main.Network.disconnectInbandHosts()
1133 main.Network.disconnectFromNet()
Devin Lim58046fa2017-07-05 16:55:00 -07001134
You Wang5df1c6d2018-04-06 18:02:02 -07001135 if copyKarafLog:
1136 main.utils.copyKarafLog( "CASE%d" % main.CurrentTestCaseNumber, before=True, includeCaseDesc=False )
Devin Lim58046fa2017-07-05 16:55:00 -07001137
Jon Hall627b1572020-12-01 12:01:15 -08001138 if not main.persistentSetup:
1139 for ctrl in main.Cluster.active():
1140 main.ONOSbench.onosStop( ctrl.ipAddress )
Jon Hall06fd0df2021-01-25 15:50:06 -08001141 else:
1142 Testcaselib.resetOnosLogLevels( main )
Jon Hall43060f62020-06-23 13:13:33 -07001143 Testcaselib.mnDockerTeardown( main )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001144
1145 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -07001146 def verifyNodes( main ):
1147 """
1148 Verifies Each active node in the cluster has an accurate view of other node's and their status
1149
1150 Params:
1151 nodes, integer array with position of the ONOS nodes in the CLIs array
1152 """
1153 nodeResults = utilities.retry( main.Cluster.nodesCheck,
1154 False,
1155 attempts=10,
1156 sleep=10 )
1157 utilities.assert_equals( expect=True, actual=nodeResults,
1158 onpass="Nodes check successful",
1159 onfail="Nodes check NOT successful" )
1160
1161 if not nodeResults:
1162 for ctrl in main.Cluster.runningNodes:
1163 main.log.debug( "{} components not ACTIVE: \n{}".format(
1164 ctrl.name,
Jon Hall6c9e2da2018-11-06 12:01:23 -08001165 ctrl.CLI.sendline( "onos:scr-list | grep -v ACTIVE" ) ) )
You Wang0bed5932018-12-11 14:45:41 -08001166 main.log.error( "Failed to verify nodes, stopping test" )
Jon Halla604fd42018-05-04 14:27:27 -07001167 main.cleanAndExit()
1168
1169 @staticmethod
Jon Hall39570262020-11-17 12:18:19 -08001170 def verifyTopology( main, switches, links, expNodes, SCCs=1 ):
Jon Halla604fd42018-05-04 14:27:27 -07001171 """
1172 Verifies that the ONOS cluster has an acuurate view of the topology
1173
1174 Params:
1175 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 -08001176 SCCs = Number of connected topology clusters within the control plane, defaults to 1
Jon Halla604fd42018-05-04 14:27:27 -07001177 """
1178 main.step( "Check number of topology elements" )
1179 topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
1180 main.FALSE,
1181 kwargs={ 'numoswitch': switches,
1182 'numolink': links,
Jon Hall39570262020-11-17 12:18:19 -08001183 'numoctrl': expNodes,
1184 'numoSCCs': SCCs },
Jon Halla604fd42018-05-04 14:27:27 -07001185 attempts=10,
1186 sleep=12 )
1187 utilities.assert_equals( expect=main.TRUE, actual=topology,
1188 onpass="Number of topology elements are correct",
Jon Hall39570262020-11-17 12:18:19 -08001189 onfail="Unexpected number of links, switches, and/or controllers: " + main.TOPOOUTPUT )
Jon Halla604fd42018-05-04 14:27:27 -07001190
1191 @staticmethod
1192 def killOnos( main, nodes, switches, links, expNodes, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -07001193 """
1194 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
1195 switches, links, nodes: number of expected switches, links and nodes after KillOnos, ex.: '4', '6'
1196 Completely Kill an ONOS instance and verify the ONOS cluster can see the proper change
1197 """
Jon Halla604fd42018-05-04 14:27:27 -07001198 # TODO: We have enough information in the Cluster instance to remove expNodes from here and verifyTopology
Jon Hall3c910162018-03-07 14:42:16 -08001199 main.step( "Killing ONOS instances with index(es): {}".format( nodes ) )
Jon Halla604fd42018-05-04 14:27:27 -07001200 if sleep is None:
1201 sleep = float( main.params[ 'timers' ][ 'OnosDiscovery' ] )
1202 else:
1203 sleep = float( sleep )
Pier3b58c652016-09-26 12:03:31 -07001204
Jon Hall214f88b2020-09-21 10:21:42 -07001205 stepResult = main.TRUE
Jon Hall1efcb3f2016-08-23 13:42:15 -07001206 for i in nodes:
Jon Hall214f88b2020-09-21 10:21:42 -07001207 node = main.Cluster.runningNodes[ i ]
1208 if node.inDocker:
1209 killResult = node.server.dockerStop( node.name )
1210 else:
1211 killResult = main.ONOSbench.onosDie( node.ipAddress )
1212 stepResult = stepResult and killResult
Devin Lim142b5342017-07-20 15:22:39 -07001213 main.Cluster.runningNodes[ i ].active = False
Jon Hall214f88b2020-09-21 10:21:42 -07001214 utilities.assert_equals( expect=main.TRUE, actual=stepResult,
1215 onpass="ONOS instance Killed",
1216 onfail="Error killing ONOS instance" )
Jon Halla604fd42018-05-04 14:27:27 -07001217 main.Cluster.reset()
Jon Hall43060f62020-06-23 13:13:33 -07001218 main.log.debug( "sleeping %i seconds" % ( sleep ) )
Jon Halla604fd42018-05-04 14:27:27 -07001219 time.sleep( sleep )
Pier3b58c652016-09-26 12:03:31 -07001220
Devin Lim142b5342017-07-20 15:22:39 -07001221 if len( nodes ) < main.Cluster.numCtrls:
Jon Halla604fd42018-05-04 14:27:27 -07001222 Testcaselib.verifyNodes( main )
1223 Testcaselib.verifyTopology( main, switches, links, expNodes )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001224
1225 @staticmethod
Jon Halla604fd42018-05-04 14:27:27 -07001226 def recoverOnos( main, nodes, switches, links, expNodes, sleep=None ):
Jon Hall1efcb3f2016-08-23 13:42:15 -07001227 """
1228 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
1229 switches, links, nodes: number of expected switches, links and nodes after recoverOnos, ex.: '4', '6'
1230 Recover an ONOS instance and verify the ONOS cluster can see the proper change
1231 """
Jon Hall3c910162018-03-07 14:42:16 -08001232 main.step( "Recovering ONOS instances with index(es): {}".format( nodes ) )
Jon Halla604fd42018-05-04 14:27:27 -07001233 if sleep is None:
1234 sleep = float( main.params[ 'timers' ][ 'OnosDiscovery' ] )
1235 else:
1236 sleep = float( sleep )
Jon Hall214f88b2020-09-21 10:21:42 -07001237 for i in nodes:
1238 node = main.Cluster.runningNodes[ i ]
1239 if node.inDocker:
1240 main.Cluster.startONOSDockerNode( i )
1241 else:
1242 main.ONOSbench.onosStart( node.ipAddress )
Jon Hall43060f62020-06-23 13:13:33 -07001243 main.log.debug( "sleeping %i seconds" % ( sleep ) )
Jon Halla604fd42018-05-04 14:27:27 -07001244 time.sleep( sleep )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001245 for i in nodes:
Jon Hall39570262020-11-17 12:18:19 -08001246 node = main.Cluster.runningNodes[ i ]
Jon Hall214f88b2020-09-21 10:21:42 -07001247 if node.inDocker:
1248 isUp = node.CLI.dockerExec( node.name, dockerPrompt=node.dockerPrompt )
1249 isUp = isUp and node.CLI.prepareForCLI()
1250 isUp = isUp and node.CLI.onosSecureSSH( userName=node.karafUser, userPWD=node.karafPass )
1251 else:
1252 isUp = main.ONOSbench.isup( node.ipAddress )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001253 utilities.assert_equals( expect=main.TRUE, actual=isUp,
1254 onpass="ONOS service is ready",
1255 onfail="ONOS service did not start properly" )
1256 for i in nodes:
1257 main.step( "Checking if ONOS CLI is ready" )
Devin Lim142b5342017-07-20 15:22:39 -07001258 ctrl = main.Cluster.runningNodes[ i ]
Jonghwan Hyun76a02b72018-01-30 16:40:48 +09001259 # ctrl.CLI.startCellCli()
Devin Lim142b5342017-07-20 15:22:39 -07001260 cliResult = ctrl.CLI.startOnosCli( ctrl.ipAddress,
1261 commandlineTimeout=60,
1262 onosStartTimeout=100 )
1263 ctrl.active = True
Jon Hall1efcb3f2016-08-23 13:42:15 -07001264 utilities.assert_equals( expect=main.TRUE,
1265 actual=cliResult,
1266 onpass="ONOS CLI is ready",
1267 onfail="ONOS CLI is not ready" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001268
Jon Halla604fd42018-05-04 14:27:27 -07001269 main.Cluster.reset()
Pier3b58c652016-09-26 12:03:31 -07001270 main.step( "Checking ONOS nodes" )
Jon Halla604fd42018-05-04 14:27:27 -07001271 Testcaselib.verifyNodes( main )
1272 Testcaselib.verifyTopology( main, switches, links, expNodes )
Pier3b58c652016-09-26 12:03:31 -07001273
Devin Lim142b5342017-07-20 15:22:39 -07001274 ready = utilities.retry( main.Cluster.active( 0 ).CLI.summary,
You Wang5bf49592020-07-08 18:47:46 -07001275 [ None, main.FALSE ],
Devin Lim142b5342017-07-20 15:22:39 -07001276 attempts=10,
1277 sleep=12 )
1278 if ready:
1279 ready = main.TRUE
1280 utilities.assert_equals( expect=main.TRUE, actual=ready,
Jon Hall1efcb3f2016-08-23 13:42:15 -07001281 onpass="ONOS summary command succeded",
1282 onfail="ONOS summary command failed" )
1283 if not ready:
1284 main.log.error( "ONOS startup failed!" )
Devin Lim44075962017-08-11 10:56:37 -07001285 main.cleanAndExit()
Jon Hall1efcb3f2016-08-23 13:42:15 -07001286
1287 @staticmethod
1288 def addHostCfg( main ):
1289 """
1290 Adds Host Configuration to ONOS
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001291 Updates expected state of the network ( pingChart )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001292 """
1293 import json
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001294 hostCfg = {}
Devin Lim57221b02018-02-14 15:45:36 -08001295 with open( main.configPath + main.forJson + "extra.json" ) as template:
Jon Hall1efcb3f2016-08-23 13:42:15 -07001296 hostCfg = json.load( template )
1297 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'in1' ]
1298 main.step( "Pushing new configuration" )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001299 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -07001300 main.Cluster.active( 0 ).REST.setNetCfg( cfg[ 'basic' ],
1301 subjectClass="hosts",
1302 subjectKey=urllib.quote( mac,
1303 safe='' ),
1304 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001305 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'out1' ]
1306 main.step( "Pushing new configuration" )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001307 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -07001308 main.Cluster.active( 0 ).REST.setNetCfg( cfg[ 'basic' ],
1309 subjectClass="hosts",
1310 subjectKey=urllib.quote( mac,
1311 safe='' ),
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001312 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001313 main.pingChart.update( { 'vlan1': { "expect": "True",
1314 "hosts": [ "olt1", "vsg1" ] } } )
1315 main.pingChart[ 'vlan5' ][ 'expect' ] = 0
1316 main.pingChart[ 'vlan10' ][ 'expect' ] = 0
Jon Hall10e2ab82020-09-15 17:14:54 -07001317 main.Cluster.active( 0 ).REST.setXconnect( "of:0000000000000001",
1318 vlanId=1,
1319 port1=5,
1320 port2=6 )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001321
1322 @staticmethod
1323 def delHostCfg( main ):
1324 """
1325 Removest Host Configuration from ONOS
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001326 Updates expected state of the network ( pingChart )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001327 """
1328 import json
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001329 hostCfg = {}
Devin Lim57221b02018-02-14 15:45:36 -08001330 with open( main.configPath + main.forJson + "extra.json" ) as template:
Jon Hall1efcb3f2016-08-23 13:42:15 -07001331 hostCfg = json.load( template )
1332 main.step( "Removing host configuration" )
1333 main.pingChart[ 'ip' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001334 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -07001335 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="hosts",
1336 subjectKey=urllib.quote(
1337 mac,
1338 safe='' ),
1339 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001340 main.step( "Removing configuration" )
1341 main.pingChart[ 'ip' ][ 'expect' ] = 0
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07001342 mac, cfg = hostCfg[ 'hosts' ].popitem()
Devin Lim142b5342017-07-20 15:22:39 -07001343 main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="hosts",
1344 subjectKey=urllib.quote(
1345 mac,
1346 safe='' ),
1347 configKey="basic" )
Jon Hall1efcb3f2016-08-23 13:42:15 -07001348 main.step( "Removing vlan configuration" )
1349 main.pingChart[ 'vlan1' ][ 'expect' ] = 0
Jon Hall10e2ab82020-09-15 17:14:54 -07001350 main.Cluster.active( 0 ).REST.deleteXconnect( "of:0000000000000001",
1351 vlanId=1 )
You Wang53dba1e2018-02-02 17:45:44 -08001352
1353 @staticmethod
1354 def verifyNetworkHostIp( main, attempts=10, sleep=10 ):
1355 """
1356 Verifies IP address assignment from the hosts
1357 """
1358 main.step( "Verify IP address assignment from hosts" )
1359 ipResult = main.TRUE
You Wangd66de192018-04-30 17:30:12 -07001360 main.Network.update()
You Wang6acb7a42018-05-04 15:12:25 -07001361 # Find out names of disconnected hosts
1362 disconnectedHosts = []
1363 if hasattr( main, "disconnectedIpv4Hosts" ):
1364 for host in main.disconnectedIpv4Hosts:
1365 disconnectedHosts.append( host )
1366 if hasattr( main, "disconnectedIpv6Hosts" ):
1367 for host in main.disconnectedIpv6Hosts:
1368 disconnectedHosts.append( host )
You Wang53dba1e2018-02-02 17:45:44 -08001369 for hostName, ip in main.expectedHosts[ "network" ].items():
You Wang6acb7a42018-05-04 15:12:25 -07001370 # Exclude disconnected hosts
1371 if hostName in disconnectedHosts:
1372 main.log.debug( "Skip verifying IP for {} as it's disconnected".format( hostName ) )
1373 continue
You Wang53dba1e2018-02-02 17:45:44 -08001374 ipResult = ipResult and utilities.retry( main.Network.verifyHostIp,
1375 main.FALSE,
1376 kwargs={ 'hostList': [ hostName ],
You Wangd66de192018-04-30 17:30:12 -07001377 'prefix': ip,
Jon Hall43060f62020-06-23 13:13:33 -07001378 'update': True },
You Wang53dba1e2018-02-02 17:45:44 -08001379 attempts=attempts,
1380 sleep=sleep )
1381 utilities.assert_equals( expect=main.TRUE, actual=ipResult,
1382 onpass="Verify network host IP succeded",
1383 onfail="Verify network host IP failed" )
1384
1385 @staticmethod
You Wangaec6a092018-08-06 15:36:31 -07001386 def verifyOnosHostIp( main, attempts=10, sleep=10, skipOnFail=True ):
You Wang53dba1e2018-02-02 17:45:44 -08001387 """
1388 Verifies host IP address assignment from ONOS
1389 """
1390 main.step( "Verify host IP address assignment in ONOS" )
1391 ipResult = main.TRUE
You Wang6acb7a42018-05-04 15:12:25 -07001392 # Find out IPs of disconnected hosts
1393 disconnectedIps = []
1394 if hasattr( main, "disconnectedIpv4Hosts" ):
1395 for host in main.disconnectedIpv4Hosts:
1396 disconnectedIps.append( main.expectedHosts[ "network" ][ host ] )
1397 if hasattr( main, "disconnectedIpv6Hosts" ):
1398 for host in main.disconnectedIpv6Hosts:
1399 disconnectedIps.append( main.expectedHosts[ "network" ][ host ] )
You Wang53dba1e2018-02-02 17:45:44 -08001400 for hostName, ip in main.expectedHosts[ "onos" ].items():
You Wang6acb7a42018-05-04 15:12:25 -07001401 # Exclude disconnected hosts
1402 if ip in disconnectedIps:
1403 main.log.debug( "Skip verifying IP for {} as it's disconnected".format( ip ) )
1404 continue
You Wang53dba1e2018-02-02 17:45:44 -08001405 ipResult = ipResult and utilities.retry( main.Cluster.active( 0 ).verifyHostIp,
1406 main.FALSE,
1407 kwargs={ 'hostList': [ hostName ],
1408 'prefix': ip },
1409 attempts=attempts,
1410 sleep=sleep )
1411 utilities.assert_equals( expect=main.TRUE, actual=ipResult,
1412 onpass="Verify ONOS host IP succeded",
1413 onfail="Verify ONOS host IP failed" )
You Wangaec6a092018-08-06 15:36:31 -07001414 if not ipResult and skipOnFail:
1415 Testcaselib.saveOnosDiagnostics( main )
You Wang89477152018-08-07 14:19:02 -07001416 Testcaselib.cleanup( main, copyKarafLog=False )
You Wangaec6a092018-08-06 15:36:31 -07001417 main.skipCase()
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08001418
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08001419 @staticmethod
1420 def updateIntfCfg( main, connectPoint, ips=[], untagged=0, tagged=[], native=0 ):
1421 """
1422 Description:
1423 Updates interface configuration in ONOS, with given IP and vlan parameters
1424 Required:
1425 * connectPoint: connect point to update configuration
1426 Optional:
1427 * ips: list of IP addresses, combined with '/xx' subnet representation,
1428 corresponding to 'ips' field in the configuration
1429 * untagged: vlan ID as an integer, corresponding to 'vlan-untagged' field in the configuration
1430 * tagged: integer list of vlan IDs, corresponding to 'vlan-tagged' field in the configuration
1431 * native: vlan ID as an integer, corresponding to 'vlan-native' field in the configuration
1432 """
1433 cfg = dict()
1434 cfg[ "ports" ] = dict()
1435 cfg[ "ports" ][ connectPoint ] = dict()
1436 cfg[ "ports" ][ connectPoint ][ "interfaces" ] = [ dict() ]
1437 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "ips" ] = ips
1438 if untagged > 0:
1439 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "vlan-untagged" ] = untagged
1440 else:
1441 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "vlan-tagged" ] = tagged
1442 if native > 0:
1443 cfg[ "ports" ][ connectPoint ][ "interfaces" ][ 0 ][ "vlan-native" ] = native
1444
1445 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( json.dumps( cfg ) ) )
You Wange24d6272018-03-27 21:18:50 -07001446
1447 @staticmethod
You Wang2cb70172018-07-25 16:44:13 -07001448 def startScapyHosts( main, scapyNames=[], mininetNames=[] ):
You Wange24d6272018-03-27 21:18:50 -07001449 """
1450 Create host components and start Scapy CLIs
You Wang2cb70172018-07-25 16:44:13 -07001451 scapyNames: list of names that will be used as component names for scapy hosts
1452 mininetNames: used when scapy host names are different from the host names
1453 in Mininet. E.g. when scapyNames=['h1Scapy'], it's required to specify the
1454 name of the corresponding Mininet host by mininetNames=['h1']
You Wange24d6272018-03-27 21:18:50 -07001455 """
1456 main.step( "Start Scapy CLIs" )
You Wang4cc61912018-08-28 10:10:58 -07001457 main.scapyNames = scapyNames if scapyNames else main.params[ 'SCAPY' ][ 'HOSTNAMES' ].split( ',' )
1458 main.scapyHosts = [] if not hasattr( main, "scapyHosts" ) else main.scapyHosts
You Wang2cb70172018-07-25 16:44:13 -07001459 for scapyName in main.scapyNames:
You Wang4cc61912018-08-28 10:10:58 -07001460 if hasattr( main, 'Mininet1' ):
1461 main.Scapy.createHostComponent( scapyName )
1462 scapyHandle = getattr( main, scapyName )
1463 if mininetNames:
1464 mininetName = mininetNames[ scapyNames.index( scapyName ) ]
1465 else:
1466 mininetName = None
Jon Hall43060f62020-06-23 13:13:33 -07001467 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
1468 scapyHandle.mExecDir = "/tmp"
1469 scapyHandle.hostHome = main.params[ "MN_DOCKER" ][ "home" ]
1470 main.log.debug( "start mn host component in docker" )
1471 scapyHandle.startHostCli( mininetName,
1472 execDir="/tmp",
1473 hostHome=main.params[ "MN_DOCKER" ][ "home" ] )
1474 else:
1475 main.log.debug( "start mn host component" )
1476 scapyHandle.startHostCli( mininetName )
You Wang2cb70172018-07-25 16:44:13 -07001477 else:
You Wang0fc21702018-11-02 17:49:18 -07001478 main.Network.createHostComponent( scapyName )
You Wang4cc61912018-08-28 10:10:58 -07001479 scapyHandle = getattr( main, scapyName )
1480 scapyHandle.connectInband()
1481 main.scapyHosts.append( scapyHandle )
You Wang2cb70172018-07-25 16:44:13 -07001482 scapyHandle.startScapy()
1483 scapyHandle.updateSelf()
1484 main.log.debug( scapyHandle.name )
1485 main.log.debug( scapyHandle.hostIp )
1486 main.log.debug( scapyHandle.hostMac )
1487
1488 @staticmethod
1489 def verifyTraffic( main, srcHosts, dstIp, dstHost, dstIntf, ipv6=False, expect=True, skipOnFail=True, maxRetry=2 ):
1490 """
1491 Verify unicast traffic by pinging from source hosts to the destination IP
1492 and capturing the packets at the destination host using Scapy.
1493 srcHosts: List of host names to send the ping packets
1494 dstIp: destination IP of the ping packets
1495 dstHost: host that runs Scapy to capture the packets
1496 dstIntf: name of the interface on the destination host
1497 expect: use True if the ping is expected to be captured at destination;
1498 Otherwise False
1499 skipOnFail: skip the rest of this test case if result is not expected
1500 maxRetry: number of retries allowed
1501 """
1502 from tests.dependencies.topology import Topology
1503 try:
1504 main.topo
1505 except ( NameError, AttributeError ):
1506 main.topo = Topology()
1507 main.step( "Verify traffic to {} by capturing packets on {}".format( dstIp, dstHost ) )
1508 result = main.TRUE
1509 for srcHost in srcHosts:
1510 trafficResult = main.topo.pingAndCapture( srcHost, dstIp, dstHost, dstIntf, ipv6,
1511 expect, maxRetry, True )
1512 if not trafficResult:
You Wang2cb70172018-07-25 16:44:13 -07001513 result = main.FALSE
1514 main.log.warn( "Scapy result from {} to {} is not as expected".format( srcHost, dstIp ) )
1515 utilities.assert_equals( expect=main.TRUE,
1516 actual=result,
1517 onpass="Verify traffic to {}: Pass".format( dstIp ),
1518 onfail="Verify traffic to {}: Fail".format( dstIp ) )
1519 if skipOnFail and result != main.TRUE:
1520 Testcaselib.saveOnosDiagnostics( main )
1521 Testcaselib.cleanup( main, copyKarafLog=False )
1522 main.skipCase()
You Wange24d6272018-03-27 21:18:50 -07001523
1524 @staticmethod
You Wang547893e2018-05-08 13:34:59 -07001525 def verifyMulticastTraffic( main, routeName, expect, skipOnFail=True, maxRetry=1 ):
You Wange24d6272018-03-27 21:18:50 -07001526 """
1527 Verify multicast traffic using scapy
1528 """
You Wangc564c6f2018-05-01 15:24:57 -07001529 from tests.dependencies.topology import Topology
1530 try:
1531 main.topo
1532 except ( NameError, AttributeError ):
1533 main.topo = Topology()
You Wang85747762018-05-11 15:51:50 -07001534 main.step( "Verify {} multicast traffic".format( routeName ) )
You Wangc02d8352018-04-17 16:42:10 -07001535 routeData = main.multicastConfig[ routeName ]
1536 srcs = main.mcastRoutes[ routeName ][ "src" ]
1537 dsts = main.mcastRoutes[ routeName ][ "dst" ]
1538 main.log.info( "Sending multicast traffic from {} to {}".format( [ routeData[ "src" ][ i ][ "host" ] for i in srcs ],
1539 [ routeData[ "dst" ][ i ][ "host" ] for i in dsts ] ) )
You Wang85747762018-05-11 15:51:50 -07001540 result = main.TRUE
You Wangc02d8352018-04-17 16:42:10 -07001541 for src in srcs:
1542 srcEntry = routeData[ "src" ][ src ]
1543 for dst in dsts:
1544 dstEntry = routeData[ "dst" ][ dst ]
1545 sender = getattr( main, srcEntry[ "host" ] )
1546 receiver = getattr( main, dstEntry[ "host" ] )
1547 main.Network.addRoute( str( srcEntry[ "host" ] ),
1548 str( routeData[ "group" ] ),
1549 str( srcEntry[ "interface" ] ),
1550 True if routeData[ "ipVersion" ] == 6 else False )
1551 # Build the packet
1552 sender.buildEther( dst=str( srcEntry[ "Ether" ] ) )
1553 if routeData[ "ipVersion" ] == 4:
1554 sender.buildIP( dst=str( routeData[ "group" ] ) )
1555 elif routeData[ "ipVersion" ] == 6:
1556 sender.buildIPv6( dst=str( routeData[ "group" ] ) )
1557 sender.buildUDP( ipVersion=routeData[ "ipVersion" ], dport=srcEntry[ "UDP" ] )
1558 sIface = srcEntry[ "interface" ]
1559 dIface = dstEntry[ "interface" ] if "interface" in dstEntry.keys() else None
1560 pktFilter = srcEntry[ "filter" ]
1561 pkt = srcEntry[ "packet" ]
1562 # Send packet and check received packet
1563 expectedResult = expect.pop( 0 ) if isinstance( expect, list ) else expect
You Wangc564c6f2018-05-01 15:24:57 -07001564 t3Cmd = "t3-troubleshoot -vv -sp {} -et ipv{} -d {} -dm {}".format( srcEntry[ "port" ], routeData[ "ipVersion" ],
Jon Halla604fd42018-05-04 14:27:27 -07001565 routeData[ "group" ], srcEntry[ "Ether" ] )
You Wangc564c6f2018-05-01 15:24:57 -07001566 trafficResult = main.topo.sendScapyPackets( sender, receiver, pktFilter, pkt, sIface, dIface,
1567 expectedResult, maxRetry, True, t3Cmd )
You Wang85747762018-05-11 15:51:50 -07001568 if not trafficResult:
1569 result = main.FALSE
1570 main.log.warn( "Scapy result from {} to {} is not as expected".format( srcEntry[ "host" ],
1571 dstEntry[ "host" ] ) )
1572 utilities.assert_equals( expect=main.TRUE,
1573 actual=result,
1574 onpass="Verify {} multicast traffic: Pass".format( routeName ),
1575 onfail="Verify {} multicast traffic: Fail".format( routeName ) )
You Wangba823f02018-05-17 13:54:08 -07001576 if skipOnFail and result != main.TRUE:
You Wang85747762018-05-11 15:51:50 -07001577 Testcaselib.saveOnosDiagnostics( main )
1578 Testcaselib.cleanup( main, copyKarafLog=False )
1579 main.skipCase()
You Wangc02d8352018-04-17 16:42:10 -07001580
1581 @staticmethod
You Wang85747762018-05-11 15:51:50 -07001582 def verifyPing( main, srcList, dstList, ipv6=False, expect=True, wait=1,
You Wang54b1d672018-06-11 16:44:13 -07001583 acceptableFailed=0, skipOnFail=True, stepMsg="Verify Ping",
1584 t3Simple=True ):
You Wang5da39c82018-04-26 22:55:08 -07001585 """
1586 Verify reachability from each host in srcList to each host in dstList
1587 """
1588 from tests.dependencies.topology import Topology
1589 try:
1590 main.topo
1591 except ( NameError, AttributeError ):
1592 main.topo = Topology()
You Wang85747762018-05-11 15:51:50 -07001593 main.step( stepMsg )
You Wang54b1d672018-06-11 16:44:13 -07001594 pingResult = main.topo.ping( srcList, dstList, ipv6, expect, wait, acceptableFailed, skipOnFail, t3Simple )
You Wang85747762018-05-11 15:51:50 -07001595 utilities.assert_equals( expect=main.TRUE,
1596 actual=pingResult,
1597 onpass="{}: Pass".format( stepMsg ),
1598 onfail="{}: Fail".format( stepMsg ) )
You Wang5da39c82018-04-26 22:55:08 -07001599 if not pingResult and skipOnFail:
1600 Testcaselib.saveOnosDiagnostics( main )
1601 Testcaselib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
1602 main.skipCase()
You Wangbc898b82018-05-03 16:22:34 -07001603
1604 @staticmethod
You Wang85747762018-05-11 15:51:50 -07001605 def verifyHostLocations( main, locationDict, retry=2 ):
You Wangbc898b82018-05-03 16:22:34 -07001606 """
1607 Verify if the specified host is discovered by ONOS on the given locations
1608 Required:
You Wang85747762018-05-11 15:51:50 -07001609 locationDict: a dictionary that maps host names to expected locations.
1610 locations could be a string or a list.
1611 ex. { "h1v4": ["of:0000000000000005/8"] }
You Wangbc898b82018-05-03 16:22:34 -07001612 Returns:
1613 main.TRUE if host is discovered on all locations provided, otherwise main.FALSE
1614 """
You Wang85747762018-05-11 15:51:50 -07001615 main.step( "Verify locations of hosts {}".format( locationDict.keys() ) )
1616 result = main.TRUE
1617 for hostName, locations in locationDict.items():
1618 main.log.info( "Verify host {} is discovered at {}".format( hostName, locations ) )
1619 hostIp = main.Network.getIPAddress( hostName, proto='IPV4' )
1620 if not hostIp:
1621 hostIp = main.Network.getIPAddress( hostName, proto='IPV6' )
1622 if not hostIp:
1623 main.log.warn( "Failed to find IP address for host {}, skipping location verification".format( hostName ) )
1624 result = main.FALSE
1625 continue
1626 locationResult = utilities.retry( main.Cluster.active( 0 ).CLI.verifyHostLocation,
1627 main.FALSE,
1628 args=( hostIp, locations ),
1629 attempts=retry + 1,
1630 sleep=10 )
1631 if not locationResult:
1632 result = main.FALSE
1633 main.log.warn( "location verification for host {} failed".format( hostName ) )
You Wang547893e2018-05-08 13:34:59 -07001634 utilities.assert_equals( expect=main.TRUE, actual=result,
You Wang85747762018-05-11 15:51:50 -07001635 onpass="Location verification passed",
1636 onfail="Location verification failed" )
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001637
1638 @staticmethod
You Wang6e5b48e2018-07-23 16:17:38 -07001639 def moveHost( main, hostName, srcSw, dstSw, gw, macAddr=None, prefixLen=None, cfg='', ipv6=False, vlan=None ):
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001640 """
1641 Move specified host from srcSw to dstSw.
1642 If srcSw and dstSw are same, the host will be moved from current port to
1643 next available port.
1644 Required:
1645 hostName: name of the host. e.g., "h1"
1646 srcSw: name of the switch that the host is attached to. e.g., "leaf1"
1647 dstSw: name of the switch that the host will be moved to. e.g., "leaf2"
1648 gw: ip address of the gateway of the new location
1649 Optional:
1650 macAddr: if specified, change MAC address of the host to the specified MAC address.
1651 prefixLen: prefix length
1652 cfg: port configuration as JSON string
1653 ipv6: Use True to move IPv6 host
You Wang6e5b48e2018-07-23 16:17:38 -07001654 vlan: vlan number of the host
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001655 """
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001656 if not hasattr( main, 'Mininet1' ):
1657 main.log.warn( "moveHost is supposed to be used only in Mininet." )
1658 return
1659
You Wang6e5b48e2018-07-23 16:17:38 -07001660 main.step( "Moving {} host {} from {} to {}".format( 'tagged' if vlan else 'untagged', hostName, srcSw, dstSw ) )
1661 main.Mininet1.moveHost( hostName, srcSw, dstSw, macAddr, prefixLen, ipv6, vlan=vlan )
1662 if not ipv6:
You Wang6260ed52018-07-18 17:54:25 -07001663 main.Mininet1.changeDefaultGateway( hostName, gw )
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001664 if cfg:
1665 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( cfg ),
1666 subjectClass="ports" )
You Wang6260ed52018-07-18 17:54:25 -07001667 # Wait for the host to get RA for setting up default gateway
Jon Hall43060f62020-06-23 13:13:33 -07001668 main.log.debug( "sleeping %i seconds" % ( 5 ) )
You Wang6260ed52018-07-18 17:54:25 -07001669 time.sleep( 5 )
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001670
1671 main.Mininet1.discoverHosts( [ hostName, ] )
1672
1673 # Update expectedHost when MAC address is changed.
1674 if macAddr is not None:
1675 ipAddr = main.expectedHosts[ "network" ][ hostName ]
1676 if ipAddr is not None:
1677 for hostName, ip in main.expectedHosts[ "onos" ].items():
1678 if ip == ipAddr:
1679 vlan = hostName.split( "/" )[ -1 ]
1680 del main.expectedHosts[ "onos" ][ hostName ]
You Wang7ea90582018-07-19 15:27:58 -07001681 main.expectedHosts[ "onos" ][ "{}/{}".format( macAddr.upper(), vlan ) ] = ip
Jonghwan Hyun785471d2018-05-14 14:48:19 -07001682 break
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001683
1684 @staticmethod
1685 def moveDualHomedHost( main, hostName, srcSw, srcPairSw, dstSw, dstPairSw, gw,
You Wang6e5b48e2018-07-23 16:17:38 -07001686 macAddr=None, prefixLen=24, cfg='', ipv6=False, vlan=None ):
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001687 """
1688 Move specified dual-homed host from srcSw-srcPairSw to dstSw-dstPairSw.
1689 If srcSw-srcPairSw and dstSw-dstPairSw are same, the host will be moved from current port
1690 to next available port.
1691 Required:
1692 hostName: name of the host. e.g., "h1"
1693 srcSw: name of the switch that the host is attached to. e.g., "leaf1"
1694 srcPairSw: name of the paired-switch that the host is attached to. e.g., "leaf2"
1695 dstSw: name of the switch that the host will be moved to. e.g., "leaf1"
1696 dstPairSw: name of the paired-switch that the host will be moved to. e.g., "leaf2"
1697 gw: ip address of the gateway of the new location
1698 Optional:
1699 macAddr: if specified, change MAC address of the host to the specified MAC address.
1700 prefixLen: prefix length
1701 cfg: port configurations as JSON string
You Wang7ea90582018-07-19 15:27:58 -07001702 ipv6: Use True to move IPv6 host
You Wang6e5b48e2018-07-23 16:17:38 -07001703 vlan: vlan number of the host
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001704 """
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001705 if not hasattr( main, 'Mininet1' ):
1706 main.log.warn( "moveDualHomedHost is supposed to be used only in Mininet." )
1707 return
1708
You Wang6e5b48e2018-07-23 16:17:38 -07001709 main.step( "Moving {} host {} from {} and {} to {} and {}".format( 'tagged' if vlan else 'untagged', hostName,
1710 srcSw, srcPairSw, dstSw, dstPairSw ) )
1711 main.Mininet1.moveDualHomedHost( hostName, srcSw, srcPairSw, dstSw, dstPairSw,
1712 macAddr=macAddr, prefixLen=prefixLen, ipv6=ipv6, vlan=vlan )
1713 if not ipv6:
You Wang7ea90582018-07-19 15:27:58 -07001714 main.Mininet1.changeDefaultGateway( hostName, gw )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001715 if cfg:
1716 main.Cluster.active( 0 ).REST.setNetCfg( json.loads( cfg ),
1717 subjectClass="ports" )
You Wang7ea90582018-07-19 15:27:58 -07001718 # Wait for the host to get RA for setting up default gateway
Jon Hall43060f62020-06-23 13:13:33 -07001719 main.log.debug( "sleeping %i seconds" % ( 5 ) )
You Wang7ea90582018-07-19 15:27:58 -07001720 time.sleep( 5 )
Jonghwan Hyun5fad1782018-05-21 14:11:16 -07001721
1722 main.Mininet1.discoverHosts( [ hostName, ] )
1723
1724 # Update expectedHost when MAC address is changed.
1725 if macAddr is not None:
1726 ipAddr = main.expectedHosts[ "network" ][ hostName ]
1727 if ipAddr is not None:
1728 for hostName, ip in main.expectedHosts[ "onos" ].items():
1729 if ip == ipAddr:
1730 vlan = hostName.split( "/" )[ -1 ]
1731 del main.expectedHosts[ "onos" ][ hostName ]
You Wang7ea90582018-07-19 15:27:58 -07001732 main.expectedHosts[ "onos" ][ "{}/{}".format( macAddr.upper(), vlan ) ] = ip
Jon Hall43060f62020-06-23 13:13:33 -07001733
1734 @staticmethod
1735 def mnDockerSetup( main ):
1736 """
1737 Optionally start and setup docker image for mininet
1738 """
Jon Hall9b0de1f2020-08-24 15:38:04 -07001739 try:
1740 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
Jon Hall43060f62020-06-23 13:13:33 -07001741
Jon Hall9b0de1f2020-08-24 15:38:04 -07001742 main.log.info( "Creating Mininet Docker" )
1743 handle = main.Mininet1.handle
1744 # build docker image
1745 dockerFilePath = "%s/../dependencies/" % main.testDir
1746 dockerName = "trellis_mininet"
1747 # Stop any leftover container
1748 main.Mininet1.dockerStop( dockerName )
1749 # TODO: assert on these docker calls
Jon Hall39570262020-11-17 12:18:19 -08001750 main.Mininet1.dockerBuild( dockerFilePath, dockerName, pull=True )
Jon Hallf6aeda22020-07-28 09:12:56 -07001751
Jon Hall9b0de1f2020-08-24 15:38:04 -07001752 confDir = "/tmp/mn_conf/"
1753 # Try to ensure the destination exists
1754 main.log.info( "Create folder for network config files" )
1755 handle.sendline( "rm -rf %s" % confDir )
1756 handle.expect( main.Mininet1.Prompt() )
1757 main.log.debug( handle.before + handle.after )
1758 handle.sendline( "mkdir -p %s" % confDir )
1759 handle.expect( main.Mininet1.Prompt() )
1760 main.log.debug( handle.before + handle.after )
Jon Hall39570262020-11-17 12:18:19 -08001761 handle.sendline( "sudo rm -rf /tmp/mn-stratum/*" )
1762 handle.expect( main.Mininet1.Prompt() )
Jon Hall9b0de1f2020-08-24 15:38:04 -07001763 # Make sure permissions are correct
1764 handle.sendline( "sudo chown %s:%s %s" % ( main.Mininet1.user_name, main.Mininet1.user_name, confDir ) )
1765 handle.expect( main.Mininet1.Prompt() )
1766 handle.sendline( "sudo chmod -R a+rwx %s" % ( confDir ) )
1767 handle.expect( main.Mininet1.Prompt() )
1768 main.log.debug( handle.before + handle.after )
1769 # Start docker container
1770 runResponse = main.Mininet1.dockerRun( main.params[ 'MN_DOCKER' ][ 'name' ],
1771 dockerName,
1772 main.params[ 'MN_DOCKER' ][ 'args' ] )
1773 if runResponse == main.FALSE:
1774 main.log.error( "Docker container already running, aborting test" )
1775 main.cleanup()
1776 main.exit()
Jon Hall43060f62020-06-23 13:13:33 -07001777
Jon Hall9b0de1f2020-08-24 15:38:04 -07001778 main.Mininet1.dockerAttach( dockerName, dockerPrompt='~#' )
1779 main.Mininet1.sudoRequired = False
Jon Hall43060f62020-06-23 13:13:33 -07001780
Jon Hall9b0de1f2020-08-24 15:38:04 -07001781 # Fow when we create component handles
1782 main.Mininet1.mExecDir = "/tmp"
1783 main.Mininet1.hostHome = main.params[ "MN_DOCKER" ][ "home" ]
1784 main.Mininet1.hostPrompt = "/home/root#"
1785
1786 # For some reason docker isn't doing this
1787 main.Mininet1.handle.sendline( "echo \"127.0.0.1 $(cat /etc/hostname)\" >> /etc/hosts" )
1788 main.Mininet1.handle.expect( "etc/hosts" )
1789 main.Mininet1.handle.expect( main.Mininet1.Prompt() )
1790 except Exception as e:
1791 main.log.exception( "Error seting up mininet" )
Jon Hall39570262020-11-17 12:18:19 -08001792 main.skipCase( result="FAIL", msg=e )
Jon Hall43060f62020-06-23 13:13:33 -07001793
1794 @staticmethod
1795 def mnDockerTeardown( main ):
1796 """
1797 Optionally stop and cleanup docker image for mininet
1798 """
1799
1800 if hasattr( main, 'Mininet1' ):
1801 if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
Jon Hall3c0114c2020-08-11 15:07:42 -07001802 main.log.info( "Exiting from Mininet Docker" )
Jon Hall43060f62020-06-23 13:13:33 -07001803
1804 # Detach from container
Jon Hall43060f62020-06-23 13:13:33 -07001805 try:
Jon Hall3c0114c2020-08-11 15:07:42 -07001806 main.Mininet1.dockerDisconnect()
Jon Hall43060f62020-06-23 13:13:33 -07001807 main.Mininet1.sudoRequired = True
1808 except Exception as e:
1809 main.log.error( e )
1810
Jon Hall39570262020-11-17 12:18:19 -08001811 # Save docker logs
1812 copyResult = main.ONOSbench.scp( main.Mininet1,
1813 "/tmp/mn-stratum/*",
1814 main.logdir,
1815 direction="from",
1816 options="-rp" )
1817
1818
Jon Hall43060f62020-06-23 13:13:33 -07001819 @staticmethod
1820 def setOnosConfig( main ):
1821 """
1822 Read and Set onos configurations from the params file
1823 """
1824 main.step( "Set ONOS configurations" )
1825 config = main.params.get( 'ONOS_Configuration' )
1826 if config:
1827 main.log.debug( config )
1828 checkResult = main.TRUE
1829 for component in config:
1830 for setting in config[ component ]:
1831 value = config[ component ][ setting ]
1832 check = main.Cluster.next().setCfg( component, setting, value )
1833 main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
1834 checkResult = check and checkResult
1835 utilities.assert_equals( expect=main.TRUE,
1836 actual=checkResult,
1837 onpass="Successfully set config",
1838 onfail="Failed to set config" )
1839 else:
1840 main.log.warn( "No configurations were specified to be changed after startup" )
1841
1842 @staticmethod
1843 def setOnosLogLevels( main ):
1844 """
1845 Read and Set onos log levels from the params file
1846 """
1847 main.step( 'Set logging levels' )
Jon Hall06fd0df2021-01-25 15:50:06 -08001848 # Get original values incase we want to reset them
1849 ctrl = main.Cluster.active(0)
Jon Halla7b27e62021-06-29 12:13:51 -07001850 ctrl.CLI.clearBuffer( timeout=1 )
Jon Hall06fd0df2021-01-25 15:50:06 -08001851 ctrl.CLI.logList()
1852
Jon Hall43060f62020-06-23 13:13:33 -07001853 logging = True
1854 try:
1855 logs = main.params.get( 'ONOS_Logging', False )
1856 if logs:
1857 for namespace, level in logs.items():
1858 for ctrl in main.Cluster.active():
1859 ctrl.CLI.logSet( level, namespace )
1860 except AttributeError:
1861 logging = False
1862 utilities.assert_equals( expect=True, actual=logging,
1863 onpass="Set log levels",
1864 onfail="Failed to set log levels" )
Jon Hall06fd0df2021-01-25 15:50:06 -08001865
1866 @staticmethod
1867 def resetOnosLogLevels( main ):
1868 """
1869 Read and reset onos log levels to a previously read set of values
1870 """
1871 main.step( 'Reset logging levels' )
1872 # Get original values incase we want to reset them
1873 ctrl = main.Cluster.active(0)
Jon Halla7b27e62021-06-29 12:13:51 -07001874 ctrl.CLI.clearBuffer( timeout=1 )
Jon Hall06fd0df2021-01-25 15:50:06 -08001875 currentLevels = ctrl.CLI.logList( saveValues=False )
1876 origLevels = ctrl.CLI.logLevels
1877 toBeSet = {}
1878 for logger, level in currentLevels.iteritems():
1879 if logger not in origLevels:
1880 toBeSet[ logger ] = origLevels[ 'ROOT' ]
1881 else:
1882 oldLevel = origLevels[ logger ]
1883 if level != oldLevel:
1884 toBeSet[ logger ] = oldLevel
Jon Hallef1480b2021-03-31 13:37:41 -07001885 # In case a previous test didn't reset
1886 logs = main.params.get( 'ONOS_Logging_Reset', False )
1887 if logs:
1888 for namespace, level in logs.items():
1889 toBeSet[ namespace ] = level
Jon Hall06fd0df2021-01-25 15:50:06 -08001890 logging = True
1891 try:
1892 for logger, level in toBeSet.iteritems():
1893 for ctrl in main.Cluster.active():
1894 ctrl.CLI.logSet( level, logger )
1895 except AttributeError:
1896 logging = False
1897 utilities.assert_equals( expect=True, actual=logging,
1898 onpass="Reset log levels",
1899 onfail="Failed to reset log levels" )