blob: 5d98972dad3b0e529d51fe445583812abb882bb6 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
Jon Hallbe6dfc42015-01-12 17:37:25 -08005author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
Jon Hall7eb38402015-01-08 17:19:54 -08008TestON is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 2 of the License, or
11( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
Jon Hall7eb38402015-01-08 17:19:54 -080013TestON is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070017
Jon Hall7eb38402015-01-08 17:19:54 -080018You should have received a copy of the GNU General Public License
19along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
21
Jon Hallbe6dfc42015-01-12 17:37:25 -080022MininetCliDriver is the basic driver which will handle the Mininet functions
23
Jon Hall272a4db2015-01-12 17:43:48 -080024Some functions rely on STS module. To install this,
25 git clone https://github.com/jhall11/sts.git
26
Jon Hallbe6dfc42015-01-12 17:37:25 -080027Some functions rely on a modified version of Mininet. These functions
28should all be noted in the comments. To get this MN version run these commands
29from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080030 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080032 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080033 git pull
34
Jon Hall272a4db2015-01-12 17:43:48 -080035
36 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080037changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070038import pexpect
adminbae64d82013-08-01 10:50:15 -070039import re
40import sys
Jon Hall7eb38402015-01-08 17:19:54 -080041sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070044
Jon Hall7eb38402015-01-08 17:19:54 -080045
46class MininetCliDriver( Emulator ):
47
48 """
49 MininetCliDriver is the basic driver which will handle
50 the Mininet functions"""
51 def __init__( self ):
52 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070053 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080054 self.name = None
Jon Hall7eb38402015-01-08 17:19:54 -080055 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070056 self.flag = 0
57
Jon Hall7eb38402015-01-08 17:19:54 -080058 def connect( self, **connectargs ):
59 """
60 Here the main is the TestON instance after creating
61 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080062 try:
63 for key in connectargs:
64 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080065
kelvin-onlaba1484582015-02-02 15:46:20 -080066 self.name = self.options[ 'name' ]
67 self.handle = super(
68 MininetCliDriver,
69 self ).connect(
70 user_name=self.user_name,
71 ip_address=self.ip_address,
72 port=None,
73 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080074
kelvin-onlaba1484582015-02-02 15:46:20 -080075 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080076 main.log.info( "Connection successful to the host " +
77 self.user_name +
78 "@" +
79 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080080 return main.TRUE
81 else:
82 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080083 self.user_name +
84 "@" +
85 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -080086 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -080087 return main.FALSE
88 except pexpect.EOF:
89 main.log.error( self.name + ": EOF exception found" )
90 main.log.error( self.name + ": " + self.handle.before )
91 main.cleanup()
92 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -080093 except Exception:
94 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -080095 main.cleanup()
96 main.exit()
97
Jon Hallefbd9792015-03-05 16:11:36 -080098 def startNet( self, topoFile='', args='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -080099 """
100 Starts Mininet accepts a topology(.py) file and/or an optional
Jon Hallefbd9792015-03-05 16:11:36 -0800101 argument ,to start the mininet, as a parameter.
Jon Hall21270ac2015-02-16 17:59:55 -0800102 Returns main.TRUE if the mininet starts successfully and
103 main.FALSE otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800104 """
Jon Hall7eb38402015-01-08 17:19:54 -0800105 if self.handle:
106 main.log.info(
107 self.name +
108 ": Clearing any residual state or processes" )
109 self.handle.sendline( "sudo mn -c" )
110 i = self.handle.expect( [ 'password\sfor\s',
111 'Cleanup\scomplete',
112 pexpect.EOF,
113 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800114 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800115 if i == 0:
116 main.log.info( self.name + ": Sending sudo password" )
117 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800118 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800119 '\$',
120 pexpect.EOF,
121 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800122 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800123 if i == 1:
124 main.log.info( self.name + ": Clean" )
125 elif i == 2:
126 main.log.error( self.name + ": Connection terminated" )
127 elif i == 3: # timeout
128 main.log.error(
129 self.name +
130 ": Something while cleaning MN took too long... " )
Jon Hallefbd9792015-03-05 16:11:36 -0800131 if topoFile == '' and args == '':
kelvin-onlaba1484582015-02-02 15:46:20 -0800132 main.log.info( self.name + ": building fresh mininet" )
133 # for reactive/PARP enabled tests
134 cmdString = "sudo mn " + self.options[ 'arg1' ] +\
135 " " + self.options[ 'arg2' ] +\
136 " --mac --controller " +\
137 self.options[ 'controller' ] + " " +\
138 self.options[ 'arg3' ]
Jon Hallfbc828e2015-01-06 17:30:19 -0800139
kelvin-onlaba1484582015-02-02 15:46:20 -0800140 argList = self.options[ 'arg1' ].split( "," )
141 global topoArgList
142 topoArgList = argList[ 0 ].split( " " )
143 argList = map( int, argList[ 1: ] )
144 topoArgList = topoArgList[ 1: ] + argList
Jon Hallfbc828e2015-01-06 17:30:19 -0800145
kelvin-onlaba1484582015-02-02 15:46:20 -0800146 self.handle.sendline( cmdString )
147 self.handle.expect( [ "sudo mn",
148 pexpect.EOF,
149 pexpect.TIMEOUT ] )
150 while True:
151 i = self.handle.expect( [ 'mininet>',
152 '\*\*\*',
153 'Exception',
154 pexpect.EOF,
155 pexpect.TIMEOUT ],
156 timeout )
157 if i == 0:
158 main.log.info( self.name + ": mininet built" )
159 return main.TRUE
160 if i == 1:
161 self.handle.expect(
162 [ "\n", pexpect.EOF, pexpect.TIMEOUT ] )
163 main.log.info( self.handle.before )
164 elif i == 2:
165 main.log.error(
166 self.name +
167 ": Launching mininet failed..." )
168 return main.FALSE
169 elif i == 3:
170 main.log.error( self.name + ": Connection timeout" )
171 return main.FALSE
172 elif i == 4: # timeout
173 main.log.error(
174 self.name +
175 ": Something took too long... " )
176 return main.FALSE
177 return main.TRUE
178 else:
179 main.log.info( "Starting topo file " + topoFile )
Jon Hallefbd9792015-03-05 16:11:36 -0800180 if args is None:
kelvin-onlaba1484582015-02-02 15:46:20 -0800181 args = ''
182 else:
183 main.log.info( "args = " + args)
184 self.handle.sendline( 'sudo ' + topoFile + ' ' + args)
Jon Hall7eb38402015-01-08 17:19:54 -0800185 i = self.handle.expect( [ 'mininet>',
Jon Hallefbd9792015-03-05 16:11:36 -0800186 pexpect.EOF,
187 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800188 timeout)
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800189 if i == 0:
190 main.log.info(self.name + ": Network started")
191 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800192 elif i == 1:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800193 main.log.error( self.name + ": Connection timeout" )
194 return main.FALSE
kelvin-onlabec228b82015-02-09 15:45:55 -0800195 elif i == 2: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800196 main.log.error(
197 self.name +
198 ": Something took too long... " )
199 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -0800200 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800201 else: # if no handle
202 main.log.error(
203 self.name +
204 ": Connection failed to the host " +
kelvin-onlab08679eb2015-01-21 16:11:48 -0800205 self.user_name +
Jon Hall7eb38402015-01-08 17:19:54 -0800206 "@" +
kelvin-onlab08679eb2015-01-21 16:11:48 -0800207 self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800208 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700209 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800210
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800211 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400212 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800213 # In tree topology, if fanout arg is not given, by default it is 2
214 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400215 fanout = 2
216 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500217 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800218 while( k <= depth - 1 ):
219 count = count + pow( fanout, k )
220 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800221 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800222 while( k <= depth - 2 ):
223 # depth-2 gives you only core links and not considering
224 # edge links as seen by ONOS. If all the links including
225 # edge links are required, do depth-1
226 count = count + pow( fanout, k )
227 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800228 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800229 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800230 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800231
Jon Hall7eb38402015-01-08 17:19:54 -0800232 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800233 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800234 # by default it is 1
235 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400236 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800237 numSwitches = depth
238 numHostsPerSw = fanout
239 totalNumHosts = numSwitches * numHostsPerSw
240 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800241 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800242 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800243 topoDict = { "num_switches": int( numSwitches ),
244 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400245 return topoDict
246
kelvin-onlabd3b64892015-01-20 13:26:24 -0800247 def calculateSwAndLinks( self ):
248 topoDict = self.numSwitchesN_links( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400249 return topoDict
250
Jon Hall7eb38402015-01-08 17:19:54 -0800251 def pingall( self, timeout=300 ):
252 """
253 Verifies the reachability of the hosts using pingall command.
254 Optional parameter timeout allows you to specify how long to
255 wait for pingall to complete
256 Returns:
257 main.TRUE if pingall completes with no pings dropped
258 otherwise main.FALSE"""
259 if self.handle:
260 main.log.info(
261 self.name +
262 ": Checking reachabilty to the hosts using pingall" )
Jon Hall6094a362014-04-11 14:46:56 -0700263 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800264 response = self.execute(
265 cmd="pingall",
266 prompt="mininet>",
267 timeout=int( timeout ) )
Jon Hallb1290e82014-11-18 16:17:48 -0500268 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800269 main.log.error( self.name + ": EOF exception found" )
270 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500271 main.cleanup()
272 main.exit()
273 except pexpect.TIMEOUT:
Jon Hall7eb38402015-01-08 17:19:54 -0800274 # We may not want to kill the test if pexpect times out
275 main.log.error( self.name + ": TIMEOUT exception found" )
276 main.log.error( self.name +
277 ": " +
278 str( self.handle.before ) )
279 # NOTE: mininet's pingall rounds, so we will check the number of
280 # passed and number of failed
281 pattern = "Results\:\s0\%\sdropped\s\(" +\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800282 "(?P<passed>[\d]+)/(?P=passed)"
Jon Hall7eb38402015-01-08 17:19:54 -0800283 if re.search( pattern, response ):
284 main.log.info( self.name + ": All hosts are reachable" )
adminbae64d82013-08-01 10:50:15 -0700285 return main.TRUE
286 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800287 main.log.error( self.name + ": Unable to reach all the hosts" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800288 main.log.info( "Pingall output: " + str( response ) )
Jon Hall7eb38402015-01-08 17:19:54 -0800289 # NOTE: Send ctrl-c to make sure pingall is done
290 self.handle.send( "\x03" )
291 self.handle.expect( "Interrupt" )
292 self.handle.expect( "mininet>" )
adminbae64d82013-08-01 10:50:15 -0700293 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800294 else:
295 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallb1290e82014-11-18 16:17:48 -0500296 main.cleanup()
297 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700298
Jon Hall7eb38402015-01-08 17:19:54 -0800299 def fpingHost( self, **pingParams ):
300 """
301 Uses the fping package for faster pinging...
302 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800303 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800304 command = args[ "SRC" ] + \
305 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
306 self.handle.sendline( command )
307 self.handle.expect(
308 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
309 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
310 response = self.handle.before
311 if re.search( ":\s-", response ):
312 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700313 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800314 elif re.search( ":\s\d{1,2}\.\d\d", response ):
315 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700316 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800317 main.log.info( self.name + ": Install fping on mininet machine... " )
318 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700319 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800320
Jon Hall7eb38402015-01-08 17:19:54 -0800321 def pingHost( self, **pingParams ):
322 """
323 Ping from one mininet host to another
324 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800325 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800326 command = args[ "SRC" ] + " ping " + \
327 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700328 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800329 main.log.warn( "Sending: " + command )
330 self.handle.sendline( command )
331 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700332 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800333 main.log.error(
334 self.name +
335 ": timeout when waiting for response from mininet" )
336 main.log.error( "response: " + str( self.handle.before ) )
337 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700338 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800339 main.log.error(
340 self.name +
341 ": timeout when waiting for response from mininet" )
342 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700343 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800344 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800345 main.log.error( self.name + ": EOF exception found" )
346 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700347 main.cleanup()
348 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800349 main.log.info( self.name + ": Ping Response: " + response )
350 if re.search( ',\s0\%\spacket\sloss', response ):
351 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800352 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700353 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800354 else:
355 main.log.error(
356 self.name +
357 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800358 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700359 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800360
Jon Hall7eb38402015-01-08 17:19:54 -0800361 def checkIP( self, host ):
362 """
363 Verifies the host's ip configured or not."""
364 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700365 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800366 response = self.execute(
367 cmd=host +
368 " ifconfig",
369 prompt="mininet>",
370 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800371 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800372 main.log.error( self.name + ": EOF exception found" )
373 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700374 main.cleanup()
375 main.exit()
adminbae64d82013-08-01 10:50:15 -0700376
Jon Hall7eb38402015-01-08 17:19:54 -0800377 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800378 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
379 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
380 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
381 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
382 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800383 # pattern = "inet addr:10.0.0.6"
384 if re.search( pattern, response ):
385 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700386 return main.TRUE
387 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800388 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700389 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800390 else:
391 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800392
Jon Hall7eb38402015-01-08 17:19:54 -0800393 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800394 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700395 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800396 response = self.execute(
397 cmd="h1 /usr/sbin/sshd -D&",
398 prompt="mininet>",
399 timeout=10 )
400 response = self.execute(
401 cmd="h4 /usr/sbin/sshd -D&",
402 prompt="mininet>",
403 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700404 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800405 vars( self )[ key ] = connectargs[ key ]
406 response = self.execute(
407 cmd="xterm h1 h4 ",
408 prompt="mininet>",
409 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800410 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800411 main.log.error( self.name + ": EOF exception found" )
412 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700413 main.cleanup()
414 main.exit()
adminbae64d82013-08-01 10:50:15 -0700415 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800416 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700417 if self.flag == 0:
418 self.flag = 1
419 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800420 else:
adminbae64d82013-08-01 10:50:15 -0700421 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800422
kelvin-onlaba1484582015-02-02 15:46:20 -0800423 def moveHost( self, host, oldSw, newSw, ):
424 """
425 Moves a host from one switch to another on the fly
426 Note: The intf between host and oldSw when detached
427 using detach(), will still show up in the 'net'
428 cmd, because switch.detach() doesn't affect switch.intfs[]
429 (which is correct behavior since the interfaces
430 haven't moved).
431 """
432 if self.handle:
433 try:
434 # Bring link between oldSw-host down
Jon Hallefbd9792015-03-05 16:11:36 -0800435 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'"+ host +\
436 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800437 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800438 response = self.execute( cmd=cmd,
439 prompt="mininet>",
440 timeout=10 )
kelvin-onlaba1484582015-02-02 15:46:20 -0800441
442 # Determine hostintf and Oldswitchintf
443 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800444 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800445 print "cmd2= ", cmd
446 self.handle.sendline( cmd )
447 self.handle.expect( "mininet>" )
448
shahshreya73537862015-02-11 15:15:24 -0800449 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800450 cmd = "px ipaddr = hintf.IP()"
451 print "cmd3= ", cmd
452 self.handle.sendline( cmd )
453 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800454
455 cmd = "px macaddr = hintf.MAC()"
456 print "cmd3= ", cmd
457 self.handle.sendline( cmd )
458 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800459
460 # Detach interface between oldSw-host
461 cmd = "px " + oldSw + ".detach( sintf )"
462 print "cmd4= ", cmd
463 self.handle.sendline( cmd )
464 self.handle.expect( "mininet>" )
465
466 # Add link between host-newSw
467 cmd = "py net.addLink(" + host + "," + newSw + ")"
468 print "cmd5= ", cmd
469 self.handle.sendline( cmd )
470 self.handle.expect( "mininet>" )
471
472 # Determine hostintf and Newswitchintf
473 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800474 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800475 print "cmd6= ", cmd
476 self.handle.sendline( cmd )
477 self.handle.expect( "mininet>" )
478
479 # Attach interface between newSw-host
480 cmd = "px " + newSw + ".attach( sintf )"
481 print "cmd3= ", cmd
482 self.handle.sendline( cmd )
483 self.handle.expect( "mininet>" )
484
485 # Set ipaddress of the host-newSw interface
486 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
487 print "cmd7 = ", cmd
488 self.handle.sendline( cmd )
489 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800490
491 # Set macaddress of the host-newSw interface
492 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
493 print "cmd8 = ", cmd
494 self.handle.sendline( cmd )
495 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800496
497 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800498 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800499 self.handle.sendline( cmd )
500 self.handle.expect( "mininet>" )
501 print "output = ", self.handle.before
502
503 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800504 cmd = host + " ifconfig"
505 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800506 self.handle.sendline( cmd )
507 self.handle.expect( "mininet>" )
508 print "ifconfig o/p = ", self.handle.before
509
510 return main.TRUE
511 except pexpect.EOF:
512 main.log.error( self.name + ": EOF exception found" )
513 main.log.error( self.name + ": " + self.handle.before )
514 return main.FALSE
515
Jon Hall7eb38402015-01-08 17:19:54 -0800516 def changeIP( self, host, intf, newIP, newNetmask ):
517 """
518 Changes the ip address of a host on the fly
519 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800520 if self.handle:
521 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800522 cmd = host + " ifconfig " + intf + " " + \
523 newIP + " " + 'netmask' + " " + newNetmask
524 self.handle.sendline( cmd )
525 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800526 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800527 main.log.info( "response = " + response )
528 main.log.info(
529 "Ip of host " +
530 host +
531 " changed to new IP " +
532 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800533 return main.TRUE
534 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800535 main.log.error( self.name + ": EOF exception found" )
536 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800537 return main.FALSE
538
Jon Hall7eb38402015-01-08 17:19:54 -0800539 def changeDefaultGateway( self, host, newGW ):
540 """
541 Changes the default gateway of a host
542 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800543 if self.handle:
544 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800545 cmd = host + " route add default gw " + newGW
546 self.handle.sendline( cmd )
547 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800548 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800549 main.log.info( "response = " + response )
550 main.log.info(
551 "Default gateway of host " +
552 host +
553 " changed to " +
554 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800555 return main.TRUE
556 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800557 main.log.error( self.name + ": EOF exception found" )
558 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800559 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800560
Jon Hall7eb38402015-01-08 17:19:54 -0800561 def addStaticMACAddress( self, host, GW, macaddr ):
562 """
Jon Hallefbd9792015-03-05 16:11:36 -0800563 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800564 if self.handle:
565 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800566 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
567 cmd = host + " arp -s " + GW + " " + macaddr
568 self.handle.sendline( cmd )
569 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800570 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800571 main.log.info( "response = " + response )
572 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800573 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800574 GW +
575 " changed to " +
576 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800577 return main.TRUE
578 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800579 main.log.error( self.name + ": EOF exception found" )
580 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800581 return main.FALSE
582
Jon Hall7eb38402015-01-08 17:19:54 -0800583 def verifyStaticGWandMAC( self, host ):
584 """
585 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800586 if self.handle:
587 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800588 # h1 arp -an
589 cmd = host + " arp -an "
590 self.handle.sendline( cmd )
591 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800592 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800593 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800594 return main.TRUE
595 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800596 main.log.error( self.name + ": EOF exception found" )
597 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800598 return main.FALSE
599
Jon Hall7eb38402015-01-08 17:19:54 -0800600 def getMacAddress( self, host ):
601 """
602 Verifies the host's ip configured or not."""
603 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700604 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800605 response = self.execute(
606 cmd=host +
607 " ifconfig",
608 prompt="mininet>",
609 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800610 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800611 main.log.error( self.name + ": EOF exception found" )
612 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700613 main.cleanup()
614 main.exit()
adminbae64d82013-08-01 10:50:15 -0700615
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700616 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800617 macAddressSearch = re.search( pattern, response, re.I )
618 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800619 main.log.info(
620 self.name +
621 ": Mac-Address of Host " +
622 host +
623 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800624 macAddress )
625 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700626 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800627 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700628
Jon Hall7eb38402015-01-08 17:19:54 -0800629 def getInterfaceMACAddress( self, host, interface ):
630 """
631 Return the IP address of the interface on the given host"""
632 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700633 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800634 response = self.execute( cmd=host + " ifconfig " + interface,
635 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800636 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800637 main.log.error( self.name + ": EOF exception found" )
638 main.log.error( self.name + ": " + self.handle.before )
639 main.cleanup()
640 main.exit()
641
642 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800643 macAddressSearch = re.search( pattern, response, re.I )
644 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800645 main.log.info( "No mac address found in %s" % response )
646 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800647 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800648 main.log.info(
649 "Mac-Address of " +
650 host +
651 ":" +
652 interface +
653 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800654 macAddress )
655 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800656 else:
657 main.log.error( "Connection failed to the host" )
658
659 def getIPAddress( self, host ):
660 """
661 Verifies the host's ip configured or not."""
662 if self.handle:
663 try:
664 response = self.execute(
665 cmd=host +
666 " ifconfig",
667 prompt="mininet>",
668 timeout=10 )
669 except pexpect.EOF:
670 main.log.error( self.name + ": EOF exception found" )
671 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700672 main.cleanup()
673 main.exit()
adminbae64d82013-08-01 10:50:15 -0700674
675 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800676 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800677 main.log.info(
678 self.name +
679 ": IP-Address of Host " +
680 host +
681 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800682 ipAddressSearch.group( 1 ) )
683 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800684 else:
685 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800686
Jon Hall7eb38402015-01-08 17:19:54 -0800687 def getSwitchDPID( self, switch ):
688 """
689 return the datapath ID of the switch"""
690 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700691 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700692 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800693 response = self.execute(
694 cmd=cmd,
695 prompt="mininet>",
696 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800697 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800698 main.log.error( self.name + ": EOF exception found" )
699 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700700 main.cleanup()
701 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800702 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800703 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700704 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800705 main.log.info(
706 "Couldn't find DPID for switch %s, found: %s" %
707 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700708 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800709 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700710 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800711 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700712
Jon Hall7eb38402015-01-08 17:19:54 -0800713 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700714 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800715 self.handle.sendline( "" )
716 self.expect( "mininet>" )
717 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700718 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800719 response = self.execute(
720 cmd=cmd,
721 prompt="mininet>",
722 timeout=10 )
723 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700724 response = self.handle.before
725 return response
726 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800727 main.log.error( self.name + ": EOF exception found" )
728 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700729 main.cleanup()
730 main.exit()
731
Jon Hall7eb38402015-01-08 17:19:54 -0800732 def getInterfaces( self, node ):
733 """
734 return information dict about interfaces connected to the node"""
735 if self.handle:
736 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800737 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700738 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700739 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800740 response = self.execute(
741 cmd=cmd,
742 prompt="mininet>",
743 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800744 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800745 main.log.error( self.name + ": EOF exception found" )
746 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700747 main.cleanup()
748 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700749 return response
750 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800751 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700752
Jon Hall7eb38402015-01-08 17:19:54 -0800753 def dump( self ):
754 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700755 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800756 response = self.execute(
757 cmd='dump',
758 prompt='mininet>',
759 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800760 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800761 main.log.error( self.name + ": EOF exception found" )
762 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700763 main.cleanup()
764 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700765 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800766
Jon Hall7eb38402015-01-08 17:19:54 -0800767 def intfs( self ):
768 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700769 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800770 response = self.execute(
771 cmd='intfs',
772 prompt='mininet>',
773 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800774 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800775 main.log.error( self.name + ": EOF exception found" )
776 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700777 main.cleanup()
778 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700779 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800780
Jon Hall7eb38402015-01-08 17:19:54 -0800781 def net( self ):
782 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700783 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800784 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800785 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800786 main.log.error( self.name + ": EOF exception found" )
787 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700788 main.cleanup()
789 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700790 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800791
792 def iperf( self, host1, host2 ):
793 main.log.info(
794 self.name +
795 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700796 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800797 cmd1 = 'iperf ' + host1 + " " + host2
798 self.handle.sendline( cmd1 )
799 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800800 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800801 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800802 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800803 return main.TRUE
804 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800805 main.log.error( self.name + ": iperf test failed" )
806 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800807 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800808 main.log.error( self.name + ": EOF exception found" )
809 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800810 main.cleanup()
811 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800812
Jon Hall7eb38402015-01-08 17:19:54 -0800813 def iperfudp( self ):
814 main.log.info(
815 self.name +
816 ": Simple iperf TCP test between two " +
817 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700818 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800819 response = self.execute(
820 cmd='iperfudp',
821 prompt='mininet>',
822 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800823 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800824 main.log.error( self.name + ": EOF exception found" )
825 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700826 main.cleanup()
827 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700828 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800829
Jon Hall7eb38402015-01-08 17:19:54 -0800830 def nodes( self ):
831 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700832 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800833 response = self.execute(
834 cmd='nodes',
835 prompt='mininet>',
836 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800837 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800838 main.log.error( self.name + ": EOF exception found" )
839 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700840 main.cleanup()
841 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700842 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800843
Jon Hall7eb38402015-01-08 17:19:54 -0800844 def pingpair( self ):
845 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700846 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800847 response = self.execute(
848 cmd='pingpair',
849 prompt='mininet>',
850 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800851 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800852 main.log.error( self.name + ": EOF exception found" )
853 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700854 main.cleanup()
855 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800856
Jon Hall7eb38402015-01-08 17:19:54 -0800857 if re.search( ',\s0\%\spacket\sloss', response ):
858 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800859 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700860 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800861 else:
862 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800863 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700864 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800865
Jon Hall7eb38402015-01-08 17:19:54 -0800866 def link( self, **linkargs ):
867 """
868 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800869 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800870 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
871 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
872 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
873 main.log.info(
874 "Bring link between '" +
875 end1 +
876 "' and '" +
877 end2 +
878 "' '" +
879 option +
880 "'" )
881 command = "link " + \
882 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -0700883 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800884 self.handle.sendline( command )
885 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800886 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800887 main.log.error( self.name + ": EOF exception found" )
888 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700889 main.cleanup()
890 main.exit()
adminbae64d82013-08-01 10:50:15 -0700891 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800892
Jon Hall7eb38402015-01-08 17:19:54 -0800893 def yank( self, **yankargs ):
894 """
895 yank a mininet switch interface to a host"""
896 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800897 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800898 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
899 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
900 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700901 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800902 response = self.execute(
903 cmd=command,
904 prompt="mininet>",
905 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800906 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800907 main.log.error( self.name + ": EOF exception found" )
908 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700909 main.cleanup()
910 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700911 return main.TRUE
912
Jon Hall7eb38402015-01-08 17:19:54 -0800913 def plug( self, **plugargs ):
914 """
915 plug the yanked mininet switch interface to a switch"""
916 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800917 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800918 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
919 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
920 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700921 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800922 response = self.execute(
923 cmd=command,
924 prompt="mininet>",
925 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800926 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800927 main.log.error( self.name + ": EOF exception found" )
928 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700929 main.cleanup()
930 main.exit()
adminbae64d82013-08-01 10:50:15 -0700931 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800932
Jon Hall7eb38402015-01-08 17:19:54 -0800933 def dpctl( self, **dpctlargs ):
934 """
935 Run dpctl command on all switches."""
936 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800937 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800938 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
939 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
940 command = "dpctl " + cmd + " " + str( cmdargs )
941 try:
942 response = self.execute(
943 cmd=command,
944 prompt="mininet>",
945 timeout=10 )
946 except pexpect.EOF:
947 main.log.error( self.name + ": EOF exception found" )
948 main.log.error( self.name + ": " + self.handle.before )
949 main.cleanup()
950 main.exit()
951 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800952
kelvin-onlabd3b64892015-01-20 13:26:24 -0800953 def getVersion( self ):
Jon Hallff6b4b22015-02-23 09:25:15 -0800954 #FIXME: What uses this? This should be refactored to get
955 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -0800956 fileInput = path + '/lib/Mininet/INSTALL'
957 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -0700958 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800959 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -0800960 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -0700961 if result:
Jon Hall7eb38402015-01-08 17:19:54 -0800962 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -0500963 return version
adminbae64d82013-08-01 10:50:15 -0700964
kelvin-onlabd3b64892015-01-20 13:26:24 -0800965 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -0800966 """
Jon Hallec3c21e2014-11-10 22:22:37 -0500967 Parameters:
968 sw: The name of an OVS switch. Example "s1"
969 Return:
Jon Hall7eb38402015-01-08 17:19:54 -0800970 The output of the command from the mininet cli
971 or main.FALSE on timeout"""
972 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -0700973 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800974 response = self.execute(
975 cmd=command,
976 prompt="mininet>",
977 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -0700978 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -0500979 return response
admin2a9548d2014-06-17 14:08:07 -0700980 else:
981 return main.FALSE
982 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800983 main.log.error( self.name + ": EOF exception found" )
984 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700985 main.cleanup()
986 main.exit()
adminbae64d82013-08-01 10:50:15 -0700987
kelvin-onlabd3b64892015-01-20 13:26:24 -0800988 def assignSwController( self, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -0800989 """
990 count is only needed if there is more than 1 controller"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800991 args = utilities.parse_args( [ "COUNT" ], **kwargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800992 count = args[ "COUNT" ] if args != {} else 1
Jon Hallf89c8552014-04-02 13:14:06 -0700993
994 argstring = "SW"
Jon Hall7eb38402015-01-08 17:19:54 -0800995 for j in range( count ):
996 argstring = argstring + ",IP" + \
997 str( j + 1 ) + ",PORT" + str( j + 1 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800998 args = utilities.parse_args( argstring.split( "," ), **kwargs )
Jon Hallf89c8552014-04-02 13:14:06 -0700999
Jon Hall7eb38402015-01-08 17:19:54 -08001000 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1001 ptcpA = int( args[ "PORT1" ] ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001002 int( sw ) if args[ "PORT1" ] is not None else ""
Jon Hall7eb38402015-01-08 17:19:54 -08001003 ptcpB = "ptcp:" + str( ptcpA ) if ptcpA != "" else ""
Jon Hallfbc828e2015-01-06 17:30:19 -08001004
Jon Hall7eb38402015-01-08 17:19:54 -08001005 command = "sh ovs-vsctl set-controller s" + \
1006 str( sw ) + " " + ptcpB + " "
1007 for j in range( count ):
1008 i = j + 1
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001009 args = utilities.parse_args(
Jon Hall7eb38402015-01-08 17:19:54 -08001010 [ "IP" + str( i ), "PORT" + str( i ) ], **kwargs )
1011 ip = args[
1012 "IP" +
1013 str( i ) ] if args[
1014 "IP" +
1015 str( i ) ] is not None else ""
1016 port = args[
1017 "PORT" +
1018 str( i ) ] if args[
1019 "PORT" +
1020 str( i ) ] is not None else ""
1021 tcp = "tcp:" + str( ip ) + ":" + str( port ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001022 " " if ip != "" else ""
Jon Hallf89c8552014-04-02 13:14:06 -07001023 command = command + tcp
Jon Hall6094a362014-04-11 14:46:56 -07001024 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001025 self.execute( cmd=command, prompt="mininet>", timeout=5 )
Jon Hall6094a362014-04-11 14:46:56 -07001026 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001027 main.log.error( self.name + ": EOF exception found" )
1028 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001029 main.cleanup()
1030 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001031 except Exception:
1032 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall6094a362014-04-11 14:46:56 -07001033 main.cleanup()
1034 main.exit()
adminbae64d82013-08-01 10:50:15 -07001035
kelvin-onlabd3b64892015-01-20 13:26:24 -08001036 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001037 """
1038 Removes the controller target from sw"""
1039 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001040 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001041 response = self.execute(
1042 cmd=command,
1043 prompt="mininet>",
1044 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001045 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001046 main.log.error( self.name + ": EOF exception found" )
1047 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001048 main.cleanup()
1049 main.exit()
1050 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001051 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001052
kelvin-onlabd3b64892015-01-20 13:26:24 -08001053 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001054 """
Jon Hallb1290e82014-11-18 16:17:48 -05001055 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001056 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001057 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001058 NOTE: cannot currently specify what type of switch
1059 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001060 sw = name of the new switch as a string
1061 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001062 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001063 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001064 """
1065 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001066 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001067 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001068 response = self.execute(
1069 cmd=command,
1070 prompt="mininet>",
1071 timeout=10 )
1072 if re.search( "already exists!", response ):
1073 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001074 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001075 elif re.search( "Error", response ):
1076 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001077 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001078 elif re.search( "usage:", response ):
1079 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001080 return main.FALSE
1081 else:
1082 return main.TRUE
1083 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001084 main.log.error( self.name + ": EOF exception found" )
1085 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001086 main.cleanup()
1087 main.exit()
1088
kelvin-onlabd3b64892015-01-20 13:26:24 -08001089 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001090 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001091 delete a switch from the mininet topology
1092 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001093 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001094 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001095 sw = name of the switch as a string
1096 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001097 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001098 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001099 response = self.execute(
1100 cmd=command,
1101 prompt="mininet>",
1102 timeout=10 )
1103 if re.search( "no switch named", response ):
1104 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001105 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001106 elif re.search( "Error", response ):
1107 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001108 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001109 elif re.search( "usage:", response ):
1110 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001111 return main.FALSE
1112 else:
1113 return main.TRUE
1114 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001115 main.log.error( self.name + ": EOF exception found" )
1116 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001117 main.cleanup()
1118 main.exit()
1119
kelvin-onlabd3b64892015-01-20 13:26:24 -08001120 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001121 """
1122 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001123 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001124 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001125 NOTE: cannot currently specify what type of link
1126 required params:
1127 node1 = the string node name of the first endpoint of the link
1128 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001129 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001130 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001131 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001132 response = self.execute(
1133 cmd=command,
1134 prompt="mininet>",
1135 timeout=10 )
1136 if re.search( "doesnt exist!", response ):
1137 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001138 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001139 elif re.search( "Error", response ):
1140 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001141 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001142 elif re.search( "usage:", response ):
1143 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001144 return main.FALSE
1145 else:
1146 return main.TRUE
1147 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001148 main.log.error( self.name + ": EOF exception found" )
1149 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001150 main.cleanup()
1151 main.exit()
1152
kelvin-onlabd3b64892015-01-20 13:26:24 -08001153 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001154 """
1155 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001156 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001157 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001158 required params:
1159 node1 = the string node name of the first endpoint of the link
1160 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001161 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001162 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001163 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001164 response = self.execute(
1165 cmd=command,
1166 prompt="mininet>",
1167 timeout=10 )
1168 if re.search( "no node named", response ):
1169 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001170 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001171 elif re.search( "Error", response ):
1172 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001173 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001174 elif re.search( "usage:", response ):
1175 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001176 return main.FALSE
1177 else:
1178 return main.TRUE
1179 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 main.log.error( self.name + ": EOF exception found" )
1181 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001182 main.cleanup()
1183 main.exit()
1184
kelvin-onlabd3b64892015-01-20 13:26:24 -08001185 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001186 """
Jon Hallb1290e82014-11-18 16:17:48 -05001187 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001188 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001189 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001190 NOTE: cannot currently specify what type of host
1191 required params:
1192 hostname = the string hostname
1193 optional key-value params
1194 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001195 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001196 """
1197 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001198 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001199 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001200 response = self.execute(
1201 cmd=command,
1202 prompt="mininet>",
1203 timeout=10 )
1204 if re.search( "already exists!", response ):
1205 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001206 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001207 elif re.search( "doesnt exists!", response ):
1208 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001209 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001210 elif re.search( "Error", response ):
1211 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001212 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001213 elif re.search( "usage:", response ):
1214 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001215 return main.FALSE
1216 else:
1217 return main.TRUE
1218 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001219 main.log.error( self.name + ": EOF exception found" )
1220 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001221 main.cleanup()
1222 main.exit()
1223
kelvin-onlabd3b64892015-01-20 13:26:24 -08001224 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001225 """
1226 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001227 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001228 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001229 NOTE: this uses a custom mn function
1230 required params:
1231 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001232 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001233 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001234 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001235 response = self.execute(
1236 cmd=command,
1237 prompt="mininet>",
1238 timeout=10 )
1239 if re.search( "no host named", response ):
1240 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001241 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001242 elif re.search( "Error", response ):
1243 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001244 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001245 elif re.search( "usage:", response ):
1246 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001247 return main.FALSE
1248 else:
1249 return main.TRUE
1250 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001251 main.log.error( self.name + ": EOF exception found" )
1252 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001253 main.cleanup()
1254 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001255
Jon Hall7eb38402015-01-08 17:19:54 -08001256 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001257 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001258 Called at the end of the test to stop the mininet and
1259 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001260 """
1261 self.handle.sendline('')
Jon Halld61331b2015-02-17 16:35:47 -08001262 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Hallefbd9792015-03-05 16:11:36 -08001263 timeout=2)
kelvin-onlaba1484582015-02-02 15:46:20 -08001264 if i == 0:
1265 self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001266 elif i == 1:
1267 return main.TRUE
1268 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001269 # print "Disconnecting Mininet"
1270 if self.handle:
1271 self.handle.sendline( "exit" )
1272 self.handle.expect( "exit" )
1273 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001274 else:
1275 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001276 return response
1277
Hari Krishnab35c6d02015-03-18 11:13:51 -07001278 def stopNet( self, fileName = "", timeout=5):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001279 """
Jon Hall21270ac2015-02-16 17:59:55 -08001280 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001281 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001282 main.FALSE if the pexpect handle does not exist.
1283
Jon Halld61331b2015-02-17 16:35:47 -08001284 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001285 """
Jon Hall21270ac2015-02-16 17:59:55 -08001286
Jon Halld61331b2015-02-17 16:35:47 -08001287 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001288 response = ''
1289 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001290 try:
kelvin-onlab26bc17f2015-02-06 14:08:59 -08001291 self.handle.sendline("")
kelvin-onlab56a3f462015-02-06 14:04:43 -08001292 i = self.handle.expect( [ 'mininet>',
1293 '\$',
1294 pexpect.EOF,
1295 pexpect.TIMEOUT ],
1296 timeout )
1297 if i == 0:
1298 main.log.info( "Exiting mininet..." )
1299
Jon Hall7eb38402015-01-08 17:19:54 -08001300 response = self.execute(
1301 cmd="exit",
1302 prompt="(.*)",
1303 timeout=120 )
Jon Halld61331b2015-02-17 16:35:47 -08001304 main.log.info( self.name + ": Stopped")
Jon Hall7eb38402015-01-08 17:19:54 -08001305 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001306 response = main.TRUE
Hari Krishnab35c6d02015-03-18 11:13:51 -07001307
kelvin-onlab56a3f462015-02-06 14:04:43 -08001308 if i == 1:
1309 main.log.info( " Mininet trying to exit while not " +
1310 "in the mininet prompt" )
1311 elif i == 2:
1312 main.log.error( "Something went wrong exiting mininet" )
1313 elif i == 3: # timeout
1314 main.log.error( "Something went wrong exiting mininet " +
1315 "TIMEOUT" )
1316
Hari Krishnab35c6d02015-03-18 11:13:51 -07001317 if fileName:
1318 self.handle.sendline("")
1319 self.handle.expect('\$')
1320 self.handle.sendline("sudo kill -9 \`ps -ef | grep \""+ fileName +"\" | grep -v grep | awk '{print $2}'\`")
Jon Hallfbc828e2015-01-06 17:30:19 -08001321 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001322 main.log.error( self.name + ": EOF exception found" )
1323 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001324 main.cleanup()
1325 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001326 else:
1327 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001328 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001329 return response
1330
Jon Hall7eb38402015-01-08 17:19:54 -08001331 def arping( self, src, dest, destmac ):
1332 self.handle.sendline( '' )
1333 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001334
Jon Hall7eb38402015-01-08 17:19:54 -08001335 self.handle.sendline( src + ' arping ' + dest )
admin07529932013-11-22 14:58:28 -08001336 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001337 self.handle.expect( [ destmac, pexpect.EOF, pexpect.TIMEOUT ] )
1338 main.log.info( self.name + ": ARP successful" )
1339 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001340 return main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -08001341 except Exception:
Jon Hall7eb38402015-01-08 17:19:54 -08001342 main.log.warn( self.name + ": ARP FAILURE" )
1343 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001344 return main.FALSE
1345
Jon Hall7eb38402015-01-08 17:19:54 -08001346 def decToHex( self, num ):
1347 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001348
Jon Hall7eb38402015-01-08 17:19:54 -08001349 def getSwitchFlowCount( self, switch ):
1350 """
1351 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001352 if self.handle:
1353 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1354 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001355 response = self.execute(
1356 cmd=cmd,
1357 prompt="mininet>",
1358 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001359 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001360 main.log.error( self.name + ": EOF exception found" )
1361 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001362 main.cleanup()
1363 main.exit()
1364 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001365 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001366 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001367 main.log.info(
1368 "Couldn't find flows on switch %s, found: %s" %
1369 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001370 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001371 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001372 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001373 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001374
kelvin-onlabd3b64892015-01-20 13:26:24 -08001375 def checkFlows( self, sw, dumpFormat=None ):
1376 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001377 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001378 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001379 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001380 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001381 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001382 response = self.execute(
1383 cmd=command,
1384 prompt="mininet>",
1385 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001386 return response
1387 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001388 main.log.error( self.name + ": EOF exception found" )
1389 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001390 main.cleanup()
1391 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001392
kelvin-onlabd3b64892015-01-20 13:26:24 -08001393 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001394 """
Jon Hallefbd9792015-03-05 16:11:36 -08001395 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001396 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001397 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001398 self.handle.sendline( "" )
1399 self.handle.expect( "mininet>" )
1400 self.handle.sendline(
1401 "sh sudo tcpdump -n -i " +
1402 intf +
1403 " " +
1404 port +
1405 " -w " +
1406 filename.strip() +
1407 " &" )
1408 self.handle.sendline( "" )
1409 i = self.handle.expect( [ 'No\ssuch\device',
1410 'listening\son',
1411 pexpect.TIMEOUT,
1412 "mininet>" ],
1413 timeout=10 )
1414 main.log.warn( self.handle.before + self.handle.after )
1415 self.handle.sendline( "" )
1416 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001417 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001418 main.log.error(
1419 self.name +
1420 ": tcpdump - No such device exists. " +
1421 "tcpdump attempted on: " +
1422 intf )
admin2a9548d2014-06-17 14:08:07 -07001423 return main.FALSE
1424 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001425 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001426 return main.TRUE
1427 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001428 main.log.error(
1429 self.name +
1430 ": tcpdump command timed out! Check interface name," +
1431 " given interface was: " +
1432 intf )
admin2a9548d2014-06-17 14:08:07 -07001433 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001434 elif i == 3:
1435 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001436 return main.TRUE
1437 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001438 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001439 return main.FALSE
1440 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001441 main.log.error( self.name + ": EOF exception found" )
1442 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001443 main.cleanup()
1444 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001445 except Exception:
1446 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001447 main.cleanup()
1448 main.exit()
1449
kelvin-onlabd3b64892015-01-20 13:26:24 -08001450 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001451 """
1452 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001453 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001454 self.handle.sendline( "sh sudo pkill tcpdump" )
1455 self.handle.expect( "mininet>" )
1456 self.handle.sendline( "" )
1457 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001458 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001459 main.log.error( self.name + ": EOF exception found" )
1460 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001461 main.cleanup()
1462 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001463 except Exception:
1464 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001465 main.cleanup()
1466 main.exit()
1467
kelvin-onlabd3b64892015-01-20 13:26:24 -08001468 def compareSwitches( self, topo, switchesJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001469 """
1470 Compare mn and onos switches
1471 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001472 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001473
Jon Hall7eb38402015-01-08 17:19:54 -08001474 This uses the sts TestONTopology object"""
kelvin-onlabd3b64892015-01-20 13:26:24 -08001475 # main.log.debug( "Switches_json string: ", switchesJson )
Jon Hall7eb38402015-01-08 17:19:54 -08001476 output = { "switches": [] }
1477 # iterate through the MN topology and pull out switches and and port
1478 # info
1479 for switch in topo.graph.switches:
Jon Hall3d87d502014-10-17 18:37:42 -04001480 ports = []
1481 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001482 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001483 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001484 'name': port.name } )
1485 output[ 'switches' ].append( {
1486 "name": switch.name,
1487 "dpid": str( switch.dpid ).zfill( 16 ),
1488 "ports": ports } )
Jon Hall3d87d502014-10-17 18:37:42 -04001489
Jon Hall7eb38402015-01-08 17:19:54 -08001490 # print "mn"
1491 # print json.dumps( output,
Jon Hallff6b4b22015-02-23 09:25:15 -08001492 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001493 # indent=4,
1494 # separators=( ',', ': ' ) )
1495 # print "onos"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001496 # print json.dumps( switchesJson,
Jon Hallff6b4b22015-02-23 09:25:15 -08001497 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001498 # indent=4,
1499 # separators=( ',', ': ' ) )
Jon Hall3d87d502014-10-17 18:37:42 -04001500
1501 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001502 mnDPIDs = []
1503 for switch in output[ 'switches' ]:
1504 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001505 mnDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001506 # print "List of Mininet switch DPID's"
1507 # print mnDPIDs
kelvin-onlabd3b64892015-01-20 13:26:24 -08001508 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001509 main.log.error(
1510 self.name +
1511 ".compare_switches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001512 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001513 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001514 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001515 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001516 if switch[ 'available' ]:
1517 onosDPIDs.append(
1518 switch[ 'id' ].replace(
1519 ":",
1520 '' ).replace(
1521 "of",
1522 '' ).lower() )
1523 # else:
1524 # print "Switch is unavailable:"
1525 # print switch
Jon Hall3d87d502014-10-17 18:37:42 -04001526 onosDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001527 # print "List of ONOS switch DPID's"
1528 # print onosDPIDs
Jon Hall3d87d502014-10-17 18:37:42 -04001529
Jon Hall7eb38402015-01-08 17:19:54 -08001530 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001531 switchResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001532 main.log.report( "Switches in MN but not in ONOS:" )
1533 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
1534 main.log.report( str( list1 ) )
1535 main.log.report( "Switches in ONOS but not in MN:" )
1536 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
kelvin-onlabedcff052015-01-16 12:53:55 -08001537 main.log.report( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001538 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001539 switchResults = main.TRUE
1540 return switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001541
kelvin-onlabd3b64892015-01-20 13:26:24 -08001542 def comparePorts( self, topo, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001543 """
Jon Hall72cf1dc2014-10-20 21:04:50 -04001544 Compare mn and onos ports
1545 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001546 portsJson: parsed json object from the onos ports api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001547
Jon Hallfbc828e2015-01-06 17:30:19 -08001548 Dependencies:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001549 1. This uses the sts TestONTopology object
1550 2. numpy - "sudo pip install numpy"
1551
Jon Hall7eb38402015-01-08 17:19:54 -08001552 """
1553 # FIXME: this does not look for extra ports in ONOS, only checks that
1554 # ONOS has what is in MN
Jon Hall72cf1dc2014-10-20 21:04:50 -04001555 from numpy import uint64
kelvin-onlabd3b64892015-01-20 13:26:24 -08001556 portsResults = main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001557 output = { "switches": [] }
1558 # iterate through the MN topology and pull out switches and and port
1559 # info
1560 for switch in topo.graph.switches:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001561 ports = []
1562 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001563 # print port.hw_addr.toStr( separator='' )
Jon Hallefbd9792015-03-05 16:11:36 -08001564 tmpPort = { 'of_port': port.port_no,
1565 'mac': str( port.hw_addr ).replace( '\'', '' ),
1566 'name': port.name,
1567 'enabled': port.enabled }
Jon Hall39f29df2014-11-04 19:30:21 -05001568
kelvin-onlabd3b64892015-01-20 13:26:24 -08001569 ports.append( tmpPort )
Jon Hallefbd9792015-03-05 16:11:36 -08001570 tmpSwitch = { 'name': switch.name,
1571 'dpid': str( switch.dpid ).zfill( 16 ),
1572 'ports': ports }
Jon Hall39f29df2014-11-04 19:30:21 -05001573
kelvin-onlabd3b64892015-01-20 13:26:24 -08001574 output[ 'switches' ].append( tmpSwitch )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001575
Jon Hall7eb38402015-01-08 17:19:54 -08001576 # PORTS
kelvin-onlabd3b64892015-01-20 13:26:24 -08001577 for mnSwitch in output[ 'switches' ]:
1578 mnPorts = []
1579 onosPorts = []
1580 switchResult = main.TRUE
1581 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001582 if port[ 'enabled' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001583 mnPorts.append( port[ 'of_port' ] )
1584 for onosSwitch in portsJson:
Jon Hall7eb38402015-01-08 17:19:54 -08001585 # print "Iterating through a new switch as seen by ONOS"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001586 # print onosSwitch
1587 if onosSwitch[ 'device' ][ 'available' ]:
1588 if onosSwitch[ 'device' ][ 'id' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001589 ':',
1590 '' ).replace(
1591 "of",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001592 '' ) == mnSwitch[ 'dpid' ]:
1593 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001594 if port[ 'isEnabled' ]:
1595 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001596 # onosPorts.append( 'local' )
1597 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001598 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001599 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001600 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001601 mnPorts.sort( key=float )
1602 onosPorts.sort( key=float )
1603 # print "\nPorts for Switch %s:" % ( mnSwitch[ 'name' ] )
1604 # print "\tmn_ports[] = ", mnPorts
1605 # print "\tonos_ports[] = ", onosPorts
1606 mnPortsLog = mnPorts
1607 onosPortsLog = onosPorts
1608 mnPorts = [ x for x in mnPorts ]
1609 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001610
Jon Hall7eb38402015-01-08 17:19:54 -08001611 # TODO: handle other reserved port numbers besides LOCAL
1612 # NOTE: Reserved ports
1613 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1614 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001615 for mnPort in mnPortsLog:
1616 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001617 # don't set results to true here as this is just one of
1618 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001619 mnPorts.remove( mnPort )
1620 onosPorts.remove( mnPort )
Jon Hall7eb38402015-01-08 17:19:54 -08001621 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001622 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001623 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001624 if 65534 in mnPorts:
1625 mnPorts.remove( 65534 )
1626 if long( uint64( -2 ) ) in onosPorts:
1627 onosPorts.remove( long( uint64( -2 ) ) )
1628 if len( mnPorts ): # the ports of this switch don't match
1629 switchResult = main.FALSE
1630 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1631 if len( onosPorts ): # the ports of this switch don't match
1632 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001633 main.log.warn(
1634 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001635 str( onosPorts ) )
1636 if switchResult == main.FALSE:
Jon Hall7eb38402015-01-08 17:19:54 -08001637 main.log.report(
1638 "The list of ports for switch %s(%s) does not match:" %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001639 ( mnSwitch[ 'name' ], mnSwitch[ 'dpid' ] ) )
1640 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1641 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1642 portsResults = portsResults and switchResult
1643 return portsResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001644
kelvin-onlabd3b64892015-01-20 13:26:24 -08001645 def compareLinks( self, topo, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001646 """
1647 Compare mn and onos links
1648 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001649 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001650
Jon Hall7eb38402015-01-08 17:19:54 -08001651 This uses the sts TestONTopology object"""
1652 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08001653 # ONOS has what is in MN
Jon Hall7eb38402015-01-08 17:19:54 -08001654 output = { "switches": [] }
kelvin-onlabd3b64892015-01-20 13:26:24 -08001655 onos = linksJson
Jon Hall7eb38402015-01-08 17:19:54 -08001656 # iterate through the MN topology and pull out switches and and port
1657 # info
1658 for switch in topo.graph.switches:
Jon Hall38481722014-11-04 16:50:05 -05001659 # print "Iterating though switches as seen by Mininet"
1660 # print switch
Jon Hall72cf1dc2014-10-20 21:04:50 -04001661 ports = []
1662 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001663 # print port.hw_addr.toStr( separator='' )
1664 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001665 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001666 'name': port.name } )
1667 output[ 'switches' ].append( {
1668 "name": switch.name,
1669 "dpid": str( switch.dpid ).zfill( 16 ),
1670 "ports": ports } )
1671 # LINKS
Jon Hall72cf1dc2014-10-20 21:04:50 -04001672
kelvin-onlabd3b64892015-01-20 13:26:24 -08001673 mnLinks = [
kelvin-onlab9592d132015-01-20 17:18:02 -08001674 link for link in topo.patch_panel.network_links if (
Jon Hall7eb38402015-01-08 17:19:54 -08001675 link.port1.enabled and link.port2.enabled ) ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08001676 if 2 * len( mnLinks ) == len( onos ):
1677 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001678 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001679 linkResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001680 main.log.report(
Jon Hall328ddca2015-01-28 15:57:15 -08001681 "Mininet has " + str( len( mnLinks ) ) +
1682 " bidirectional links and ONOS has " +
1683 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001684
Jon Hall7eb38402015-01-08 17:19:54 -08001685 # iterate through MN links and check if an ONOS link exists in
1686 # both directions
1687 # NOTE: Will currently only show mn links as down if they are
1688 # cut through STS. We can either do everything through STS or
kelvin-onlabd3b64892015-01-20 13:26:24 -08001689 # wait for upNetworkLinks and downNetworkLinks to be
Jon Hall7eb38402015-01-08 17:19:54 -08001690 # fully implemented.
kelvin-onlabd3b64892015-01-20 13:26:24 -08001691 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08001692 # print "Link: %s" % link
1693 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04001694 node1 = None
1695 port1 = None
1696 node2 = None
1697 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08001698 firstDir = main.FALSE
1699 secondDir = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001700 for switch in output[ 'switches' ]:
1701 # print "Switch: %s" % switch[ 'name' ]
1702 if switch[ 'name' ] == link.node1.name:
1703 node1 = switch[ 'dpid' ]
1704 for port in switch[ 'ports' ]:
1705 if str( port[ 'name' ] ) == str( link.port1 ):
1706 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001707 if node1 is not None and node2 is not None:
1708 break
Jon Hall7eb38402015-01-08 17:19:54 -08001709 if switch[ 'name' ] == link.node2.name:
1710 node2 = switch[ 'dpid' ]
1711 for port in switch[ 'ports' ]:
1712 if str( port[ 'name' ] ) == str( link.port2 ):
1713 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001714 if node1 is not None and node2 is not None:
1715 break
1716
kelvin-onlabd3b64892015-01-20 13:26:24 -08001717 for onosLink in onos:
1718 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001719 ":",
1720 '' ).replace(
1721 "of",
1722 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001723 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001724 ":",
1725 '' ).replace(
1726 "of",
1727 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001728 onosPort1 = onosLink[ 'src' ][ 'port' ]
1729 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001730
Jon Hall72cf1dc2014-10-20 21:04:50 -04001731 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08001732 if str( onosNode1 ) == str( node1 ) and str(
1733 onosNode2 ) == str( node2 ):
1734 if int( onosPort1 ) == int( port1 ) and int(
1735 onosPort2 ) == int( port2 ):
1736 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001737 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001738 main.log.warn(
1739 'The port numbers do not match for ' +
1740 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001741 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001742 'link %s/%s -> %s/%s' %
1743 ( node1,
1744 port1,
1745 node2,
1746 port2 ) +
1747 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001748 ( onosNode1,
1749 onosPort1,
1750 onosNode2,
1751 onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001752
1753 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08001754 elif ( str( onosNode1 ) == str( node2 ) and
1755 str( onosNode2 ) == str( node1 ) ):
1756 if ( int( onosPort1 ) == int( port2 )
1757 and int( onosPort2 ) == int( port1 ) ):
1758 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001759 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001760 main.log.warn(
1761 'The port numbers do not match for ' +
1762 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001763 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001764 'link %s/%s -> %s/%s' %
1765 ( node2,
1766 port2,
1767 node1,
1768 port1 ) +
1769 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001770 ( onosNode2,
1771 onosPort2,
1772 onosNode1,
1773 onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001774 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04001775 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08001776 if not firstDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001777 main.log.report(
1778 'ONOS does not have the link %s/%s -> %s/%s' %
1779 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001780 if not secondDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001781 main.log.report(
1782 'ONOS does not have the link %s/%s -> %s/%s' %
1783 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001784 linkResults = linkResults and firstDir and secondDir
1785 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001786
Jon Hallff6b4b22015-02-23 09:25:15 -08001787 def compareHosts( self, topo, hostsJson ):
1788 """
1789 Compare mn and onos Hosts.
1790 Since Mininet hosts are quiet, ONOS will only know of them when they
1791 speak. For this reason, we will only check that the hosts in ONOS
1792 stores are in Mininet, and not vice versa.
1793 topo: sts TestONTopology object
1794 hostsJson: parsed json object from the onos hosts api
1795
1796 This uses the sts TestONTopology object"""
1797 import json
1798 hostResults = main.TRUE
1799 hosts = []
1800 # iterate through the MN topology and pull out hosts
1801 for mnHost in topo.graph.hosts:
1802 interfaces = []
1803 for intf in mnHost.interfaces:
1804 interfaces.append( {
1805 "name": intf.name, # str
1806 "ips": [ str( ip ) for ip in intf.ips ], # list of IPAddrs
1807 # hw_addr is of type EthAddr, Not JSON serializable
1808 "hw_addr": str( intf.hw_addr ) } )
1809 hosts.append( {
1810 "name": mnHost.name, # str
1811 "interfaces": interfaces } ) # list
1812 for onosHost in hostsJson:
1813 onosMAC = onosHost[ 'mac' ].lower()
1814 match = False
1815 for mnHost in hosts:
1816 for mnIntf in mnHost[ 'interfaces' ]:
1817 if onosMAC == mnIntf[ 'hw_addr' ].lower() :
1818 match = True
1819 for ip in mnIntf[ 'ips' ]:
1820 if ip in onosHost[ 'ips' ]:
1821 pass # all is well
1822 else:
1823 # misssing ip
1824 main.log.error( "ONOS host " + onosHost[ 'id' ]
1825 + " has a different IP than " +
1826 "the Mininet host." )
1827 output = json.dumps(
1828 onosHost,
1829 sort_keys=True,
1830 indent=4,
1831 separators=( ',', ': ' ) )
1832 main.log.info( output )
1833 hostResults = main.FALSE
1834 if not match:
1835 hostResults = main.FALSE
1836 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
1837 "corresponding Mininet host." )
1838 output = json.dumps( onosHost,
1839 sort_keys=True,
1840 indent=4,
1841 separators=( ',', ': ' ) )
1842 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08001843 return hostResults
1844
kelvin-onlabd3b64892015-01-20 13:26:24 -08001845 def getHosts( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08001846 """
1847 Returns a list of all hosts
1848 Don't ask questions just use it"""
1849 self.handle.sendline( "" )
1850 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001851
Jon Hall7eb38402015-01-08 17:19:54 -08001852 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
1853 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001854
kelvin-onlabd3b64892015-01-20 13:26:24 -08001855 handlePy = self.handle.before
1856 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
1857 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07001858
Jon Hall7eb38402015-01-08 17:19:54 -08001859 self.handle.sendline( "" )
1860 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001861
kelvin-onlabd3b64892015-01-20 13:26:24 -08001862 hostStr = handlePy.replace( "]", "" )
1863 hostStr = hostStr.replace( "'", "" )
1864 hostStr = hostStr.replace( "[", "" )
1865 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001866
kelvin-onlabd3b64892015-01-20 13:26:24 -08001867 return hostList
adminbae64d82013-08-01 10:50:15 -07001868
Jon Hall7eb38402015-01-08 17:19:54 -08001869 def update( self ):
1870 """
1871 updates the port address and status information for
1872 each port in mn"""
1873 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08001874 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05001875 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001876 self.handle.sendline( "" )
1877 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001878
Jon Hall7eb38402015-01-08 17:19:54 -08001879 self.handle.sendline( "update" )
1880 self.handle.expect( "update" )
1881 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001882
Jon Hall7eb38402015-01-08 17:19:54 -08001883 self.handle.sendline( "" )
1884 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001885
Jon Hallb1290e82014-11-18 16:17:48 -05001886 return main.TRUE
1887 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001888 main.log.error( self.name + ": EOF exception found" )
1889 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001890 main.cleanup()
1891 main.exit()
1892
adminbae64d82013-08-01 10:50:15 -07001893if __name__ != "__main__":
1894 import sys
Jon Hall7eb38402015-01-08 17:19:54 -08001895 sys.modules[ __name__ ] = MininetCliDriver()