blob: 93365909b5aa41bf3322cba30af941c660147bc1 [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
kelvin-onlab50907142015-04-01 13:37:45 -070046class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080047
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(
kelvin-onlab50907142015-04-01 13:37:45 -070068 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080069 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
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700251 def pingall( self, timeout=300, shortCircuit = False ,numFailedPings = 1):
Jon Hall7eb38402015-01-08 17:19:54 -0800252 """
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
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700256 Optional:
257 shortCircuit - Break the pingall based on the number of failed hosts
258 ping
259 numFailedPings - initialized the number required for the pingall to
260 break defaults to 1
Jon Hall7eb38402015-01-08 17:19:54 -0800261 Returns:
262 main.TRUE if pingall completes with no pings dropped
263 otherwise main.FALSE"""
264 if self.handle:
265 main.log.info(
266 self.name +
267 ": Checking reachabilty to the hosts using pingall" )
Jon Hall6094a362014-04-11 14:46:56 -0700268 try:
kelvin-onlabb9408212015-04-01 13:34:04 -0700269 if not shortCircuit:
270 response = self.execute(
271 cmd="pingall",
272 prompt="mininet>",
273 timeout=int( timeout ) )
274 else:
275 self.handle.sendline( "pingall" )
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700276 i = self.handle.expect( [ "mininet>","X",
kelvin-onlabb9408212015-04-01 13:34:04 -0700277 pexpect.EOF,
278 pexpect.TIMEOUT ],
279 timeout )
280 if i == 0:
kelvin-onlab38143812015-04-01 15:03:01 -0700281 main.log.info( "mininet> prompt found!" )
282 response = str( self.handle.before )
kelvin-onlabb9408212015-04-01 13:34:04 -0700283 if i == 1:
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700284 main.log.info( self.name +
285 ": Cannot ping some of the hosts")
286 failedPings = 1
287 main.log.info( self.name + ": failed to ping " +
288 str( failedPings ) + " host" )
289 while failedPings != numFailedPings:
290 j = self.handle.expect( [ "mininet>","X",
291 pexpect.EOF,
292 pexpect.TIMEOUT ],
293 timeout )
294 if j == 0:
295 main.log.info( self.name + ": pingall finished")
296 break
297 if j == 1:
298 failedPings = failedPings + 1
299 main.log.info( self.name + ": failed to ping "
300 + str( failedPings ) + " host" )
301
302 if j == 2:
303 main.log.error( self.name +
304 ": EOF exception found" )
305 main.log.error( self.name + ": " +
306 self.handle.before )
307 main.cleanup()
308 main.exit()
309 if j == 3:
310 main.log.error( self.name +
311 ": TIMEOUT exception found" )
312 main.log.error( self.name +
313 ": " +
314 str( self.handle.before ) )
315 break
316
317 main.log.info( self.name + ": Cannot ping "
318 + str( failedPings ) +" hosts")
kelvin-onlab38143812015-04-01 15:03:01 -0700319 main.log.info( str( self.handle.before ) )
320 response = str( self.handle.before )
kelvin-onlabb9408212015-04-01 13:34:04 -0700321 if i == 2:
322 main.log.error( self.name + ": EOF exception found" )
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700323 main.log.error( self.name + ": "
324 + self.handle.before )
kelvin-onlabb9408212015-04-01 13:34:04 -0700325 main.cleanup()
326 main.exit()
327 if i == 3:
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700328 main.log.error( self.name +
329 ": TIMEOUT exception found" )
kelvin-onlabb9408212015-04-01 13:34:04 -0700330 main.log.error( self.name +
331 ": " +
332 str( self.handle.before ) )
333
Jon Hallb1290e82014-11-18 16:17:48 -0500334 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800335 main.log.error( self.name + ": EOF exception found" )
336 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500337 main.cleanup()
338 main.exit()
339 except pexpect.TIMEOUT:
Jon Hall7eb38402015-01-08 17:19:54 -0800340 # We may not want to kill the test if pexpect times out
341 main.log.error( self.name + ": TIMEOUT exception found" )
342 main.log.error( self.name +
343 ": " +
344 str( self.handle.before ) )
345 # NOTE: mininet's pingall rounds, so we will check the number of
346 # passed and number of failed
347 pattern = "Results\:\s0\%\sdropped\s\(" +\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800348 "(?P<passed>[\d]+)/(?P=passed)"
Jon Hall7eb38402015-01-08 17:19:54 -0800349 if re.search( pattern, response ):
350 main.log.info( self.name + ": All hosts are reachable" )
adminbae64d82013-08-01 10:50:15 -0700351 return main.TRUE
352 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800353 main.log.error( self.name + ": Unable to reach all the hosts" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800354 main.log.info( "Pingall output: " + str( response ) )
Jon Hall7eb38402015-01-08 17:19:54 -0800355 # NOTE: Send ctrl-c to make sure pingall is done
356 self.handle.send( "\x03" )
357 self.handle.expect( "Interrupt" )
358 self.handle.expect( "mininet>" )
adminbae64d82013-08-01 10:50:15 -0700359 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800360 else:
361 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallb1290e82014-11-18 16:17:48 -0500362 main.cleanup()
363 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700364
Jon Hall7eb38402015-01-08 17:19:54 -0800365 def fpingHost( self, **pingParams ):
366 """
367 Uses the fping package for faster pinging...
368 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800369 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800370 command = args[ "SRC" ] + \
371 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
372 self.handle.sendline( command )
373 self.handle.expect(
374 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
375 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
376 response = self.handle.before
377 if re.search( ":\s-", response ):
378 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700379 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800380 elif re.search( ":\s\d{1,2}\.\d\d", response ):
381 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700382 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800383 main.log.info( self.name + ": Install fping on mininet machine... " )
384 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700385 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800386
Jon Hall7eb38402015-01-08 17:19:54 -0800387 def pingHost( self, **pingParams ):
388 """
389 Ping from one mininet host to another
390 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800391 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800392 command = args[ "SRC" ] + " ping " + \
393 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700394 try:
Jon Hall61282e32015-03-19 11:34:11 -0700395 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800396 self.handle.sendline( command )
397 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700398 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800399 main.log.error(
400 self.name +
401 ": timeout when waiting for response from mininet" )
402 main.log.error( "response: " + str( self.handle.before ) )
403 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700404 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800405 main.log.error(
406 self.name +
407 ": timeout when waiting for response from mininet" )
408 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700409 response = self.handle.before
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()
Jon Hall7eb38402015-01-08 17:19:54 -0800415 main.log.info( self.name + ": Ping Response: " + response )
416 if re.search( ',\s0\%\spacket\sloss', response ):
417 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800418 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700419 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800420 else:
421 main.log.error(
422 self.name +
423 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800424 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700425 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800426
Jon Hall7eb38402015-01-08 17:19:54 -0800427 def checkIP( self, host ):
428 """
429 Verifies the host's ip configured or not."""
430 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700431 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800432 response = self.execute(
433 cmd=host +
434 " ifconfig",
435 prompt="mininet>",
436 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800437 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800438 main.log.error( self.name + ": EOF exception found" )
439 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700440 main.cleanup()
441 main.exit()
adminbae64d82013-08-01 10:50:15 -0700442
Jon Hall7eb38402015-01-08 17:19:54 -0800443 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800444 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
445 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
446 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
447 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
448 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800449 # pattern = "inet addr:10.0.0.6"
450 if re.search( pattern, response ):
451 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700452 return main.TRUE
453 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800454 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700455 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800456 else:
457 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800458
Jon Hall7eb38402015-01-08 17:19:54 -0800459 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800460 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700461 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800462 response = self.execute(
463 cmd="h1 /usr/sbin/sshd -D&",
464 prompt="mininet>",
465 timeout=10 )
466 response = self.execute(
467 cmd="h4 /usr/sbin/sshd -D&",
468 prompt="mininet>",
469 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700470 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800471 vars( self )[ key ] = connectargs[ key ]
472 response = self.execute(
473 cmd="xterm h1 h4 ",
474 prompt="mininet>",
475 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800476 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800477 main.log.error( self.name + ": EOF exception found" )
478 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700479 main.cleanup()
480 main.exit()
adminbae64d82013-08-01 10:50:15 -0700481 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800482 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700483 if self.flag == 0:
484 self.flag = 1
485 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800486 else:
adminbae64d82013-08-01 10:50:15 -0700487 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800488
kelvin-onlaba1484582015-02-02 15:46:20 -0800489 def moveHost( self, host, oldSw, newSw, ):
490 """
491 Moves a host from one switch to another on the fly
492 Note: The intf between host and oldSw when detached
493 using detach(), will still show up in the 'net'
494 cmd, because switch.detach() doesn't affect switch.intfs[]
495 (which is correct behavior since the interfaces
496 haven't moved).
497 """
498 if self.handle:
499 try:
500 # Bring link between oldSw-host down
Jon Hallefbd9792015-03-05 16:11:36 -0800501 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'"+ host +\
502 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800503 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800504 response = self.execute( cmd=cmd,
505 prompt="mininet>",
506 timeout=10 )
kelvin-onlaba1484582015-02-02 15:46:20 -0800507
508 # Determine hostintf and Oldswitchintf
509 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800510 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800511 print "cmd2= ", cmd
512 self.handle.sendline( cmd )
513 self.handle.expect( "mininet>" )
514
shahshreya73537862015-02-11 15:15:24 -0800515 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800516 cmd = "px ipaddr = hintf.IP()"
517 print "cmd3= ", cmd
518 self.handle.sendline( cmd )
519 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800520
521 cmd = "px macaddr = hintf.MAC()"
522 print "cmd3= ", cmd
523 self.handle.sendline( cmd )
524 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800525
526 # Detach interface between oldSw-host
527 cmd = "px " + oldSw + ".detach( sintf )"
528 print "cmd4= ", cmd
529 self.handle.sendline( cmd )
530 self.handle.expect( "mininet>" )
531
532 # Add link between host-newSw
533 cmd = "py net.addLink(" + host + "," + newSw + ")"
534 print "cmd5= ", cmd
535 self.handle.sendline( cmd )
536 self.handle.expect( "mininet>" )
537
538 # Determine hostintf and Newswitchintf
539 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800540 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800541 print "cmd6= ", cmd
542 self.handle.sendline( cmd )
543 self.handle.expect( "mininet>" )
544
545 # Attach interface between newSw-host
546 cmd = "px " + newSw + ".attach( sintf )"
547 print "cmd3= ", cmd
548 self.handle.sendline( cmd )
549 self.handle.expect( "mininet>" )
550
551 # Set ipaddress of the host-newSw interface
552 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
553 print "cmd7 = ", cmd
554 self.handle.sendline( cmd )
555 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800556
557 # Set macaddress of the host-newSw interface
558 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
559 print "cmd8 = ", cmd
560 self.handle.sendline( cmd )
561 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800562
563 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800564 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800565 self.handle.sendline( cmd )
566 self.handle.expect( "mininet>" )
567 print "output = ", self.handle.before
568
569 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800570 cmd = host + " ifconfig"
571 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800572 self.handle.sendline( cmd )
573 self.handle.expect( "mininet>" )
574 print "ifconfig o/p = ", self.handle.before
575
576 return main.TRUE
577 except pexpect.EOF:
578 main.log.error( self.name + ": EOF exception found" )
579 main.log.error( self.name + ": " + self.handle.before )
580 return main.FALSE
581
Jon Hall7eb38402015-01-08 17:19:54 -0800582 def changeIP( self, host, intf, newIP, newNetmask ):
583 """
584 Changes the ip address of a host on the fly
585 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800586 if self.handle:
587 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800588 cmd = host + " ifconfig " + intf + " " + \
589 newIP + " " + 'netmask' + " " + newNetmask
590 self.handle.sendline( cmd )
591 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800592 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800593 main.log.info( "response = " + response )
594 main.log.info(
595 "Ip of host " +
596 host +
597 " changed to new IP " +
598 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800599 return main.TRUE
600 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800601 main.log.error( self.name + ": EOF exception found" )
602 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800603 return main.FALSE
604
Jon Hall7eb38402015-01-08 17:19:54 -0800605 def changeDefaultGateway( self, host, newGW ):
606 """
607 Changes the default gateway of a host
608 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800609 if self.handle:
610 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800611 cmd = host + " route add default gw " + newGW
612 self.handle.sendline( cmd )
613 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800614 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800615 main.log.info( "response = " + response )
616 main.log.info(
617 "Default gateway of host " +
618 host +
619 " changed to " +
620 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800621 return main.TRUE
622 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800623 main.log.error( self.name + ": EOF exception found" )
624 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800625 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800626
Jon Hall7eb38402015-01-08 17:19:54 -0800627 def addStaticMACAddress( self, host, GW, macaddr ):
628 """
Jon Hallefbd9792015-03-05 16:11:36 -0800629 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800630 if self.handle:
631 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800632 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
633 cmd = host + " arp -s " + GW + " " + macaddr
634 self.handle.sendline( cmd )
635 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800636 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800637 main.log.info( "response = " + response )
638 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800639 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800640 GW +
641 " changed to " +
642 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800643 return main.TRUE
644 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800645 main.log.error( self.name + ": EOF exception found" )
646 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800647 return main.FALSE
648
Jon Hall7eb38402015-01-08 17:19:54 -0800649 def verifyStaticGWandMAC( self, host ):
650 """
651 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800652 if self.handle:
653 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800654 # h1 arp -an
655 cmd = host + " arp -an "
656 self.handle.sendline( cmd )
657 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800658 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800659 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800660 return main.TRUE
661 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800662 main.log.error( self.name + ": EOF exception found" )
663 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800664 return main.FALSE
665
Jon Hall7eb38402015-01-08 17:19:54 -0800666 def getMacAddress( self, host ):
667 """
668 Verifies the host's ip configured or not."""
669 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700670 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800671 response = self.execute(
672 cmd=host +
673 " ifconfig",
674 prompt="mininet>",
675 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800676 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800677 main.log.error( self.name + ": EOF exception found" )
678 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700679 main.cleanup()
680 main.exit()
adminbae64d82013-08-01 10:50:15 -0700681
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700682 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800683 macAddressSearch = re.search( pattern, response, re.I )
684 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800685 main.log.info(
686 self.name +
687 ": Mac-Address of Host " +
688 host +
689 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800690 macAddress )
691 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700692 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800693 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700694
Jon Hall7eb38402015-01-08 17:19:54 -0800695 def getInterfaceMACAddress( self, host, interface ):
696 """
697 Return the IP address of the interface on the given host"""
698 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700699 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800700 response = self.execute( cmd=host + " ifconfig " + interface,
701 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800702 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800703 main.log.error( self.name + ": EOF exception found" )
704 main.log.error( self.name + ": " + self.handle.before )
705 main.cleanup()
706 main.exit()
707
708 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800709 macAddressSearch = re.search( pattern, response, re.I )
710 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800711 main.log.info( "No mac address found in %s" % response )
712 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800713 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800714 main.log.info(
715 "Mac-Address of " +
716 host +
717 ":" +
718 interface +
719 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800720 macAddress )
721 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800722 else:
723 main.log.error( "Connection failed to the host" )
724
725 def getIPAddress( self, host ):
726 """
727 Verifies the host's ip configured or not."""
728 if self.handle:
729 try:
730 response = self.execute(
731 cmd=host +
732 " ifconfig",
733 prompt="mininet>",
734 timeout=10 )
735 except pexpect.EOF:
736 main.log.error( self.name + ": EOF exception found" )
737 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700738 main.cleanup()
739 main.exit()
adminbae64d82013-08-01 10:50:15 -0700740
741 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800742 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800743 main.log.info(
744 self.name +
745 ": IP-Address of Host " +
746 host +
747 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800748 ipAddressSearch.group( 1 ) )
749 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800750 else:
751 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800752
Jon Hall7eb38402015-01-08 17:19:54 -0800753 def getSwitchDPID( self, switch ):
754 """
755 return the datapath ID of the switch"""
756 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700757 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700758 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800759 response = self.execute(
760 cmd=cmd,
761 prompt="mininet>",
762 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800763 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800764 main.log.error( self.name + ": EOF exception found" )
765 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700766 main.cleanup()
767 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800768 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800769 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700770 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800771 main.log.info(
772 "Couldn't find DPID for switch %s, found: %s" %
773 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700774 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800775 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700776 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800777 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700778
Jon Hall7eb38402015-01-08 17:19:54 -0800779 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700780 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800781 self.handle.sendline( "" )
782 self.expect( "mininet>" )
783 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700784 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800785 response = self.execute(
786 cmd=cmd,
787 prompt="mininet>",
788 timeout=10 )
789 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700790 response = self.handle.before
791 return response
792 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800793 main.log.error( self.name + ": EOF exception found" )
794 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700795 main.cleanup()
796 main.exit()
797
Jon Hall7eb38402015-01-08 17:19:54 -0800798 def getInterfaces( self, node ):
799 """
800 return information dict about interfaces connected to the node"""
801 if self.handle:
802 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800803 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700804 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700805 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800806 response = self.execute(
807 cmd=cmd,
808 prompt="mininet>",
809 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800810 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800811 main.log.error( self.name + ": EOF exception found" )
812 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700813 main.cleanup()
814 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700815 return response
816 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800817 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700818
Jon Hall7eb38402015-01-08 17:19:54 -0800819 def dump( self ):
820 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700821 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800822 response = self.execute(
823 cmd='dump',
824 prompt='mininet>',
825 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800826 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800827 main.log.error( self.name + ": EOF exception found" )
828 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700829 main.cleanup()
830 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700831 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800832
Jon Hall7eb38402015-01-08 17:19:54 -0800833 def intfs( self ):
834 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700835 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800836 response = self.execute(
837 cmd='intfs',
838 prompt='mininet>',
839 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800840 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800841 main.log.error( self.name + ": EOF exception found" )
842 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700843 main.cleanup()
844 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700845 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800846
Jon Hall7eb38402015-01-08 17:19:54 -0800847 def net( self ):
848 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700849 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800850 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
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 Hall668ed802014-04-08 17:17:59 -0700856 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800857
858 def iperf( self, host1, host2 ):
859 main.log.info(
860 self.name +
861 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700862 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800863 cmd1 = 'iperf ' + host1 + " " + host2
864 self.handle.sendline( cmd1 )
865 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800866 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800867 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800868 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800869 return main.TRUE
870 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800871 main.log.error( self.name + ": iperf test failed" )
872 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800873 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800874 main.log.error( self.name + ": EOF exception found" )
875 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800876 main.cleanup()
877 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800878
Jon Hall7eb38402015-01-08 17:19:54 -0800879 def iperfudp( self ):
880 main.log.info(
881 self.name +
882 ": Simple iperf TCP test between two " +
883 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700884 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800885 response = self.execute(
886 cmd='iperfudp',
887 prompt='mininet>',
888 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800889 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800890 main.log.error( self.name + ": EOF exception found" )
891 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700892 main.cleanup()
893 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700894 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800895
Jon Hall7eb38402015-01-08 17:19:54 -0800896 def nodes( self ):
897 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700898 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800899 response = self.execute(
900 cmd='nodes',
901 prompt='mininet>',
902 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800903 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800904 main.log.error( self.name + ": EOF exception found" )
905 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700906 main.cleanup()
907 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700908 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800909
Jon Hall7eb38402015-01-08 17:19:54 -0800910 def pingpair( self ):
911 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700912 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800913 response = self.execute(
914 cmd='pingpair',
915 prompt='mininet>',
916 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800917 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800918 main.log.error( self.name + ": EOF exception found" )
919 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700920 main.cleanup()
921 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800922
Jon Hall7eb38402015-01-08 17:19:54 -0800923 if re.search( ',\s0\%\spacket\sloss', response ):
924 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800925 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700926 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800927 else:
928 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800929 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700930 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800931
Jon Hall7eb38402015-01-08 17:19:54 -0800932 def link( self, **linkargs ):
933 """
934 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800935 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800936 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
937 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
938 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
939 main.log.info(
940 "Bring link between '" +
941 end1 +
942 "' and '" +
943 end2 +
944 "' '" +
945 option +
946 "'" )
947 command = "link " + \
948 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -0700949 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800950 self.handle.sendline( command )
951 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800952 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800953 main.log.error( self.name + ": EOF exception found" )
954 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700955 main.cleanup()
956 main.exit()
adminbae64d82013-08-01 10:50:15 -0700957 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800958
Jon Hall7eb38402015-01-08 17:19:54 -0800959 def yank( self, **yankargs ):
960 """
961 yank a mininet switch interface to a host"""
962 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800963 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800964 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
965 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
966 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700967 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800968 response = self.execute(
969 cmd=command,
970 prompt="mininet>",
971 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800972 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800973 main.log.error( self.name + ": EOF exception found" )
974 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700975 main.cleanup()
976 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700977 return main.TRUE
978
Jon Hall7eb38402015-01-08 17:19:54 -0800979 def plug( self, **plugargs ):
980 """
981 plug the yanked mininet switch interface to a switch"""
982 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800983 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800984 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
985 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
986 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700987 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800988 response = self.execute(
989 cmd=command,
990 prompt="mininet>",
991 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800992 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800993 main.log.error( self.name + ": EOF exception found" )
994 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700995 main.cleanup()
996 main.exit()
adminbae64d82013-08-01 10:50:15 -0700997 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800998
Jon Hall7eb38402015-01-08 17:19:54 -0800999 def dpctl( self, **dpctlargs ):
1000 """
1001 Run dpctl command on all switches."""
1002 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001003 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001004 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1005 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1006 command = "dpctl " + cmd + " " + str( cmdargs )
1007 try:
1008 response = self.execute(
1009 cmd=command,
1010 prompt="mininet>",
1011 timeout=10 )
1012 except pexpect.EOF:
1013 main.log.error( self.name + ": EOF exception found" )
1014 main.log.error( self.name + ": " + self.handle.before )
1015 main.cleanup()
1016 main.exit()
1017 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001018
kelvin-onlabd3b64892015-01-20 13:26:24 -08001019 def getVersion( self ):
Jon Hallff6b4b22015-02-23 09:25:15 -08001020 #FIXME: What uses this? This should be refactored to get
1021 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001022 fileInput = path + '/lib/Mininet/INSTALL'
1023 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001024 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001025 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001026 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001027 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001028 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001029 return version
adminbae64d82013-08-01 10:50:15 -07001030
kelvin-onlabd3b64892015-01-20 13:26:24 -08001031 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001032 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001033 Parameters:
1034 sw: The name of an OVS switch. Example "s1"
1035 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001036 The output of the command from the mininet cli
1037 or main.FALSE on timeout"""
1038 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001039 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001040 response = self.execute(
1041 cmd=command,
1042 prompt="mininet>",
1043 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001044 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001045 return response
admin2a9548d2014-06-17 14:08:07 -07001046 else:
1047 return main.FALSE
1048 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001049 main.log.error( self.name + ": EOF exception found" )
1050 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001051 main.cleanup()
1052 main.exit()
adminbae64d82013-08-01 10:50:15 -07001053
kelvin-onlabd3b64892015-01-20 13:26:24 -08001054 def assignSwController( self, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001055 """
1056 count is only needed if there is more than 1 controller"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001057 args = utilities.parse_args( [ "COUNT" ], **kwargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001058 count = args[ "COUNT" ] if args != {} else 1
Jon Hallf89c8552014-04-02 13:14:06 -07001059
1060 argstring = "SW"
Jon Hall7eb38402015-01-08 17:19:54 -08001061 for j in range( count ):
1062 argstring = argstring + ",IP" + \
1063 str( j + 1 ) + ",PORT" + str( j + 1 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001064 args = utilities.parse_args( argstring.split( "," ), **kwargs )
Jon Hallf89c8552014-04-02 13:14:06 -07001065
Jon Hall7eb38402015-01-08 17:19:54 -08001066 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1067 ptcpA = int( args[ "PORT1" ] ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001068 int( sw ) if args[ "PORT1" ] is not None else ""
Jon Hall7eb38402015-01-08 17:19:54 -08001069 ptcpB = "ptcp:" + str( ptcpA ) if ptcpA != "" else ""
Jon Hallfbc828e2015-01-06 17:30:19 -08001070
Jon Hall7eb38402015-01-08 17:19:54 -08001071 command = "sh ovs-vsctl set-controller s" + \
1072 str( sw ) + " " + ptcpB + " "
1073 for j in range( count ):
1074 i = j + 1
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001075 args = utilities.parse_args(
Jon Hall7eb38402015-01-08 17:19:54 -08001076 [ "IP" + str( i ), "PORT" + str( i ) ], **kwargs )
1077 ip = args[
1078 "IP" +
1079 str( i ) ] if args[
1080 "IP" +
1081 str( i ) ] is not None else ""
1082 port = args[
1083 "PORT" +
1084 str( i ) ] if args[
1085 "PORT" +
1086 str( i ) ] is not None else ""
1087 tcp = "tcp:" + str( ip ) + ":" + str( port ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001088 " " if ip != "" else ""
Jon Hallf89c8552014-04-02 13:14:06 -07001089 command = command + tcp
Jon Hall6094a362014-04-11 14:46:56 -07001090 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001091 self.execute( cmd=command, prompt="mininet>", timeout=5 )
Jon Hall6094a362014-04-11 14:46:56 -07001092 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001093 main.log.error( self.name + ": EOF exception found" )
1094 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001095 main.cleanup()
1096 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001097 except Exception:
1098 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall6094a362014-04-11 14:46:56 -07001099 main.cleanup()
1100 main.exit()
adminbae64d82013-08-01 10:50:15 -07001101
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001103 """
1104 Removes the controller target from sw"""
1105 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001106 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001107 response = self.execute(
1108 cmd=command,
1109 prompt="mininet>",
1110 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001111 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001112 main.log.error( self.name + ": EOF exception found" )
1113 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001114 main.cleanup()
1115 main.exit()
1116 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001117 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001118
kelvin-onlabd3b64892015-01-20 13:26:24 -08001119 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001120 """
Jon Hallb1290e82014-11-18 16:17:48 -05001121 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001122 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001123 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001124 NOTE: cannot currently specify what type of switch
1125 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001126 sw = name of the new switch as a string
1127 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001128 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001129 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001130 """
1131 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001132 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001133 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001134 response = self.execute(
1135 cmd=command,
1136 prompt="mininet>",
1137 timeout=10 )
1138 if re.search( "already exists!", response ):
1139 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001140 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001141 elif re.search( "Error", response ):
1142 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001143 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001144 elif re.search( "usage:", response ):
1145 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001146 return main.FALSE
1147 else:
1148 return main.TRUE
1149 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001150 main.log.error( self.name + ": EOF exception found" )
1151 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001152 main.cleanup()
1153 main.exit()
1154
kelvin-onlabd3b64892015-01-20 13:26:24 -08001155 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001156 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001157 delete a switch from the mininet topology
1158 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001159 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001160 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001161 sw = name of the switch as a string
1162 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001163 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001164 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001165 response = self.execute(
1166 cmd=command,
1167 prompt="mininet>",
1168 timeout=10 )
1169 if re.search( "no switch named", response ):
1170 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001171 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001172 elif re.search( "Error", response ):
1173 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001174 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001175 elif re.search( "usage:", response ):
1176 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001177 return main.FALSE
1178 else:
1179 return main.TRUE
1180 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001181 main.log.error( self.name + ": EOF exception found" )
1182 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001183 main.cleanup()
1184 main.exit()
1185
kelvin-onlabd3b64892015-01-20 13:26:24 -08001186 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001187 """
1188 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001189 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001190 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001191 NOTE: cannot currently specify what type of link
1192 required params:
1193 node1 = the string node name of the first endpoint of the link
1194 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001195 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001196 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001197 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001198 response = self.execute(
1199 cmd=command,
1200 prompt="mininet>",
1201 timeout=10 )
1202 if re.search( "doesnt exist!", response ):
1203 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001204 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001205 elif re.search( "Error", response ):
1206 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001207 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001208 elif re.search( "usage:", response ):
1209 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001210 return main.FALSE
1211 else:
1212 return main.TRUE
1213 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001214 main.log.error( self.name + ": EOF exception found" )
1215 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001216 main.cleanup()
1217 main.exit()
1218
kelvin-onlabd3b64892015-01-20 13:26:24 -08001219 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001220 """
1221 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001222 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001223 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001224 required params:
1225 node1 = the string node name of the first endpoint of the link
1226 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001227 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001228 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001229 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001230 response = self.execute(
1231 cmd=command,
1232 prompt="mininet>",
1233 timeout=10 )
1234 if re.search( "no node named", response ):
1235 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001236 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001237 elif re.search( "Error", response ):
1238 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001239 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001240 elif re.search( "usage:", response ):
1241 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001242 return main.FALSE
1243 else:
1244 return main.TRUE
1245 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001246 main.log.error( self.name + ": EOF exception found" )
1247 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001248 main.cleanup()
1249 main.exit()
1250
kelvin-onlabd3b64892015-01-20 13:26:24 -08001251 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001252 """
Jon Hallb1290e82014-11-18 16:17:48 -05001253 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001254 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001255 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001256 NOTE: cannot currently specify what type of host
1257 required params:
1258 hostname = the string hostname
1259 optional key-value params
1260 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001261 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001262 """
1263 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001264 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001265 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001266 response = self.execute(
1267 cmd=command,
1268 prompt="mininet>",
1269 timeout=10 )
1270 if re.search( "already exists!", response ):
1271 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001272 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001273 elif re.search( "doesnt exists!", response ):
1274 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001275 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001276 elif re.search( "Error", response ):
1277 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001278 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001279 elif re.search( "usage:", response ):
1280 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001281 return main.FALSE
1282 else:
1283 return main.TRUE
1284 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001285 main.log.error( self.name + ": EOF exception found" )
1286 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001287 main.cleanup()
1288 main.exit()
1289
kelvin-onlabd3b64892015-01-20 13:26:24 -08001290 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001291 """
1292 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001293 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001294 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001295 NOTE: this uses a custom mn function
1296 required params:
1297 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001298 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001299 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001300 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001301 response = self.execute(
1302 cmd=command,
1303 prompt="mininet>",
1304 timeout=10 )
1305 if re.search( "no host named", response ):
1306 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001307 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001308 elif re.search( "Error", response ):
1309 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001310 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001311 elif re.search( "usage:", response ):
1312 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001313 return main.FALSE
1314 else:
1315 return main.TRUE
1316 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001317 main.log.error( self.name + ": EOF exception found" )
1318 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001319 main.cleanup()
1320 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001321
Jon Hall7eb38402015-01-08 17:19:54 -08001322 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001323 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001324 Called at the end of the test to stop the mininet and
1325 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001326 """
1327 self.handle.sendline('')
Jon Halld61331b2015-02-17 16:35:47 -08001328 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Hallefbd9792015-03-05 16:11:36 -08001329 timeout=2)
kelvin-onlaba1484582015-02-02 15:46:20 -08001330 if i == 0:
1331 self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001332 elif i == 1:
1333 return main.TRUE
1334 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001335 # print "Disconnecting Mininet"
1336 if self.handle:
1337 self.handle.sendline( "exit" )
1338 self.handle.expect( "exit" )
1339 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001340 else:
1341 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001342 return response
1343
Hari Krishnab35c6d02015-03-18 11:13:51 -07001344 def stopNet( self, fileName = "", timeout=5):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001345 """
Jon Hall21270ac2015-02-16 17:59:55 -08001346 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001347 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001348 main.FALSE if the pexpect handle does not exist.
1349
Jon Halld61331b2015-02-17 16:35:47 -08001350 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001351 """
Jon Hall21270ac2015-02-16 17:59:55 -08001352
Jon Halld61331b2015-02-17 16:35:47 -08001353 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001354 response = ''
1355 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001356 try:
kelvin-onlab26bc17f2015-02-06 14:08:59 -08001357 self.handle.sendline("")
kelvin-onlab56a3f462015-02-06 14:04:43 -08001358 i = self.handle.expect( [ 'mininet>',
1359 '\$',
1360 pexpect.EOF,
1361 pexpect.TIMEOUT ],
1362 timeout )
1363 if i == 0:
1364 main.log.info( "Exiting mininet..." )
1365
Jon Hall7eb38402015-01-08 17:19:54 -08001366 response = self.execute(
1367 cmd="exit",
1368 prompt="(.*)",
1369 timeout=120 )
Jon Halld61331b2015-02-17 16:35:47 -08001370 main.log.info( self.name + ": Stopped")
Jon Hall7eb38402015-01-08 17:19:54 -08001371 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001372 response = main.TRUE
Hari Krishnab35c6d02015-03-18 11:13:51 -07001373
kelvin-onlab56a3f462015-02-06 14:04:43 -08001374 if i == 1:
1375 main.log.info( " Mininet trying to exit while not " +
1376 "in the mininet prompt" )
1377 elif i == 2:
1378 main.log.error( "Something went wrong exiting mininet" )
1379 elif i == 3: # timeout
1380 main.log.error( "Something went wrong exiting mininet " +
1381 "TIMEOUT" )
1382
Hari Krishnab35c6d02015-03-18 11:13:51 -07001383 if fileName:
1384 self.handle.sendline("")
1385 self.handle.expect('\$')
1386 self.handle.sendline("sudo kill -9 \`ps -ef | grep \""+ fileName +"\" | grep -v grep | awk '{print $2}'\`")
Jon Hallfbc828e2015-01-06 17:30:19 -08001387 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 )
Jon Hall6094a362014-04-11 14:46:56 -07001390 main.cleanup()
1391 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001392 else:
1393 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001394 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001395 return response
1396
Jon Hall7eb38402015-01-08 17:19:54 -08001397 def arping( self, src, dest, destmac ):
1398 self.handle.sendline( '' )
1399 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001400
Jon Hall7eb38402015-01-08 17:19:54 -08001401 self.handle.sendline( src + ' arping ' + dest )
admin07529932013-11-22 14:58:28 -08001402 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001403 self.handle.expect( [ destmac, pexpect.EOF, pexpect.TIMEOUT ] )
1404 main.log.info( self.name + ": ARP successful" )
1405 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001406 return main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -08001407 except Exception:
Jon Hall7eb38402015-01-08 17:19:54 -08001408 main.log.warn( self.name + ": ARP FAILURE" )
1409 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001410 return main.FALSE
1411
Jon Hall7eb38402015-01-08 17:19:54 -08001412 def decToHex( self, num ):
1413 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001414
Jon Hall7eb38402015-01-08 17:19:54 -08001415 def getSwitchFlowCount( self, switch ):
1416 """
1417 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001418 if self.handle:
1419 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1420 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001421 response = self.execute(
1422 cmd=cmd,
1423 prompt="mininet>",
1424 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001425 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001426 main.log.error( self.name + ": EOF exception found" )
1427 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001428 main.cleanup()
1429 main.exit()
1430 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001431 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001432 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001433 main.log.info(
1434 "Couldn't find flows on switch %s, found: %s" %
1435 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001436 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001437 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001438 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001439 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001440
kelvin-onlabd3b64892015-01-20 13:26:24 -08001441 def checkFlows( self, sw, dumpFormat=None ):
1442 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001443 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001444 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001445 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001446 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001447 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001448 response = self.execute(
1449 cmd=command,
1450 prompt="mininet>",
1451 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001452 return response
1453 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001454 main.log.error( self.name + ": EOF exception found" )
1455 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001456 main.cleanup()
1457 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001458
kelvin-onlabd3b64892015-01-20 13:26:24 -08001459 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001460 """
Jon Hallefbd9792015-03-05 16:11:36 -08001461 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001462 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001463 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001464 self.handle.sendline( "" )
1465 self.handle.expect( "mininet>" )
1466 self.handle.sendline(
1467 "sh sudo tcpdump -n -i " +
1468 intf +
1469 " " +
1470 port +
1471 " -w " +
1472 filename.strip() +
1473 " &" )
1474 self.handle.sendline( "" )
1475 i = self.handle.expect( [ 'No\ssuch\device',
1476 'listening\son',
1477 pexpect.TIMEOUT,
1478 "mininet>" ],
1479 timeout=10 )
1480 main.log.warn( self.handle.before + self.handle.after )
1481 self.handle.sendline( "" )
1482 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001483 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001484 main.log.error(
1485 self.name +
1486 ": tcpdump - No such device exists. " +
1487 "tcpdump attempted on: " +
1488 intf )
admin2a9548d2014-06-17 14:08:07 -07001489 return main.FALSE
1490 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001491 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001492 return main.TRUE
1493 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001494 main.log.error(
1495 self.name +
1496 ": tcpdump command timed out! Check interface name," +
1497 " given interface was: " +
1498 intf )
admin2a9548d2014-06-17 14:08:07 -07001499 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001500 elif i == 3:
1501 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001502 return main.TRUE
1503 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001504 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001505 return main.FALSE
1506 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001507 main.log.error( self.name + ": EOF exception found" )
1508 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001509 main.cleanup()
1510 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001511 except Exception:
1512 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001513 main.cleanup()
1514 main.exit()
1515
kelvin-onlabd3b64892015-01-20 13:26:24 -08001516 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001517 """
1518 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001519 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001520 self.handle.sendline( "sh sudo pkill tcpdump" )
1521 self.handle.expect( "mininet>" )
1522 self.handle.sendline( "" )
1523 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001524 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001525 main.log.error( self.name + ": EOF exception found" )
1526 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001527 main.cleanup()
1528 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001529 except Exception:
1530 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001531 main.cleanup()
1532 main.exit()
1533
kelvin-onlabd3b64892015-01-20 13:26:24 -08001534 def compareSwitches( self, topo, switchesJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001535 """
1536 Compare mn and onos switches
1537 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001538 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001539
Jon Hall7eb38402015-01-08 17:19:54 -08001540 This uses the sts TestONTopology object"""
kelvin-onlabd3b64892015-01-20 13:26:24 -08001541 # main.log.debug( "Switches_json string: ", switchesJson )
Jon Hall7eb38402015-01-08 17:19:54 -08001542 output = { "switches": [] }
1543 # iterate through the MN topology and pull out switches and and port
1544 # info
1545 for switch in topo.graph.switches:
Jon Hall3d87d502014-10-17 18:37:42 -04001546 ports = []
1547 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001548 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001549 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001550 'name': port.name } )
1551 output[ 'switches' ].append( {
1552 "name": switch.name,
1553 "dpid": str( switch.dpid ).zfill( 16 ),
1554 "ports": ports } )
Jon Hall3d87d502014-10-17 18:37:42 -04001555
Jon Hall7eb38402015-01-08 17:19:54 -08001556 # print "mn"
1557 # print json.dumps( output,
Jon Hallff6b4b22015-02-23 09:25:15 -08001558 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001559 # indent=4,
1560 # separators=( ',', ': ' ) )
1561 # print "onos"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001562 # print json.dumps( switchesJson,
Jon Hallff6b4b22015-02-23 09:25:15 -08001563 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001564 # indent=4,
1565 # separators=( ',', ': ' ) )
Jon Hall3d87d502014-10-17 18:37:42 -04001566
1567 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001568 mnDPIDs = []
1569 for switch in output[ 'switches' ]:
1570 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001571 mnDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001572 # print "List of Mininet switch DPID's"
1573 # print mnDPIDs
kelvin-onlabd3b64892015-01-20 13:26:24 -08001574 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001575 main.log.error(
1576 self.name +
1577 ".compare_switches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001578 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001579 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001580 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001581 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001582 if switch[ 'available' ]:
1583 onosDPIDs.append(
1584 switch[ 'id' ].replace(
1585 ":",
1586 '' ).replace(
1587 "of",
1588 '' ).lower() )
1589 # else:
1590 # print "Switch is unavailable:"
1591 # print switch
Jon Hall3d87d502014-10-17 18:37:42 -04001592 onosDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001593 # print "List of ONOS switch DPID's"
1594 # print onosDPIDs
Jon Hall3d87d502014-10-17 18:37:42 -04001595
Jon Hall7eb38402015-01-08 17:19:54 -08001596 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001597 switchResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001598 main.log.report( "Switches in MN but not in ONOS:" )
1599 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
1600 main.log.report( str( list1 ) )
1601 main.log.report( "Switches in ONOS but not in MN:" )
1602 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
kelvin-onlabedcff052015-01-16 12:53:55 -08001603 main.log.report( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001604 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001605 switchResults = main.TRUE
1606 return switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001607
kelvin-onlabd3b64892015-01-20 13:26:24 -08001608 def comparePorts( self, topo, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001609 """
Jon Hall72cf1dc2014-10-20 21:04:50 -04001610 Compare mn and onos ports
1611 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001612 portsJson: parsed json object from the onos ports api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001613
Jon Hallfbc828e2015-01-06 17:30:19 -08001614 Dependencies:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001615 1. This uses the sts TestONTopology object
1616 2. numpy - "sudo pip install numpy"
1617
Jon Hall7eb38402015-01-08 17:19:54 -08001618 """
1619 # FIXME: this does not look for extra ports in ONOS, only checks that
1620 # ONOS has what is in MN
Jon Hall72cf1dc2014-10-20 21:04:50 -04001621 from numpy import uint64
kelvin-onlabd3b64892015-01-20 13:26:24 -08001622 portsResults = main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001623 output = { "switches": [] }
1624 # iterate through the MN topology and pull out switches and and port
1625 # info
1626 for switch in topo.graph.switches:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001627 ports = []
1628 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001629 # print port.hw_addr.toStr( separator='' )
Jon Hallefbd9792015-03-05 16:11:36 -08001630 tmpPort = { 'of_port': port.port_no,
1631 'mac': str( port.hw_addr ).replace( '\'', '' ),
1632 'name': port.name,
1633 'enabled': port.enabled }
Jon Hall39f29df2014-11-04 19:30:21 -05001634
kelvin-onlabd3b64892015-01-20 13:26:24 -08001635 ports.append( tmpPort )
Jon Hallefbd9792015-03-05 16:11:36 -08001636 tmpSwitch = { 'name': switch.name,
1637 'dpid': str( switch.dpid ).zfill( 16 ),
1638 'ports': ports }
Jon Hall39f29df2014-11-04 19:30:21 -05001639
kelvin-onlabd3b64892015-01-20 13:26:24 -08001640 output[ 'switches' ].append( tmpSwitch )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001641
Jon Hall7eb38402015-01-08 17:19:54 -08001642 # PORTS
kelvin-onlabd3b64892015-01-20 13:26:24 -08001643 for mnSwitch in output[ 'switches' ]:
1644 mnPorts = []
1645 onosPorts = []
1646 switchResult = main.TRUE
1647 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001648 if port[ 'enabled' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001649 mnPorts.append( port[ 'of_port' ] )
1650 for onosSwitch in portsJson:
Jon Hall7eb38402015-01-08 17:19:54 -08001651 # print "Iterating through a new switch as seen by ONOS"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001652 # print onosSwitch
1653 if onosSwitch[ 'device' ][ 'available' ]:
1654 if onosSwitch[ 'device' ][ 'id' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001655 ':',
1656 '' ).replace(
1657 "of",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001658 '' ) == mnSwitch[ 'dpid' ]:
1659 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001660 if port[ 'isEnabled' ]:
1661 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001662 # onosPorts.append( 'local' )
1663 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001664 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001665 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001666 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001667 mnPorts.sort( key=float )
1668 onosPorts.sort( key=float )
1669 # print "\nPorts for Switch %s:" % ( mnSwitch[ 'name' ] )
1670 # print "\tmn_ports[] = ", mnPorts
1671 # print "\tonos_ports[] = ", onosPorts
1672 mnPortsLog = mnPorts
1673 onosPortsLog = onosPorts
1674 mnPorts = [ x for x in mnPorts ]
1675 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001676
Jon Hall7eb38402015-01-08 17:19:54 -08001677 # TODO: handle other reserved port numbers besides LOCAL
1678 # NOTE: Reserved ports
1679 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1680 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001681 for mnPort in mnPortsLog:
1682 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001683 # don't set results to true here as this is just one of
1684 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001685 mnPorts.remove( mnPort )
1686 onosPorts.remove( mnPort )
Jon Hall7eb38402015-01-08 17:19:54 -08001687 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001688 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001689 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001690 if 65534 in mnPorts:
1691 mnPorts.remove( 65534 )
1692 if long( uint64( -2 ) ) in onosPorts:
1693 onosPorts.remove( long( uint64( -2 ) ) )
1694 if len( mnPorts ): # the ports of this switch don't match
1695 switchResult = main.FALSE
1696 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1697 if len( onosPorts ): # the ports of this switch don't match
1698 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001699 main.log.warn(
1700 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001701 str( onosPorts ) )
1702 if switchResult == main.FALSE:
Jon Hall7eb38402015-01-08 17:19:54 -08001703 main.log.report(
1704 "The list of ports for switch %s(%s) does not match:" %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001705 ( mnSwitch[ 'name' ], mnSwitch[ 'dpid' ] ) )
1706 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1707 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1708 portsResults = portsResults and switchResult
1709 return portsResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001710
kelvin-onlabd3b64892015-01-20 13:26:24 -08001711 def compareLinks( self, topo, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001712 """
1713 Compare mn and onos links
1714 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001715 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001716
Jon Hall7eb38402015-01-08 17:19:54 -08001717 This uses the sts TestONTopology object"""
1718 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08001719 # ONOS has what is in MN
Jon Hall7eb38402015-01-08 17:19:54 -08001720 output = { "switches": [] }
kelvin-onlabd3b64892015-01-20 13:26:24 -08001721 onos = linksJson
Jon Hall7eb38402015-01-08 17:19:54 -08001722 # iterate through the MN topology and pull out switches and and port
1723 # info
1724 for switch in topo.graph.switches:
Jon Hall38481722014-11-04 16:50:05 -05001725 # print "Iterating though switches as seen by Mininet"
1726 # print switch
Jon Hall72cf1dc2014-10-20 21:04:50 -04001727 ports = []
1728 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001729 # print port.hw_addr.toStr( separator='' )
1730 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001731 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001732 'name': port.name } )
1733 output[ 'switches' ].append( {
1734 "name": switch.name,
1735 "dpid": str( switch.dpid ).zfill( 16 ),
1736 "ports": ports } )
1737 # LINKS
Jon Hall72cf1dc2014-10-20 21:04:50 -04001738
kelvin-onlabd3b64892015-01-20 13:26:24 -08001739 mnLinks = [
kelvin-onlab9592d132015-01-20 17:18:02 -08001740 link for link in topo.patch_panel.network_links if (
Jon Hall7eb38402015-01-08 17:19:54 -08001741 link.port1.enabled and link.port2.enabled ) ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08001742 if 2 * len( mnLinks ) == len( onos ):
1743 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001744 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001745 linkResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001746 main.log.report(
Jon Hall328ddca2015-01-28 15:57:15 -08001747 "Mininet has " + str( len( mnLinks ) ) +
1748 " bidirectional links and ONOS has " +
1749 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001750
Jon Hall7eb38402015-01-08 17:19:54 -08001751 # iterate through MN links and check if an ONOS link exists in
1752 # both directions
1753 # NOTE: Will currently only show mn links as down if they are
1754 # cut through STS. We can either do everything through STS or
kelvin-onlabd3b64892015-01-20 13:26:24 -08001755 # wait for upNetworkLinks and downNetworkLinks to be
Jon Hall7eb38402015-01-08 17:19:54 -08001756 # fully implemented.
kelvin-onlabd3b64892015-01-20 13:26:24 -08001757 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08001758 # print "Link: %s" % link
1759 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04001760 node1 = None
1761 port1 = None
1762 node2 = None
1763 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08001764 firstDir = main.FALSE
1765 secondDir = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001766 for switch in output[ 'switches' ]:
1767 # print "Switch: %s" % switch[ 'name' ]
1768 if switch[ 'name' ] == link.node1.name:
1769 node1 = switch[ 'dpid' ]
1770 for port in switch[ 'ports' ]:
1771 if str( port[ 'name' ] ) == str( link.port1 ):
1772 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001773 if node1 is not None and node2 is not None:
1774 break
Jon Hall7eb38402015-01-08 17:19:54 -08001775 if switch[ 'name' ] == link.node2.name:
1776 node2 = switch[ 'dpid' ]
1777 for port in switch[ 'ports' ]:
1778 if str( port[ 'name' ] ) == str( link.port2 ):
1779 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001780 if node1 is not None and node2 is not None:
1781 break
1782
kelvin-onlabd3b64892015-01-20 13:26:24 -08001783 for onosLink in onos:
1784 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001785 ":",
1786 '' ).replace(
1787 "of",
1788 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001789 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001790 ":",
1791 '' ).replace(
1792 "of",
1793 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001794 onosPort1 = onosLink[ 'src' ][ 'port' ]
1795 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001796
Jon Hall72cf1dc2014-10-20 21:04:50 -04001797 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08001798 if str( onosNode1 ) == str( node1 ) and str(
1799 onosNode2 ) == str( node2 ):
1800 if int( onosPort1 ) == int( port1 ) and int(
1801 onosPort2 ) == int( port2 ):
1802 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001803 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001804 main.log.warn(
1805 'The port numbers do not match for ' +
1806 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001807 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001808 'link %s/%s -> %s/%s' %
1809 ( node1,
1810 port1,
1811 node2,
1812 port2 ) +
1813 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001814 ( onosNode1,
1815 onosPort1,
1816 onosNode2,
1817 onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001818
1819 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08001820 elif ( str( onosNode1 ) == str( node2 ) and
1821 str( onosNode2 ) == str( node1 ) ):
1822 if ( int( onosPort1 ) == int( port2 )
1823 and int( onosPort2 ) == int( port1 ) ):
1824 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001825 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001826 main.log.warn(
1827 'The port numbers do not match for ' +
1828 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001829 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001830 'link %s/%s -> %s/%s' %
1831 ( node2,
1832 port2,
1833 node1,
1834 port1 ) +
1835 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001836 ( onosNode2,
1837 onosPort2,
1838 onosNode1,
1839 onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001840 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04001841 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08001842 if not firstDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001843 main.log.report(
1844 'ONOS does not have the link %s/%s -> %s/%s' %
1845 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001846 if not secondDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001847 main.log.report(
1848 'ONOS does not have the link %s/%s -> %s/%s' %
1849 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001850 linkResults = linkResults and firstDir and secondDir
1851 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001852
Jon Hallff6b4b22015-02-23 09:25:15 -08001853 def compareHosts( self, topo, hostsJson ):
1854 """
1855 Compare mn and onos Hosts.
1856 Since Mininet hosts are quiet, ONOS will only know of them when they
1857 speak. For this reason, we will only check that the hosts in ONOS
1858 stores are in Mininet, and not vice versa.
1859 topo: sts TestONTopology object
1860 hostsJson: parsed json object from the onos hosts api
1861
1862 This uses the sts TestONTopology object"""
1863 import json
1864 hostResults = main.TRUE
1865 hosts = []
1866 # iterate through the MN topology and pull out hosts
1867 for mnHost in topo.graph.hosts:
1868 interfaces = []
1869 for intf in mnHost.interfaces:
1870 interfaces.append( {
1871 "name": intf.name, # str
1872 "ips": [ str( ip ) for ip in intf.ips ], # list of IPAddrs
1873 # hw_addr is of type EthAddr, Not JSON serializable
1874 "hw_addr": str( intf.hw_addr ) } )
1875 hosts.append( {
1876 "name": mnHost.name, # str
1877 "interfaces": interfaces } ) # list
1878 for onosHost in hostsJson:
1879 onosMAC = onosHost[ 'mac' ].lower()
1880 match = False
1881 for mnHost in hosts:
1882 for mnIntf in mnHost[ 'interfaces' ]:
1883 if onosMAC == mnIntf[ 'hw_addr' ].lower() :
1884 match = True
1885 for ip in mnIntf[ 'ips' ]:
1886 if ip in onosHost[ 'ips' ]:
1887 pass # all is well
1888 else:
1889 # misssing ip
1890 main.log.error( "ONOS host " + onosHost[ 'id' ]
1891 + " has a different IP than " +
1892 "the Mininet host." )
1893 output = json.dumps(
1894 onosHost,
1895 sort_keys=True,
1896 indent=4,
1897 separators=( ',', ': ' ) )
1898 main.log.info( output )
1899 hostResults = main.FALSE
1900 if not match:
1901 hostResults = main.FALSE
1902 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
1903 "corresponding Mininet host." )
1904 output = json.dumps( onosHost,
1905 sort_keys=True,
1906 indent=4,
1907 separators=( ',', ': ' ) )
1908 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08001909 return hostResults
1910
kelvin-onlabd3b64892015-01-20 13:26:24 -08001911 def getHosts( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08001912 """
1913 Returns a list of all hosts
1914 Don't ask questions just use it"""
1915 self.handle.sendline( "" )
1916 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001917
Jon Hall7eb38402015-01-08 17:19:54 -08001918 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
1919 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001920
kelvin-onlabd3b64892015-01-20 13:26:24 -08001921 handlePy = self.handle.before
1922 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
1923 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07001924
Jon Hall7eb38402015-01-08 17:19:54 -08001925 self.handle.sendline( "" )
1926 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001927
kelvin-onlabd3b64892015-01-20 13:26:24 -08001928 hostStr = handlePy.replace( "]", "" )
1929 hostStr = hostStr.replace( "'", "" )
1930 hostStr = hostStr.replace( "[", "" )
1931 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001932
kelvin-onlabd3b64892015-01-20 13:26:24 -08001933 return hostList
adminbae64d82013-08-01 10:50:15 -07001934
Jon Hall7eb38402015-01-08 17:19:54 -08001935 def update( self ):
1936 """
1937 updates the port address and status information for
1938 each port in mn"""
1939 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08001940 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05001941 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001942 self.handle.sendline( "" )
1943 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001944
Jon Hall7eb38402015-01-08 17:19:54 -08001945 self.handle.sendline( "update" )
1946 self.handle.expect( "update" )
1947 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001948
Jon Hall7eb38402015-01-08 17:19:54 -08001949 self.handle.sendline( "" )
1950 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001951
Jon Hallb1290e82014-11-18 16:17:48 -05001952 return main.TRUE
1953 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001954 main.log.error( self.name + ": EOF exception found" )
1955 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001956 main.cleanup()
1957 main.exit()
1958
adminbae64d82013-08-01 10:50:15 -07001959if __name__ != "__main__":
1960 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07001961 sys.modules[ __name__ ] = MininetCliDriver()