blob: 3a8328330378fced3d74386732cab6014ab72bb1 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
Jon Hallbe6dfc42015-01-12 17:37:25 -08005author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
Jon Hall7eb38402015-01-08 17:19:54 -08008TestON is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 2 of the License, or
11( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
Jon Hall7eb38402015-01-08 17:19:54 -080013TestON is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070017
Jon Hall7eb38402015-01-08 17:19:54 -080018You should have received a copy of the GNU General Public License
19along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
21
Jon Hallbe6dfc42015-01-12 17:37:25 -080022MininetCliDriver is the basic driver which will handle the Mininet functions
23
Jon Hall272a4db2015-01-12 17:43:48 -080024Some functions rely on STS module. To install this,
25 git clone https://github.com/jhall11/sts.git
26
Jon Hallbe6dfc42015-01-12 17:37:25 -080027Some functions rely on a modified version of Mininet. These functions
28should all be noted in the comments. To get this MN version run these commands
29from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080030 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080032 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080033 git pull
34
Jon Hall272a4db2015-01-12 17:43:48 -080035
36 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080037changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070038import pexpect
adminbae64d82013-08-01 10:50:15 -070039import re
40import sys
Jon Hall7eb38402015-01-08 17:19:54 -080041sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070044
Jon Hall7eb38402015-01-08 17:19:54 -080045
46class MininetCliDriver( Emulator ):
47
48 """
49 MininetCliDriver is the basic driver which will handle
50 the Mininet functions"""
51 def __init__( self ):
52 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070053 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080054 self.name = None
Jon Hall7eb38402015-01-08 17:19:54 -080055 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070056 self.flag = 0
57
Jon Hall7eb38402015-01-08 17:19:54 -080058 def connect( self, **connectargs ):
59 """
60 Here the main is the TestON instance after creating
61 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080062 try:
63 for key in connectargs:
64 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080065
kelvin-onlaba1484582015-02-02 15:46:20 -080066 self.name = self.options[ 'name' ]
67 self.handle = super(
68 MininetCliDriver,
69 self ).connect(
70 user_name=self.user_name,
71 ip_address=self.ip_address,
72 port=None,
73 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080074
kelvin-onlaba1484582015-02-02 15:46:20 -080075 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080076 main.log.info( "Connection successful to the host " +
77 self.user_name +
78 "@" +
79 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080080 return main.TRUE
81 else:
82 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080083 self.user_name +
84 "@" +
85 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -080086 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -080087 return main.FALSE
88 except pexpect.EOF:
89 main.log.error( self.name + ": EOF exception found" )
90 main.log.error( self.name + ": " + self.handle.before )
91 main.cleanup()
92 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -080093 except Exception:
94 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -080095 main.cleanup()
96 main.exit()
97
Jon Hallefbd9792015-03-05 16:11:36 -080098 def startNet( self, topoFile='', args='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -080099 """
100 Starts Mininet accepts a topology(.py) file and/or an optional
Jon Hallefbd9792015-03-05 16:11:36 -0800101 argument ,to start the mininet, as a parameter.
Jon Hall21270ac2015-02-16 17:59:55 -0800102 Returns main.TRUE if the mininet starts successfully and
103 main.FALSE otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800104 """
Jon Hall7eb38402015-01-08 17:19:54 -0800105 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700106 # make sure old networks are cleaned up
107 main.log.info( self.name +
108 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800109 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:
Jon Hall689d8e42015-04-03 13:59:24 -0700116 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800117 main.log.info( self.name + ": Sending sudo password" )
118 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800119 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800120 '\$',
121 pexpect.EOF,
122 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800123 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800124 if i == 1:
125 main.log.info( self.name + ": Clean" )
126 elif i == 2:
127 main.log.error( self.name + ": Connection terminated" )
128 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700129 main.log.error( self.name + ": Something while cleaning " +
130 "Mininet took too long... " )
131 # Craft the string to start mininet
132 cmdString = "sudo "
133 if topoFile is None or topoFile == '': # If no file is given
134 main.log.info( self.name + ": building fresh Mininet" )
135 cmdString += "mn "
136 if args is None or args == '':
137 # If no args given, use args from .topo file
138 args = self.options[ 'arg1' ] +\
139 " " + self.options[ 'arg2' ] +\
140 " --mac --controller " +\
141 self.options[ 'controller' ] + " " +\
142 self.options[ 'arg3' ]
143 else: # else only use given args
144 pass
145 # TODO: allow use of topo args and method args?
146 else: # Use given topology file
147 main.log.info( "Starting Mininet from topo file " + topoFile )
148 cmdString += topoFile + " "
Jon Hallefbd9792015-03-05 16:11:36 -0800149 if args is None:
kelvin-onlaba1484582015-02-02 15:46:20 -0800150 args = ''
Jon Hall689d8e42015-04-03 13:59:24 -0700151 # TODO: allow use of args from .topo file?
152 cmdString += args
153 # Send the command and check if network started
154 self.handle.sendline( "" )
155 self.handle.expect( '\$' )
156 main.log.info( "Sending '" + cmdString + "' to " + self.name )
157 self.handle.sendline( cmdString )
158 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800159 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700160 'Exception',
161 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800162 pexpect.EOF,
163 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700164 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800165 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700166 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800167 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800168 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700169 response = str( self.handle.before +
170 self.handle.after )
171 self.handle.expect( '\$' )
172 response += str( self.handle.before +
173 self.handle.after )
174 main.log.error(
175 self.name +
176 ": Launching Mininet failed: " + response )
177 return main.FALSE
178 elif i == 2:
179 self.handle.expect( [ "\n",
180 pexpect.EOF,
181 pexpect.TIMEOUT ],
182 timeout )
183 main.log.info( self.handle.before )
184 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800185 main.log.error( self.name + ": Connection timeout" )
186 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700187 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800188 main.log.error(
189 self.name +
190 ": Something took too long... " )
191 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700192 # Why did we hit this part?
193 main.log.error( "startNet did not return correctly" )
194 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800195 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700196 main.log.error( self.name + ": Connection failed to the host " +
197 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800198 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700199 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800200
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800201 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400202 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800203 # In tree topology, if fanout arg is not given, by default it is 2
204 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400205 fanout = 2
206 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500207 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800208 while( k <= depth - 1 ):
209 count = count + pow( fanout, k )
210 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800211 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800212 while( k <= depth - 2 ):
213 # depth-2 gives you only core links and not considering
214 # edge links as seen by ONOS. If all the links including
215 # edge links are required, do depth-1
216 count = count + pow( fanout, k )
217 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800218 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800219 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800220 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800221
Jon Hall7eb38402015-01-08 17:19:54 -0800222 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800223 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800224 # by default it is 1
225 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400226 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800227 numSwitches = depth
228 numHostsPerSw = fanout
229 totalNumHosts = numSwitches * numHostsPerSw
230 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800231 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800232 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800233 topoDict = { "num_switches": int( numSwitches ),
234 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400235 return topoDict
236
kelvin-onlabd3b64892015-01-20 13:26:24 -0800237 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700238 """
239 Calculate the number of switches and links in a topo."""
240 # TODO: combine this function and numSwitchesNlinks
241 argList = self.options[ 'arg1' ].split( "," )
242 topoArgList = argList[ 0 ].split( " " )
243 argList = map( int, argList[ 1: ] )
244 topoArgList = topoArgList[ 1: ] + argList
245
246 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400247 return topoDict
248
Jon Hall7eb38402015-01-08 17:19:54 -0800249 def pingall( self, timeout=300 ):
250 """
251 Verifies the reachability of the hosts using pingall command.
252 Optional parameter timeout allows you to specify how long to
253 wait for pingall to complete
254 Returns:
255 main.TRUE if pingall completes with no pings dropped
256 otherwise main.FALSE"""
257 if self.handle:
258 main.log.info(
259 self.name +
260 ": Checking reachabilty to the hosts using pingall" )
Jon Hall6094a362014-04-11 14:46:56 -0700261 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800262 response = self.execute(
263 cmd="pingall",
264 prompt="mininet>",
265 timeout=int( timeout ) )
Jon Hallb1290e82014-11-18 16:17:48 -0500266 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800267 main.log.error( self.name + ": EOF exception found" )
268 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500269 main.cleanup()
270 main.exit()
271 except pexpect.TIMEOUT:
Jon Hall7eb38402015-01-08 17:19:54 -0800272 # We may not want to kill the test if pexpect times out
273 main.log.error( self.name + ": TIMEOUT exception found" )
274 main.log.error( self.name +
275 ": " +
276 str( self.handle.before ) )
277 # NOTE: mininet's pingall rounds, so we will check the number of
278 # passed and number of failed
279 pattern = "Results\:\s0\%\sdropped\s\(" +\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800280 "(?P<passed>[\d]+)/(?P=passed)"
Jon Hall7eb38402015-01-08 17:19:54 -0800281 if re.search( pattern, response ):
282 main.log.info( self.name + ": All hosts are reachable" )
adminbae64d82013-08-01 10:50:15 -0700283 return main.TRUE
284 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800285 main.log.error( self.name + ": Unable to reach all the hosts" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800286 main.log.info( "Pingall output: " + str( response ) )
Jon Hall7eb38402015-01-08 17:19:54 -0800287 # NOTE: Send ctrl-c to make sure pingall is done
288 self.handle.send( "\x03" )
289 self.handle.expect( "Interrupt" )
290 self.handle.expect( "mininet>" )
adminbae64d82013-08-01 10:50:15 -0700291 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800292 else:
293 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallb1290e82014-11-18 16:17:48 -0500294 main.cleanup()
295 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700296
Jon Hall7eb38402015-01-08 17:19:54 -0800297 def fpingHost( self, **pingParams ):
298 """
299 Uses the fping package for faster pinging...
300 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800301 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800302 command = args[ "SRC" ] + \
303 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
304 self.handle.sendline( command )
305 self.handle.expect(
306 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
307 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
308 response = self.handle.before
309 if re.search( ":\s-", response ):
310 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700311 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800312 elif re.search( ":\s\d{1,2}\.\d\d", response ):
313 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700314 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800315 main.log.info( self.name + ": Install fping on mininet machine... " )
316 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700317 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800318
Jon Hall7eb38402015-01-08 17:19:54 -0800319 def pingHost( self, **pingParams ):
320 """
321 Ping from one mininet host to another
322 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800323 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800324 command = args[ "SRC" ] + " ping " + \
325 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700326 try:
Jon Hall61282e32015-03-19 11:34:11 -0700327 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800328 self.handle.sendline( command )
329 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700330 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800331 main.log.error(
332 self.name +
333 ": timeout when waiting for response from mininet" )
334 main.log.error( "response: " + str( self.handle.before ) )
335 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700336 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800337 main.log.error(
338 self.name +
339 ": timeout when waiting for response from mininet" )
340 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700341 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800342 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800343 main.log.error( self.name + ": EOF exception found" )
344 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700345 main.cleanup()
346 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800347 main.log.info( self.name + ": Ping Response: " + response )
348 if re.search( ',\s0\%\spacket\sloss', response ):
349 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800350 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700351 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800352 else:
353 main.log.error(
354 self.name +
355 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800356 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700357 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800358
Jon Hall7eb38402015-01-08 17:19:54 -0800359 def checkIP( self, host ):
360 """
361 Verifies the host's ip configured or not."""
362 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700363 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800364 response = self.execute(
365 cmd=host +
366 " ifconfig",
367 prompt="mininet>",
368 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800369 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800370 main.log.error( self.name + ": EOF exception found" )
371 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700372 main.cleanup()
373 main.exit()
adminbae64d82013-08-01 10:50:15 -0700374
Jon Hall7eb38402015-01-08 17:19:54 -0800375 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800376 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
377 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
378 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
379 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
380 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800381 # pattern = "inet addr:10.0.0.6"
382 if re.search( pattern, response ):
383 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700384 return main.TRUE
385 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800386 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700387 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800388 else:
389 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800390
Jon Hall7eb38402015-01-08 17:19:54 -0800391 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800392 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700393 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800394 response = self.execute(
395 cmd="h1 /usr/sbin/sshd -D&",
396 prompt="mininet>",
397 timeout=10 )
398 response = self.execute(
399 cmd="h4 /usr/sbin/sshd -D&",
400 prompt="mininet>",
401 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700402 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800403 vars( self )[ key ] = connectargs[ key ]
404 response = self.execute(
405 cmd="xterm h1 h4 ",
406 prompt="mininet>",
407 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800408 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800409 main.log.error( self.name + ": EOF exception found" )
410 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700411 main.cleanup()
412 main.exit()
adminbae64d82013-08-01 10:50:15 -0700413 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800414 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700415 if self.flag == 0:
416 self.flag = 1
417 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800418 else:
adminbae64d82013-08-01 10:50:15 -0700419 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800420
kelvin-onlaba1484582015-02-02 15:46:20 -0800421 def moveHost( self, host, oldSw, newSw, ):
422 """
423 Moves a host from one switch to another on the fly
424 Note: The intf between host and oldSw when detached
425 using detach(), will still show up in the 'net'
426 cmd, because switch.detach() doesn't affect switch.intfs[]
427 (which is correct behavior since the interfaces
428 haven't moved).
429 """
430 if self.handle:
431 try:
432 # Bring link between oldSw-host down
Jon Hallefbd9792015-03-05 16:11:36 -0800433 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'"+ host +\
434 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800435 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800436 response = self.execute( cmd=cmd,
437 prompt="mininet>",
438 timeout=10 )
kelvin-onlaba1484582015-02-02 15:46:20 -0800439
440 # Determine hostintf and Oldswitchintf
441 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800442 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800443 print "cmd2= ", cmd
444 self.handle.sendline( cmd )
445 self.handle.expect( "mininet>" )
446
shahshreya73537862015-02-11 15:15:24 -0800447 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800448 cmd = "px ipaddr = hintf.IP()"
449 print "cmd3= ", cmd
450 self.handle.sendline( cmd )
451 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800452
453 cmd = "px macaddr = hintf.MAC()"
454 print "cmd3= ", cmd
455 self.handle.sendline( cmd )
456 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800457
458 # Detach interface between oldSw-host
459 cmd = "px " + oldSw + ".detach( sintf )"
460 print "cmd4= ", cmd
461 self.handle.sendline( cmd )
462 self.handle.expect( "mininet>" )
463
464 # Add link between host-newSw
465 cmd = "py net.addLink(" + host + "," + newSw + ")"
466 print "cmd5= ", cmd
467 self.handle.sendline( cmd )
468 self.handle.expect( "mininet>" )
469
470 # Determine hostintf and Newswitchintf
471 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800472 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800473 print "cmd6= ", cmd
474 self.handle.sendline( cmd )
475 self.handle.expect( "mininet>" )
476
477 # Attach interface between newSw-host
478 cmd = "px " + newSw + ".attach( sintf )"
479 print "cmd3= ", cmd
480 self.handle.sendline( cmd )
481 self.handle.expect( "mininet>" )
482
483 # Set ipaddress of the host-newSw interface
484 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
485 print "cmd7 = ", cmd
486 self.handle.sendline( cmd )
487 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800488
489 # Set macaddress of the host-newSw interface
490 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
491 print "cmd8 = ", cmd
492 self.handle.sendline( cmd )
493 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800494
495 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800496 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800497 self.handle.sendline( cmd )
498 self.handle.expect( "mininet>" )
499 print "output = ", self.handle.before
500
501 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800502 cmd = host + " ifconfig"
503 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800504 self.handle.sendline( cmd )
505 self.handle.expect( "mininet>" )
506 print "ifconfig o/p = ", self.handle.before
507
508 return main.TRUE
509 except pexpect.EOF:
510 main.log.error( self.name + ": EOF exception found" )
511 main.log.error( self.name + ": " + self.handle.before )
512 return main.FALSE
513
Jon Hall7eb38402015-01-08 17:19:54 -0800514 def changeIP( self, host, intf, newIP, newNetmask ):
515 """
516 Changes the ip address of a host on the fly
517 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800518 if self.handle:
519 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800520 cmd = host + " ifconfig " + intf + " " + \
521 newIP + " " + 'netmask' + " " + newNetmask
522 self.handle.sendline( cmd )
523 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800524 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800525 main.log.info( "response = " + response )
526 main.log.info(
527 "Ip of host " +
528 host +
529 " changed to new IP " +
530 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800531 return main.TRUE
532 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800533 main.log.error( self.name + ": EOF exception found" )
534 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800535 return main.FALSE
536
Jon Hall7eb38402015-01-08 17:19:54 -0800537 def changeDefaultGateway( self, host, newGW ):
538 """
539 Changes the default gateway of a host
540 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800541 if self.handle:
542 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800543 cmd = host + " route add default gw " + newGW
544 self.handle.sendline( cmd )
545 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800546 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800547 main.log.info( "response = " + response )
548 main.log.info(
549 "Default gateway of host " +
550 host +
551 " changed to " +
552 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800553 return main.TRUE
554 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800555 main.log.error( self.name + ": EOF exception found" )
556 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800557 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800558
Jon Hall7eb38402015-01-08 17:19:54 -0800559 def addStaticMACAddress( self, host, GW, macaddr ):
560 """
Jon Hallefbd9792015-03-05 16:11:36 -0800561 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800562 if self.handle:
563 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800564 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
565 cmd = host + " arp -s " + GW + " " + macaddr
566 self.handle.sendline( cmd )
567 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800568 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800569 main.log.info( "response = " + response )
570 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800571 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800572 GW +
573 " changed to " +
574 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800575 return main.TRUE
576 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800577 main.log.error( self.name + ": EOF exception found" )
578 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800579 return main.FALSE
580
Jon Hall7eb38402015-01-08 17:19:54 -0800581 def verifyStaticGWandMAC( self, host ):
582 """
583 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800584 if self.handle:
585 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800586 # h1 arp -an
587 cmd = host + " arp -an "
588 self.handle.sendline( cmd )
589 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800590 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800591 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800592 return main.TRUE
593 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800594 main.log.error( self.name + ": EOF exception found" )
595 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800596 return main.FALSE
597
Jon Hall7eb38402015-01-08 17:19:54 -0800598 def getMacAddress( self, host ):
599 """
600 Verifies the host's ip configured or not."""
601 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700602 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800603 response = self.execute(
604 cmd=host +
605 " ifconfig",
606 prompt="mininet>",
607 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800609 main.log.error( self.name + ": EOF exception found" )
610 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700611 main.cleanup()
612 main.exit()
adminbae64d82013-08-01 10:50:15 -0700613
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700614 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800615 macAddressSearch = re.search( pattern, response, re.I )
616 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800617 main.log.info(
618 self.name +
619 ": Mac-Address of Host " +
620 host +
621 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800622 macAddress )
623 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700624 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800625 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700626
Jon Hall7eb38402015-01-08 17:19:54 -0800627 def getInterfaceMACAddress( self, host, interface ):
628 """
629 Return the IP address of the interface on the given host"""
630 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700631 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800632 response = self.execute( cmd=host + " ifconfig " + interface,
633 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800634 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800635 main.log.error( self.name + ": EOF exception found" )
636 main.log.error( self.name + ": " + self.handle.before )
637 main.cleanup()
638 main.exit()
639
640 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800641 macAddressSearch = re.search( pattern, response, re.I )
642 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800643 main.log.info( "No mac address found in %s" % response )
644 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800645 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800646 main.log.info(
647 "Mac-Address of " +
648 host +
649 ":" +
650 interface +
651 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800652 macAddress )
653 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800654 else:
655 main.log.error( "Connection failed to the host" )
656
657 def getIPAddress( self, host ):
658 """
659 Verifies the host's ip configured or not."""
660 if self.handle:
661 try:
662 response = self.execute(
663 cmd=host +
664 " ifconfig",
665 prompt="mininet>",
666 timeout=10 )
667 except pexpect.EOF:
668 main.log.error( self.name + ": EOF exception found" )
669 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700670 main.cleanup()
671 main.exit()
adminbae64d82013-08-01 10:50:15 -0700672
673 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800674 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800675 main.log.info(
676 self.name +
677 ": IP-Address of Host " +
678 host +
679 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800680 ipAddressSearch.group( 1 ) )
681 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800682 else:
683 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800684
Jon Hall7eb38402015-01-08 17:19:54 -0800685 def getSwitchDPID( self, switch ):
686 """
687 return the datapath ID of the switch"""
688 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700689 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700690 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800691 response = self.execute(
692 cmd=cmd,
693 prompt="mininet>",
694 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800695 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800696 main.log.error( self.name + ": EOF exception found" )
697 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700698 main.cleanup()
699 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800700 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800701 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700702 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800703 main.log.info(
704 "Couldn't find DPID for switch %s, found: %s" %
705 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700706 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800707 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700708 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800709 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700710
Jon Hall7eb38402015-01-08 17:19:54 -0800711 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700712 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800713 self.handle.sendline( "" )
714 self.expect( "mininet>" )
715 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700716 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800717 response = self.execute(
718 cmd=cmd,
719 prompt="mininet>",
720 timeout=10 )
721 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700722 response = self.handle.before
723 return response
724 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800725 main.log.error( self.name + ": EOF exception found" )
726 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700727 main.cleanup()
728 main.exit()
729
Jon Hall7eb38402015-01-08 17:19:54 -0800730 def getInterfaces( self, node ):
731 """
732 return information dict about interfaces connected to the node"""
733 if self.handle:
734 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800735 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700736 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700737 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800738 response = self.execute(
739 cmd=cmd,
740 prompt="mininet>",
741 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800742 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800743 main.log.error( self.name + ": EOF exception found" )
744 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700745 main.cleanup()
746 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700747 return response
748 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800749 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700750
Jon Hall7eb38402015-01-08 17:19:54 -0800751 def dump( self ):
752 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700753 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800754 response = self.execute(
755 cmd='dump',
756 prompt='mininet>',
757 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800758 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800759 main.log.error( self.name + ": EOF exception found" )
760 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700761 main.cleanup()
762 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700763 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800764
Jon Hall7eb38402015-01-08 17:19:54 -0800765 def intfs( self ):
766 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700767 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800768 response = self.execute(
769 cmd='intfs',
770 prompt='mininet>',
771 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800772 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800773 main.log.error( self.name + ": EOF exception found" )
774 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700775 main.cleanup()
776 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700777 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800778
Jon Hall7eb38402015-01-08 17:19:54 -0800779 def net( self ):
780 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700781 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800782 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800783 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800784 main.log.error( self.name + ": EOF exception found" )
785 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700786 main.cleanup()
787 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700788 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800789
790 def iperf( self, host1, host2 ):
791 main.log.info(
792 self.name +
793 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700794 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800795 cmd1 = 'iperf ' + host1 + " " + host2
796 self.handle.sendline( cmd1 )
797 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800798 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800799 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800800 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800801 return main.TRUE
802 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800803 main.log.error( self.name + ": iperf test failed" )
804 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800805 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800806 main.log.error( self.name + ": EOF exception found" )
807 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800808 main.cleanup()
809 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800810
Jon Hall7eb38402015-01-08 17:19:54 -0800811 def iperfudp( self ):
812 main.log.info(
813 self.name +
814 ": Simple iperf TCP test between two " +
815 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700816 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800817 response = self.execute(
818 cmd='iperfudp',
819 prompt='mininet>',
820 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800821 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800822 main.log.error( self.name + ": EOF exception found" )
823 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700824 main.cleanup()
825 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700826 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800827
Jon Hall7eb38402015-01-08 17:19:54 -0800828 def nodes( self ):
829 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700830 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800831 response = self.execute(
832 cmd='nodes',
833 prompt='mininet>',
834 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800835 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800836 main.log.error( self.name + ": EOF exception found" )
837 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700838 main.cleanup()
839 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700840 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800841
Jon Hall7eb38402015-01-08 17:19:54 -0800842 def pingpair( self ):
843 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700844 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800845 response = self.execute(
846 cmd='pingpair',
847 prompt='mininet>',
848 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800849 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800850 main.log.error( self.name + ": EOF exception found" )
851 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700852 main.cleanup()
853 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800854
Jon Hall7eb38402015-01-08 17:19:54 -0800855 if re.search( ',\s0\%\spacket\sloss', response ):
856 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800857 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700858 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800859 else:
860 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800861 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700862 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800863
Jon Hall7eb38402015-01-08 17:19:54 -0800864 def link( self, **linkargs ):
865 """
866 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800867 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800868 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
869 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
870 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
871 main.log.info(
872 "Bring link between '" +
873 end1 +
874 "' and '" +
875 end2 +
876 "' '" +
877 option +
878 "'" )
879 command = "link " + \
880 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -0700881 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800882 self.handle.sendline( command )
883 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800884 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800885 main.log.error( self.name + ": EOF exception found" )
886 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700887 main.cleanup()
888 main.exit()
adminbae64d82013-08-01 10:50:15 -0700889 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800890
Jon Hall7eb38402015-01-08 17:19:54 -0800891 def yank( self, **yankargs ):
892 """
893 yank a mininet switch interface to a host"""
894 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800895 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800896 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
897 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
898 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700899 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800900 response = self.execute(
901 cmd=command,
902 prompt="mininet>",
903 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800904 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800905 main.log.error( self.name + ": EOF exception found" )
906 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700907 main.cleanup()
908 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700909 return main.TRUE
910
Jon Hall7eb38402015-01-08 17:19:54 -0800911 def plug( self, **plugargs ):
912 """
913 plug the yanked mininet switch interface to a switch"""
914 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800915 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800916 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
917 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
918 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700919 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800920 response = self.execute(
921 cmd=command,
922 prompt="mininet>",
923 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800924 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800925 main.log.error( self.name + ": EOF exception found" )
926 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700927 main.cleanup()
928 main.exit()
adminbae64d82013-08-01 10:50:15 -0700929 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800930
Jon Hall7eb38402015-01-08 17:19:54 -0800931 def dpctl( self, **dpctlargs ):
932 """
933 Run dpctl command on all switches."""
934 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800935 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800936 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
937 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
938 command = "dpctl " + cmd + " " + str( cmdargs )
939 try:
940 response = self.execute(
941 cmd=command,
942 prompt="mininet>",
943 timeout=10 )
944 except pexpect.EOF:
945 main.log.error( self.name + ": EOF exception found" )
946 main.log.error( self.name + ": " + self.handle.before )
947 main.cleanup()
948 main.exit()
949 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800950
kelvin-onlabd3b64892015-01-20 13:26:24 -0800951 def getVersion( self ):
Jon Hallff6b4b22015-02-23 09:25:15 -0800952 #FIXME: What uses this? This should be refactored to get
953 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -0800954 fileInput = path + '/lib/Mininet/INSTALL'
955 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -0700956 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800957 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -0800958 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -0700959 if result:
Jon Hall7eb38402015-01-08 17:19:54 -0800960 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -0500961 return version
adminbae64d82013-08-01 10:50:15 -0700962
kelvin-onlabd3b64892015-01-20 13:26:24 -0800963 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -0800964 """
Jon Hallec3c21e2014-11-10 22:22:37 -0500965 Parameters:
966 sw: The name of an OVS switch. Example "s1"
967 Return:
Jon Hall7eb38402015-01-08 17:19:54 -0800968 The output of the command from the mininet cli
969 or main.FALSE on timeout"""
970 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -0700971 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800972 response = self.execute(
973 cmd=command,
974 prompt="mininet>",
975 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -0700976 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -0500977 return response
admin2a9548d2014-06-17 14:08:07 -0700978 else:
979 return main.FALSE
980 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800981 main.log.error( self.name + ": EOF exception found" )
982 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700983 main.cleanup()
984 main.exit()
adminbae64d82013-08-01 10:50:15 -0700985
kelvin-onlabd3b64892015-01-20 13:26:24 -0800986 def assignSwController( self, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -0800987 """
988 count is only needed if there is more than 1 controller"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800989 args = utilities.parse_args( [ "COUNT" ], **kwargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800990 count = args[ "COUNT" ] if args != {} else 1
Jon Hallf89c8552014-04-02 13:14:06 -0700991
992 argstring = "SW"
Jon Hall7eb38402015-01-08 17:19:54 -0800993 for j in range( count ):
994 argstring = argstring + ",IP" + \
995 str( j + 1 ) + ",PORT" + str( j + 1 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800996 args = utilities.parse_args( argstring.split( "," ), **kwargs )
Jon Hallf89c8552014-04-02 13:14:06 -0700997
Jon Hall7eb38402015-01-08 17:19:54 -0800998 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
999 ptcpA = int( args[ "PORT1" ] ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001000 int( sw ) if args[ "PORT1" ] is not None else ""
Jon Hall7eb38402015-01-08 17:19:54 -08001001 ptcpB = "ptcp:" + str( ptcpA ) if ptcpA != "" else ""
Jon Hallfbc828e2015-01-06 17:30:19 -08001002
Jon Hall7eb38402015-01-08 17:19:54 -08001003 command = "sh ovs-vsctl set-controller s" + \
1004 str( sw ) + " " + ptcpB + " "
1005 for j in range( count ):
1006 i = j + 1
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001007 args = utilities.parse_args(
Jon Hall7eb38402015-01-08 17:19:54 -08001008 [ "IP" + str( i ), "PORT" + str( i ) ], **kwargs )
1009 ip = args[
1010 "IP" +
1011 str( i ) ] if args[
1012 "IP" +
1013 str( i ) ] is not None else ""
1014 port = args[
1015 "PORT" +
1016 str( i ) ] if args[
1017 "PORT" +
1018 str( i ) ] is not None else ""
1019 tcp = "tcp:" + str( ip ) + ":" + str( port ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001020 " " if ip != "" else ""
Jon Hallf89c8552014-04-02 13:14:06 -07001021 command = command + tcp
Jon Hall6094a362014-04-11 14:46:56 -07001022 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001023 self.execute( cmd=command, prompt="mininet>", timeout=5 )
Jon Hall6094a362014-04-11 14:46:56 -07001024 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001025 main.log.error( self.name + ": EOF exception found" )
1026 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001027 main.cleanup()
1028 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001029 except Exception:
1030 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall6094a362014-04-11 14:46:56 -07001031 main.cleanup()
1032 main.exit()
adminbae64d82013-08-01 10:50:15 -07001033
kelvin-onlabd3b64892015-01-20 13:26:24 -08001034 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001035 """
1036 Removes the controller target from sw"""
1037 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001038 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001039 response = self.execute(
1040 cmd=command,
1041 prompt="mininet>",
1042 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001043 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001044 main.log.error( self.name + ": EOF exception found" )
1045 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001046 main.cleanup()
1047 main.exit()
1048 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001049 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001050
kelvin-onlabd3b64892015-01-20 13:26:24 -08001051 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001052 """
Jon Hallb1290e82014-11-18 16:17:48 -05001053 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001054 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001055 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001056 NOTE: cannot currently specify what type of switch
1057 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001058 sw = name of the new switch as a string
1059 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001060 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001061 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001062 """
1063 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001064 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001065 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001066 response = self.execute(
1067 cmd=command,
1068 prompt="mininet>",
1069 timeout=10 )
1070 if re.search( "already exists!", response ):
1071 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001072 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001073 elif re.search( "Error", response ):
1074 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001075 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001076 elif re.search( "usage:", response ):
1077 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001078 return main.FALSE
1079 else:
1080 return main.TRUE
1081 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001082 main.log.error( self.name + ": EOF exception found" )
1083 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001084 main.cleanup()
1085 main.exit()
1086
kelvin-onlabd3b64892015-01-20 13:26:24 -08001087 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001088 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001089 delete a switch from the mininet topology
1090 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001091 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001092 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001093 sw = name of the switch as a string
1094 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001095 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001096 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001097 response = self.execute(
1098 cmd=command,
1099 prompt="mininet>",
1100 timeout=10 )
1101 if re.search( "no switch named", response ):
1102 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001103 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001104 elif re.search( "Error", response ):
1105 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001106 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001107 elif re.search( "usage:", response ):
1108 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001109 return main.FALSE
1110 else:
1111 return main.TRUE
1112 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001113 main.log.error( self.name + ": EOF exception found" )
1114 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001115 main.cleanup()
1116 main.exit()
1117
kelvin-onlabd3b64892015-01-20 13:26:24 -08001118 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001119 """
1120 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001121 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001122 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001123 NOTE: cannot currently specify what type of link
1124 required params:
1125 node1 = the string node name of the first endpoint of the link
1126 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001127 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001128 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001129 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001130 response = self.execute(
1131 cmd=command,
1132 prompt="mininet>",
1133 timeout=10 )
1134 if re.search( "doesnt exist!", response ):
1135 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001136 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001137 elif re.search( "Error", response ):
1138 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001139 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001140 elif re.search( "usage:", response ):
1141 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001142 return main.FALSE
1143 else:
1144 return main.TRUE
1145 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001146 main.log.error( self.name + ": EOF exception found" )
1147 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001148 main.cleanup()
1149 main.exit()
1150
kelvin-onlabd3b64892015-01-20 13:26:24 -08001151 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001152 """
1153 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001154 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001155 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001156 required params:
1157 node1 = the string node name of the first endpoint of the link
1158 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001159 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001160 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001161 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001162 response = self.execute(
1163 cmd=command,
1164 prompt="mininet>",
1165 timeout=10 )
1166 if re.search( "no node named", response ):
1167 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001168 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001169 elif re.search( "Error", 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( "usage:", response ):
1173 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001174 return main.FALSE
1175 else:
1176 return main.TRUE
1177 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001178 main.log.error( self.name + ": EOF exception found" )
1179 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001180 main.cleanup()
1181 main.exit()
1182
kelvin-onlabd3b64892015-01-20 13:26:24 -08001183 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001184 """
Jon Hallb1290e82014-11-18 16:17:48 -05001185 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001186 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001187 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001188 NOTE: cannot currently specify what type of host
1189 required params:
1190 hostname = the string hostname
1191 optional key-value params
1192 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001193 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001194 """
1195 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001196 command = "addhost " + str( hostname ) + " " + str( switch )
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( "already exists!", 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( "doesnt exists!", 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( "Error", response ):
1209 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001210 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001211 elif re.search( "usage:", response ):
1212 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001213 return main.FALSE
1214 else:
1215 return main.TRUE
1216 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001217 main.log.error( self.name + ": EOF exception found" )
1218 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001219 main.cleanup()
1220 main.exit()
1221
kelvin-onlabd3b64892015-01-20 13:26:24 -08001222 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001223 """
1224 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001225 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001226 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001227 NOTE: this uses a custom mn function
1228 required params:
1229 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001230 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001231 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001232 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001233 response = self.execute(
1234 cmd=command,
1235 prompt="mininet>",
1236 timeout=10 )
1237 if re.search( "no host named", 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( "Error", response ):
1241 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001242 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001243 elif re.search( "usage:", response ):
1244 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001245 return main.FALSE
1246 else:
1247 return main.TRUE
1248 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001249 main.log.error( self.name + ": EOF exception found" )
1250 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001251 main.cleanup()
1252 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001253
Jon Hall7eb38402015-01-08 17:19:54 -08001254 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001255 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001256 Called at the end of the test to stop the mininet and
1257 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001258 """
1259 self.handle.sendline('')
Jon Halld61331b2015-02-17 16:35:47 -08001260 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Hallefbd9792015-03-05 16:11:36 -08001261 timeout=2)
kelvin-onlaba1484582015-02-02 15:46:20 -08001262 if i == 0:
1263 self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001264 elif i == 1:
1265 return main.TRUE
1266 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001267 # print "Disconnecting Mininet"
1268 if self.handle:
1269 self.handle.sendline( "exit" )
1270 self.handle.expect( "exit" )
1271 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001272 else:
1273 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001274 return response
1275
Hari Krishnab35c6d02015-03-18 11:13:51 -07001276 def stopNet( self, fileName = "", timeout=5):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001277 """
Jon Hall21270ac2015-02-16 17:59:55 -08001278 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001279 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001280 main.FALSE if the pexpect handle does not exist.
1281
Jon Halld61331b2015-02-17 16:35:47 -08001282 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001283 """
Jon Hall21270ac2015-02-16 17:59:55 -08001284
Jon Halld61331b2015-02-17 16:35:47 -08001285 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001286 response = ''
1287 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001288 try:
kelvin-onlab26bc17f2015-02-06 14:08:59 -08001289 self.handle.sendline("")
kelvin-onlab56a3f462015-02-06 14:04:43 -08001290 i = self.handle.expect( [ 'mininet>',
1291 '\$',
1292 pexpect.EOF,
1293 pexpect.TIMEOUT ],
1294 timeout )
1295 if i == 0:
1296 main.log.info( "Exiting mininet..." )
1297
Jon Hall7eb38402015-01-08 17:19:54 -08001298 response = self.execute(
1299 cmd="exit",
1300 prompt="(.*)",
1301 timeout=120 )
Jon Halld61331b2015-02-17 16:35:47 -08001302 main.log.info( self.name + ": Stopped")
Jon Hall7eb38402015-01-08 17:19:54 -08001303 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001304 response = main.TRUE
Hari Krishnab35c6d02015-03-18 11:13:51 -07001305
kelvin-onlab56a3f462015-02-06 14:04:43 -08001306 if i == 1:
1307 main.log.info( " Mininet trying to exit while not " +
1308 "in the mininet prompt" )
1309 elif i == 2:
1310 main.log.error( "Something went wrong exiting mininet" )
1311 elif i == 3: # timeout
1312 main.log.error( "Something went wrong exiting mininet " +
1313 "TIMEOUT" )
1314
Hari Krishnab35c6d02015-03-18 11:13:51 -07001315 if fileName:
1316 self.handle.sendline("")
1317 self.handle.expect('\$')
1318 self.handle.sendline("sudo kill -9 \`ps -ef | grep \""+ fileName +"\" | grep -v grep | awk '{print $2}'\`")
Jon Hallfbc828e2015-01-06 17:30:19 -08001319 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001320 main.log.error( self.name + ": EOF exception found" )
1321 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001322 main.cleanup()
1323 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001324 else:
1325 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001326 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001327 return response
1328
Jon Hall7eb38402015-01-08 17:19:54 -08001329 def arping( self, src, dest, destmac ):
1330 self.handle.sendline( '' )
1331 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001332
Jon Hall7eb38402015-01-08 17:19:54 -08001333 self.handle.sendline( src + ' arping ' + dest )
admin07529932013-11-22 14:58:28 -08001334 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001335 self.handle.expect( [ destmac, pexpect.EOF, pexpect.TIMEOUT ] )
1336 main.log.info( self.name + ": ARP successful" )
1337 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001338 return main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -08001339 except Exception:
Jon Hall7eb38402015-01-08 17:19:54 -08001340 main.log.warn( self.name + ": ARP FAILURE" )
1341 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001342 return main.FALSE
1343
Jon Hall7eb38402015-01-08 17:19:54 -08001344 def decToHex( self, num ):
1345 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001346
Jon Hall7eb38402015-01-08 17:19:54 -08001347 def getSwitchFlowCount( self, switch ):
1348 """
1349 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001350 if self.handle:
1351 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1352 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001353 response = self.execute(
1354 cmd=cmd,
1355 prompt="mininet>",
1356 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001357 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001358 main.log.error( self.name + ": EOF exception found" )
1359 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001360 main.cleanup()
1361 main.exit()
1362 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001363 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001364 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001365 main.log.info(
1366 "Couldn't find flows on switch %s, found: %s" %
1367 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001368 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001369 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001370 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001371 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001372
kelvin-onlabd3b64892015-01-20 13:26:24 -08001373 def checkFlows( self, sw, dumpFormat=None ):
1374 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001375 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001376 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001377 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001378 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001379 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001380 response = self.execute(
1381 cmd=command,
1382 prompt="mininet>",
1383 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001384 return response
1385 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001386 main.log.error( self.name + ": EOF exception found" )
1387 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001388 main.cleanup()
1389 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001390
kelvin-onlabd3b64892015-01-20 13:26:24 -08001391 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001392 """
Jon Hallefbd9792015-03-05 16:11:36 -08001393 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001394 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001395 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001396 self.handle.sendline( "" )
1397 self.handle.expect( "mininet>" )
1398 self.handle.sendline(
1399 "sh sudo tcpdump -n -i " +
1400 intf +
1401 " " +
1402 port +
1403 " -w " +
1404 filename.strip() +
1405 " &" )
1406 self.handle.sendline( "" )
1407 i = self.handle.expect( [ 'No\ssuch\device',
1408 'listening\son',
1409 pexpect.TIMEOUT,
1410 "mininet>" ],
1411 timeout=10 )
1412 main.log.warn( self.handle.before + self.handle.after )
1413 self.handle.sendline( "" )
1414 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001415 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001416 main.log.error(
1417 self.name +
1418 ": tcpdump - No such device exists. " +
1419 "tcpdump attempted on: " +
1420 intf )
admin2a9548d2014-06-17 14:08:07 -07001421 return main.FALSE
1422 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001423 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001424 return main.TRUE
1425 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001426 main.log.error(
1427 self.name +
1428 ": tcpdump command timed out! Check interface name," +
1429 " given interface was: " +
1430 intf )
admin2a9548d2014-06-17 14:08:07 -07001431 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001432 elif i == 3:
1433 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001434 return main.TRUE
1435 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001436 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001437 return main.FALSE
1438 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001439 main.log.error( self.name + ": EOF exception found" )
1440 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001441 main.cleanup()
1442 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001443 except Exception:
1444 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001445 main.cleanup()
1446 main.exit()
1447
kelvin-onlabd3b64892015-01-20 13:26:24 -08001448 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001449 """
1450 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001451 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001452 self.handle.sendline( "sh sudo pkill tcpdump" )
1453 self.handle.expect( "mininet>" )
1454 self.handle.sendline( "" )
1455 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001456 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001457 main.log.error( self.name + ": EOF exception found" )
1458 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001459 main.cleanup()
1460 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001461 except Exception:
1462 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001463 main.cleanup()
1464 main.exit()
1465
kelvin-onlabd3b64892015-01-20 13:26:24 -08001466 def compareSwitches( self, topo, switchesJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001467 """
1468 Compare mn and onos switches
1469 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001470 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001471
Jon Hall7eb38402015-01-08 17:19:54 -08001472 This uses the sts TestONTopology object"""
kelvin-onlabd3b64892015-01-20 13:26:24 -08001473 # main.log.debug( "Switches_json string: ", switchesJson )
Jon Hall7eb38402015-01-08 17:19:54 -08001474 output = { "switches": [] }
1475 # iterate through the MN topology and pull out switches and and port
1476 # info
1477 for switch in topo.graph.switches:
Jon Hall3d87d502014-10-17 18:37:42 -04001478 ports = []
1479 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001480 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001481 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001482 'name': port.name } )
1483 output[ 'switches' ].append( {
1484 "name": switch.name,
1485 "dpid": str( switch.dpid ).zfill( 16 ),
1486 "ports": ports } )
Jon Hall3d87d502014-10-17 18:37:42 -04001487
Jon Hall7eb38402015-01-08 17:19:54 -08001488 # print "mn"
1489 # print json.dumps( output,
Jon Hallff6b4b22015-02-23 09:25:15 -08001490 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001491 # indent=4,
1492 # separators=( ',', ': ' ) )
1493 # print "onos"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001494 # print json.dumps( switchesJson,
Jon Hallff6b4b22015-02-23 09:25:15 -08001495 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001496 # indent=4,
1497 # separators=( ',', ': ' ) )
Jon Hall3d87d502014-10-17 18:37:42 -04001498
1499 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001500 mnDPIDs = []
1501 for switch in output[ 'switches' ]:
1502 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001503 mnDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001504 # print "List of Mininet switch DPID's"
1505 # print mnDPIDs
kelvin-onlabd3b64892015-01-20 13:26:24 -08001506 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001507 main.log.error(
1508 self.name +
1509 ".compare_switches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001510 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001511 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001512 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001513 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001514 if switch[ 'available' ]:
1515 onosDPIDs.append(
1516 switch[ 'id' ].replace(
1517 ":",
1518 '' ).replace(
1519 "of",
1520 '' ).lower() )
1521 # else:
1522 # print "Switch is unavailable:"
1523 # print switch
Jon Hall3d87d502014-10-17 18:37:42 -04001524 onosDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001525 # print "List of ONOS switch DPID's"
1526 # print onosDPIDs
Jon Hall3d87d502014-10-17 18:37:42 -04001527
Jon Hall7eb38402015-01-08 17:19:54 -08001528 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001529 switchResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001530 main.log.report( "Switches in MN but not in ONOS:" )
1531 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
1532 main.log.report( str( list1 ) )
1533 main.log.report( "Switches in ONOS but not in MN:" )
1534 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
kelvin-onlabedcff052015-01-16 12:53:55 -08001535 main.log.report( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001536 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001537 switchResults = main.TRUE
1538 return switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001539
kelvin-onlabd3b64892015-01-20 13:26:24 -08001540 def comparePorts( self, topo, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001541 """
Jon Hall72cf1dc2014-10-20 21:04:50 -04001542 Compare mn and onos ports
1543 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001544 portsJson: parsed json object from the onos ports api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001545
Jon Hallfbc828e2015-01-06 17:30:19 -08001546 Dependencies:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001547 1. This uses the sts TestONTopology object
1548 2. numpy - "sudo pip install numpy"
1549
Jon Hall7eb38402015-01-08 17:19:54 -08001550 """
1551 # FIXME: this does not look for extra ports in ONOS, only checks that
1552 # ONOS has what is in MN
Jon Hall72cf1dc2014-10-20 21:04:50 -04001553 from numpy import uint64
kelvin-onlabd3b64892015-01-20 13:26:24 -08001554 portsResults = main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001555 output = { "switches": [] }
1556 # iterate through the MN topology and pull out switches and and port
1557 # info
1558 for switch in topo.graph.switches:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001559 ports = []
1560 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001561 # print port.hw_addr.toStr( separator='' )
Jon Hallefbd9792015-03-05 16:11:36 -08001562 tmpPort = { 'of_port': port.port_no,
1563 'mac': str( port.hw_addr ).replace( '\'', '' ),
1564 'name': port.name,
1565 'enabled': port.enabled }
Jon Hall39f29df2014-11-04 19:30:21 -05001566
kelvin-onlabd3b64892015-01-20 13:26:24 -08001567 ports.append( tmpPort )
Jon Hallefbd9792015-03-05 16:11:36 -08001568 tmpSwitch = { 'name': switch.name,
1569 'dpid': str( switch.dpid ).zfill( 16 ),
1570 'ports': ports }
Jon Hall39f29df2014-11-04 19:30:21 -05001571
kelvin-onlabd3b64892015-01-20 13:26:24 -08001572 output[ 'switches' ].append( tmpSwitch )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001573
Jon Hall7eb38402015-01-08 17:19:54 -08001574 # PORTS
kelvin-onlabd3b64892015-01-20 13:26:24 -08001575 for mnSwitch in output[ 'switches' ]:
1576 mnPorts = []
1577 onosPorts = []
1578 switchResult = main.TRUE
1579 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001580 if port[ 'enabled' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001581 mnPorts.append( port[ 'of_port' ] )
1582 for onosSwitch in portsJson:
Jon Hall7eb38402015-01-08 17:19:54 -08001583 # print "Iterating through a new switch as seen by ONOS"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001584 # print onosSwitch
1585 if onosSwitch[ 'device' ][ 'available' ]:
1586 if onosSwitch[ 'device' ][ 'id' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001587 ':',
1588 '' ).replace(
1589 "of",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001590 '' ) == mnSwitch[ 'dpid' ]:
1591 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001592 if port[ 'isEnabled' ]:
1593 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001594 # onosPorts.append( 'local' )
1595 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001596 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001597 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001598 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001599 mnPorts.sort( key=float )
1600 onosPorts.sort( key=float )
1601 # print "\nPorts for Switch %s:" % ( mnSwitch[ 'name' ] )
1602 # print "\tmn_ports[] = ", mnPorts
1603 # print "\tonos_ports[] = ", onosPorts
1604 mnPortsLog = mnPorts
1605 onosPortsLog = onosPorts
1606 mnPorts = [ x for x in mnPorts ]
1607 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001608
Jon Hall7eb38402015-01-08 17:19:54 -08001609 # TODO: handle other reserved port numbers besides LOCAL
1610 # NOTE: Reserved ports
1611 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1612 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001613 for mnPort in mnPortsLog:
1614 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001615 # don't set results to true here as this is just one of
1616 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001617 mnPorts.remove( mnPort )
1618 onosPorts.remove( mnPort )
Jon Hall7eb38402015-01-08 17:19:54 -08001619 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001620 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001621 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001622 if 65534 in mnPorts:
1623 mnPorts.remove( 65534 )
1624 if long( uint64( -2 ) ) in onosPorts:
1625 onosPorts.remove( long( uint64( -2 ) ) )
1626 if len( mnPorts ): # the ports of this switch don't match
1627 switchResult = main.FALSE
1628 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1629 if len( onosPorts ): # the ports of this switch don't match
1630 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001631 main.log.warn(
1632 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001633 str( onosPorts ) )
1634 if switchResult == main.FALSE:
Jon Hall7eb38402015-01-08 17:19:54 -08001635 main.log.report(
1636 "The list of ports for switch %s(%s) does not match:" %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001637 ( mnSwitch[ 'name' ], mnSwitch[ 'dpid' ] ) )
1638 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1639 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1640 portsResults = portsResults and switchResult
1641 return portsResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001642
kelvin-onlabd3b64892015-01-20 13:26:24 -08001643 def compareLinks( self, topo, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001644 """
1645 Compare mn and onos links
1646 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001647 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001648
Jon Hall7eb38402015-01-08 17:19:54 -08001649 This uses the sts TestONTopology object"""
1650 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08001651 # ONOS has what is in MN
Jon Hall7eb38402015-01-08 17:19:54 -08001652 output = { "switches": [] }
kelvin-onlabd3b64892015-01-20 13:26:24 -08001653 onos = linksJson
Jon Hall7eb38402015-01-08 17:19:54 -08001654 # iterate through the MN topology and pull out switches and and port
1655 # info
1656 for switch in topo.graph.switches:
Jon Hall38481722014-11-04 16:50:05 -05001657 # print "Iterating though switches as seen by Mininet"
1658 # print switch
Jon Hall72cf1dc2014-10-20 21:04:50 -04001659 ports = []
1660 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001661 # print port.hw_addr.toStr( separator='' )
1662 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001663 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001664 'name': port.name } )
1665 output[ 'switches' ].append( {
1666 "name": switch.name,
1667 "dpid": str( switch.dpid ).zfill( 16 ),
1668 "ports": ports } )
1669 # LINKS
Jon Hall72cf1dc2014-10-20 21:04:50 -04001670
kelvin-onlabd3b64892015-01-20 13:26:24 -08001671 mnLinks = [
kelvin-onlab9592d132015-01-20 17:18:02 -08001672 link for link in topo.patch_panel.network_links if (
Jon Hall7eb38402015-01-08 17:19:54 -08001673 link.port1.enabled and link.port2.enabled ) ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08001674 if 2 * len( mnLinks ) == len( onos ):
1675 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001676 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001677 linkResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001678 main.log.report(
Jon Hall328ddca2015-01-28 15:57:15 -08001679 "Mininet has " + str( len( mnLinks ) ) +
1680 " bidirectional links and ONOS has " +
1681 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001682
Jon Hall7eb38402015-01-08 17:19:54 -08001683 # iterate through MN links and check if an ONOS link exists in
1684 # both directions
1685 # NOTE: Will currently only show mn links as down if they are
1686 # cut through STS. We can either do everything through STS or
kelvin-onlabd3b64892015-01-20 13:26:24 -08001687 # wait for upNetworkLinks and downNetworkLinks to be
Jon Hall7eb38402015-01-08 17:19:54 -08001688 # fully implemented.
kelvin-onlabd3b64892015-01-20 13:26:24 -08001689 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08001690 # print "Link: %s" % link
1691 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04001692 node1 = None
1693 port1 = None
1694 node2 = None
1695 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08001696 firstDir = main.FALSE
1697 secondDir = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001698 for switch in output[ 'switches' ]:
1699 # print "Switch: %s" % switch[ 'name' ]
1700 if switch[ 'name' ] == link.node1.name:
1701 node1 = switch[ 'dpid' ]
1702 for port in switch[ 'ports' ]:
1703 if str( port[ 'name' ] ) == str( link.port1 ):
1704 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001705 if node1 is not None and node2 is not None:
1706 break
Jon Hall7eb38402015-01-08 17:19:54 -08001707 if switch[ 'name' ] == link.node2.name:
1708 node2 = switch[ 'dpid' ]
1709 for port in switch[ 'ports' ]:
1710 if str( port[ 'name' ] ) == str( link.port2 ):
1711 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001712 if node1 is not None and node2 is not None:
1713 break
1714
kelvin-onlabd3b64892015-01-20 13:26:24 -08001715 for onosLink in onos:
1716 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001717 ":",
1718 '' ).replace(
1719 "of",
1720 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001721 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001722 ":",
1723 '' ).replace(
1724 "of",
1725 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001726 onosPort1 = onosLink[ 'src' ][ 'port' ]
1727 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001728
Jon Hall72cf1dc2014-10-20 21:04:50 -04001729 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08001730 if str( onosNode1 ) == str( node1 ) and str(
1731 onosNode2 ) == str( node2 ):
1732 if int( onosPort1 ) == int( port1 ) and int(
1733 onosPort2 ) == int( port2 ):
1734 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001735 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001736 main.log.warn(
1737 'The port numbers do not match for ' +
1738 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001739 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001740 'link %s/%s -> %s/%s' %
1741 ( node1,
1742 port1,
1743 node2,
1744 port2 ) +
1745 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001746 ( onosNode1,
1747 onosPort1,
1748 onosNode2,
1749 onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001750
1751 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08001752 elif ( str( onosNode1 ) == str( node2 ) and
1753 str( onosNode2 ) == str( node1 ) ):
1754 if ( int( onosPort1 ) == int( port2 )
1755 and int( onosPort2 ) == int( port1 ) ):
1756 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001757 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001758 main.log.warn(
1759 'The port numbers do not match for ' +
1760 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001761 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001762 'link %s/%s -> %s/%s' %
1763 ( node2,
1764 port2,
1765 node1,
1766 port1 ) +
1767 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001768 ( onosNode2,
1769 onosPort2,
1770 onosNode1,
1771 onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001772 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04001773 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08001774 if not firstDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001775 main.log.report(
1776 'ONOS does not have the link %s/%s -> %s/%s' %
1777 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001778 if not secondDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001779 main.log.report(
1780 'ONOS does not have the link %s/%s -> %s/%s' %
1781 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001782 linkResults = linkResults and firstDir and secondDir
1783 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001784
Jon Hallff6b4b22015-02-23 09:25:15 -08001785 def compareHosts( self, topo, hostsJson ):
1786 """
1787 Compare mn and onos Hosts.
1788 Since Mininet hosts are quiet, ONOS will only know of them when they
1789 speak. For this reason, we will only check that the hosts in ONOS
1790 stores are in Mininet, and not vice versa.
1791 topo: sts TestONTopology object
1792 hostsJson: parsed json object from the onos hosts api
1793
1794 This uses the sts TestONTopology object"""
1795 import json
1796 hostResults = main.TRUE
1797 hosts = []
1798 # iterate through the MN topology and pull out hosts
1799 for mnHost in topo.graph.hosts:
1800 interfaces = []
1801 for intf in mnHost.interfaces:
1802 interfaces.append( {
1803 "name": intf.name, # str
1804 "ips": [ str( ip ) for ip in intf.ips ], # list of IPAddrs
1805 # hw_addr is of type EthAddr, Not JSON serializable
1806 "hw_addr": str( intf.hw_addr ) } )
1807 hosts.append( {
1808 "name": mnHost.name, # str
1809 "interfaces": interfaces } ) # list
1810 for onosHost in hostsJson:
1811 onosMAC = onosHost[ 'mac' ].lower()
1812 match = False
1813 for mnHost in hosts:
1814 for mnIntf in mnHost[ 'interfaces' ]:
1815 if onosMAC == mnIntf[ 'hw_addr' ].lower() :
1816 match = True
1817 for ip in mnIntf[ 'ips' ]:
1818 if ip in onosHost[ 'ips' ]:
1819 pass # all is well
1820 else:
1821 # misssing ip
1822 main.log.error( "ONOS host " + onosHost[ 'id' ]
1823 + " has a different IP than " +
1824 "the Mininet host." )
1825 output = json.dumps(
1826 onosHost,
1827 sort_keys=True,
1828 indent=4,
1829 separators=( ',', ': ' ) )
1830 main.log.info( output )
1831 hostResults = main.FALSE
1832 if not match:
1833 hostResults = main.FALSE
1834 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
1835 "corresponding Mininet host." )
1836 output = json.dumps( onosHost,
1837 sort_keys=True,
1838 indent=4,
1839 separators=( ',', ': ' ) )
1840 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08001841 return hostResults
1842
kelvin-onlabd3b64892015-01-20 13:26:24 -08001843 def getHosts( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08001844 """
1845 Returns a list of all hosts
1846 Don't ask questions just use it"""
1847 self.handle.sendline( "" )
1848 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001849
Jon Hall7eb38402015-01-08 17:19:54 -08001850 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
1851 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001852
kelvin-onlabd3b64892015-01-20 13:26:24 -08001853 handlePy = self.handle.before
1854 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
1855 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07001856
Jon Hall7eb38402015-01-08 17:19:54 -08001857 self.handle.sendline( "" )
1858 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001859
kelvin-onlabd3b64892015-01-20 13:26:24 -08001860 hostStr = handlePy.replace( "]", "" )
1861 hostStr = hostStr.replace( "'", "" )
1862 hostStr = hostStr.replace( "[", "" )
1863 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001864
kelvin-onlabd3b64892015-01-20 13:26:24 -08001865 return hostList
adminbae64d82013-08-01 10:50:15 -07001866
Jon Hall7eb38402015-01-08 17:19:54 -08001867 def update( self ):
1868 """
1869 updates the port address and status information for
1870 each port in mn"""
1871 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08001872 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05001873 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001874 self.handle.sendline( "" )
1875 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001876
Jon Hall7eb38402015-01-08 17:19:54 -08001877 self.handle.sendline( "update" )
1878 self.handle.expect( "update" )
1879 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001880
Jon Hall7eb38402015-01-08 17:19:54 -08001881 self.handle.sendline( "" )
1882 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001883
Jon Hallb1290e82014-11-18 16:17:48 -05001884 return main.TRUE
1885 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001886 main.log.error( self.name + ": EOF exception found" )
1887 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001888 main.cleanup()
1889 main.exit()
1890
adminbae64d82013-08-01 10:50:15 -07001891if __name__ != "__main__":
1892 import sys
Jon Hall7eb38402015-01-08 17:19:54 -08001893 sys.modules[ __name__ ] = MininetCliDriver()