blob: 2d7c0a57aeb0bda0dfbfae2453506869b2fff5bb [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
Jon Hallbe6dfc42015-01-12 17:37:25 -08005author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
Jon Hall7eb38402015-01-08 17:19:54 -08008TestON is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 2 of the License, or
11( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
Jon Hall7eb38402015-01-08 17:19:54 -080013TestON is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070017
Jon Hall7eb38402015-01-08 17:19:54 -080018You should have received a copy of the GNU General Public License
19along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
21
Jon Hallbe6dfc42015-01-12 17:37:25 -080022MininetCliDriver is the basic driver which will handle the Mininet functions
23
Jon Hall272a4db2015-01-12 17:43:48 -080024Some functions rely on STS module. To install this,
25 git clone https://github.com/jhall11/sts.git
26
Jon Hallbe6dfc42015-01-12 17:37:25 -080027Some functions rely on a modified version of Mininet. These functions
28should all be noted in the comments. To get this MN version run these commands
29from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080030 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080032 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080033 git pull
34
Jon Hall272a4db2015-01-12 17:43:48 -080035
36 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080037changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070038import pexpect
adminbae64d82013-08-01 10:50:15 -070039import re
40import sys
Jon Hall7eb38402015-01-08 17:19:54 -080041sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070044
Jon Hall7eb38402015-01-08 17:19:54 -080045
kelvin-onlab50907142015-04-01 13:37:45 -070046class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080047
48 """
49 MininetCliDriver is the basic driver which will handle
50 the Mininet functions"""
51 def __init__( self ):
52 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070053 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080054 self.name = None
Jon Hall7eb38402015-01-08 17:19:54 -080055 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070056 self.flag = 0
57
Jon Hall7eb38402015-01-08 17:19:54 -080058 def connect( self, **connectargs ):
59 """
60 Here the main is the TestON instance after creating
61 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080062 try:
63 for key in connectargs:
64 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080065
kelvin-onlaba1484582015-02-02 15:46:20 -080066 self.name = self.options[ 'name' ]
67 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070068 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080069 self ).connect(
70 user_name=self.user_name,
71 ip_address=self.ip_address,
72 port=None,
73 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080074
kelvin-onlaba1484582015-02-02 15:46:20 -080075 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080076 main.log.info( "Connection successful to the host " +
77 self.user_name +
78 "@" +
79 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080080 return main.TRUE
81 else:
82 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080083 self.user_name +
84 "@" +
85 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -080086 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -080087 return main.FALSE
88 except pexpect.EOF:
89 main.log.error( self.name + ": EOF exception found" )
90 main.log.error( self.name + ": " + self.handle.before )
91 main.cleanup()
92 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -080093 except Exception:
94 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -080095 main.cleanup()
96 main.exit()
97
Jon Hallefbd9792015-03-05 16:11:36 -080098 def startNet( self, topoFile='', args='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -080099 """
100 Starts Mininet accepts a topology(.py) file and/or an optional
Jon Hallefbd9792015-03-05 16:11:36 -0800101 argument ,to start the mininet, as a parameter.
Jon Hall21270ac2015-02-16 17:59:55 -0800102 Returns main.TRUE if the mininet starts successfully and
103 main.FALSE otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800104 """
Jon Hall7eb38402015-01-08 17:19:54 -0800105 if self.handle:
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
kelvin-onlabc44f0192015-04-02 22:08:41 -0700249 def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0):
Jon Hall7eb38402015-01-08 17:19:54 -0800250 """
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
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700254 Optional:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700255 timeout(seconds) - This is the pexpect timeout; The function will
256 timeout if the amount of time between failed
257 pings exceedes this time and pingall is still
258 running
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700259 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700260 ping
261 acceptableFailed - Set the number of acceptable failed pings for the
262 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800263 Returns:
264 main.TRUE if pingall completes with no pings dropped
265 otherwise main.FALSE"""
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700266 try:
267 if self.handle:
268 main.log.info(
269 self.name +
270 ": Checking reachabilty to the hosts using pingall" )
271 response = ""
272 failedPings = 0
273 returnValue = main.TRUE
274 self.handle.sendline( "pingall" )
275 while True:
276 i = self.handle.expect( [ "mininet>","X",
277 pexpect.EOF,
278 pexpect.TIMEOUT ],
279 timeout )
280 if i == 0:
281 main.log.info( self.name + ": pingall finished")
282 response += self.handle.before
283 break
284 elif i == 1:
285 response += self.handle.before + self.handle.after
286 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700287 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700288 returnValue = main.FALSE
289 if shortCircuit:
290 main.log.error( self.name +
291 ": Aborting pingall - "
292 + str( failedPings ) +
293 " pings failed" )
294 break
295 elif i == 2:
296 main.log.error( self.name +
297 ": EOF exception found" )
298 main.log.error( self.name + ": " +
299 self.handle.before )
300 main.cleanup()
301 main.exit()
302 elif i == 3:
303 response += self.handle.before
304 main.log.error( self.name +
305 ": TIMEOUT exception found" )
306 main.log.error( self.name +
307 ": " +
308 str( response ) )
309 # NOTE: Send ctrl-c to make sure pingall is done
310 self.handle.sendline( "\x03" )
311 self.handle.expect( "Interrupt" )
312 self.handle.expect( "mininet>" )
313 break
314 pattern = "Results\:"
315 main.log.info( "Pingall output: " + str( response ) )
316 if re.search( pattern, response ):
317 main.log.info( self.name + ": Pingall finished with "
318 + str( failedPings ) + " failed pings" )
319 return returnValue
320 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700321 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700322 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700323 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700324 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700325 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700326 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700327 main.log.error( self.name + ": Connection failed to the host" )
328 main.cleanup()
329 main.exit()
330 except pexpect.TIMEOUT:
331 if response:
332 main.log.info( "Pingall output: " + str( response ) )
333 main.log.error( self.name + ": pexpect.TIMEOUT found" )
334 return main.FALSE
335 except pexpect.EOF:
336 main.log.error( self.name + ": EOF exception found" )
337 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500338 main.cleanup()
339 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700340
Jon Hall7eb38402015-01-08 17:19:54 -0800341 def fpingHost( self, **pingParams ):
342 """
343 Uses the fping package for faster pinging...
344 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800345 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800346 command = args[ "SRC" ] + \
347 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
348 self.handle.sendline( command )
349 self.handle.expect(
350 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
351 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
352 response = self.handle.before
353 if re.search( ":\s-", response ):
354 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700355 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800356 elif re.search( ":\s\d{1,2}\.\d\d", response ):
357 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700358 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800359 main.log.info( self.name + ": Install fping on mininet machine... " )
360 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700361 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800362
Jon Hall7eb38402015-01-08 17:19:54 -0800363 def pingHost( self, **pingParams ):
364 """
365 Ping from one mininet host to another
366 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800367 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800368 command = args[ "SRC" ] + " ping " + \
369 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700370 try:
Jon Hall61282e32015-03-19 11:34:11 -0700371 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800372 self.handle.sendline( command )
373 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700374 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800375 main.log.error(
376 self.name +
377 ": timeout when waiting for response from mininet" )
378 main.log.error( "response: " + str( self.handle.before ) )
379 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700380 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800381 main.log.error(
382 self.name +
383 ": timeout when waiting for response from mininet" )
384 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700385 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800386 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800387 main.log.error( self.name + ": EOF exception found" )
388 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700389 main.cleanup()
390 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800391 main.log.info( self.name + ": Ping Response: " + response )
392 if re.search( ',\s0\%\spacket\sloss', response ):
393 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800394 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700395 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800396 else:
397 main.log.error(
398 self.name +
399 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800400 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700401 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800402
Jon Hall7eb38402015-01-08 17:19:54 -0800403 def checkIP( self, host ):
404 """
405 Verifies the host's ip configured or not."""
406 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700407 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800408 response = self.execute(
409 cmd=host +
410 " ifconfig",
411 prompt="mininet>",
412 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800413 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800414 main.log.error( self.name + ": EOF exception found" )
415 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700416 main.cleanup()
417 main.exit()
adminbae64d82013-08-01 10:50:15 -0700418
Jon Hall7eb38402015-01-08 17:19:54 -0800419 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800420 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
421 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
422 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
423 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
424 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800425 # pattern = "inet addr:10.0.0.6"
426 if re.search( pattern, response ):
427 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700428 return main.TRUE
429 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800430 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700431 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800432 else:
433 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800434
Jon Hall7eb38402015-01-08 17:19:54 -0800435 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800436 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700437 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800438 response = self.execute(
439 cmd="h1 /usr/sbin/sshd -D&",
440 prompt="mininet>",
441 timeout=10 )
442 response = self.execute(
443 cmd="h4 /usr/sbin/sshd -D&",
444 prompt="mininet>",
445 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700446 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800447 vars( self )[ key ] = connectargs[ key ]
448 response = self.execute(
449 cmd="xterm h1 h4 ",
450 prompt="mininet>",
451 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800452 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800453 main.log.error( self.name + ": EOF exception found" )
454 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700455 main.cleanup()
456 main.exit()
adminbae64d82013-08-01 10:50:15 -0700457 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800458 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700459 if self.flag == 0:
460 self.flag = 1
461 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800462 else:
adminbae64d82013-08-01 10:50:15 -0700463 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800464
kelvin-onlaba1484582015-02-02 15:46:20 -0800465 def moveHost( self, host, oldSw, newSw, ):
466 """
467 Moves a host from one switch to another on the fly
468 Note: The intf between host and oldSw when detached
469 using detach(), will still show up in the 'net'
470 cmd, because switch.detach() doesn't affect switch.intfs[]
471 (which is correct behavior since the interfaces
472 haven't moved).
473 """
474 if self.handle:
475 try:
476 # Bring link between oldSw-host down
Jon Hallefbd9792015-03-05 16:11:36 -0800477 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'"+ host +\
478 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800479 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800480 response = self.execute( cmd=cmd,
481 prompt="mininet>",
482 timeout=10 )
kelvin-onlaba1484582015-02-02 15:46:20 -0800483
484 # Determine hostintf and Oldswitchintf
485 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800486 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800487 print "cmd2= ", cmd
488 self.handle.sendline( cmd )
489 self.handle.expect( "mininet>" )
490
shahshreya73537862015-02-11 15:15:24 -0800491 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800492 cmd = "px ipaddr = hintf.IP()"
493 print "cmd3= ", cmd
494 self.handle.sendline( cmd )
495 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800496
497 cmd = "px macaddr = hintf.MAC()"
498 print "cmd3= ", cmd
499 self.handle.sendline( cmd )
500 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800501
502 # Detach interface between oldSw-host
503 cmd = "px " + oldSw + ".detach( sintf )"
504 print "cmd4= ", cmd
505 self.handle.sendline( cmd )
506 self.handle.expect( "mininet>" )
507
508 # Add link between host-newSw
509 cmd = "py net.addLink(" + host + "," + newSw + ")"
510 print "cmd5= ", cmd
511 self.handle.sendline( cmd )
512 self.handle.expect( "mininet>" )
513
514 # Determine hostintf and Newswitchintf
515 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800516 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800517 print "cmd6= ", cmd
518 self.handle.sendline( cmd )
519 self.handle.expect( "mininet>" )
520
521 # Attach interface between newSw-host
522 cmd = "px " + newSw + ".attach( sintf )"
523 print "cmd3= ", cmd
524 self.handle.sendline( cmd )
525 self.handle.expect( "mininet>" )
526
527 # Set ipaddress of the host-newSw interface
528 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
529 print "cmd7 = ", cmd
530 self.handle.sendline( cmd )
531 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800532
533 # Set macaddress of the host-newSw interface
534 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
535 print "cmd8 = ", cmd
536 self.handle.sendline( cmd )
537 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800538
539 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800540 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800541 self.handle.sendline( cmd )
542 self.handle.expect( "mininet>" )
543 print "output = ", self.handle.before
544
545 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800546 cmd = host + " ifconfig"
547 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800548 self.handle.sendline( cmd )
549 self.handle.expect( "mininet>" )
550 print "ifconfig o/p = ", self.handle.before
551
552 return main.TRUE
553 except pexpect.EOF:
554 main.log.error( self.name + ": EOF exception found" )
555 main.log.error( self.name + ": " + self.handle.before )
556 return main.FALSE
557
Jon Hall7eb38402015-01-08 17:19:54 -0800558 def changeIP( self, host, intf, newIP, newNetmask ):
559 """
560 Changes the ip address of a host on the fly
561 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800562 if self.handle:
563 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800564 cmd = host + " ifconfig " + intf + " " + \
565 newIP + " " + 'netmask' + " " + newNetmask
566 self.handle.sendline( cmd )
567 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800568 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800569 main.log.info( "response = " + response )
570 main.log.info(
571 "Ip of host " +
572 host +
573 " changed to new IP " +
574 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -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 )
shahshreyae6c7cf42014-11-26 16:39:01 -0800579 return main.FALSE
580
Jon Hall7eb38402015-01-08 17:19:54 -0800581 def changeDefaultGateway( self, host, newGW ):
582 """
583 Changes the default gateway of a host
584 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800585 if self.handle:
586 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800587 cmd = host + " route add default gw " + newGW
588 self.handle.sendline( cmd )
589 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800590 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800591 main.log.info( "response = " + response )
592 main.log.info(
593 "Default gateway of host " +
594 host +
595 " changed to " +
596 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800597 return main.TRUE
598 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800599 main.log.error( self.name + ": EOF exception found" )
600 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800601 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800602
Jon Hall7eb38402015-01-08 17:19:54 -0800603 def addStaticMACAddress( self, host, GW, macaddr ):
604 """
Jon Hallefbd9792015-03-05 16:11:36 -0800605 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800606 if self.handle:
607 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800608 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
609 cmd = host + " arp -s " + GW + " " + macaddr
610 self.handle.sendline( cmd )
611 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800612 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800613 main.log.info( "response = " + response )
614 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800615 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800616 GW +
617 " changed to " +
618 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800619 return main.TRUE
620 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800621 main.log.error( self.name + ": EOF exception found" )
622 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800623 return main.FALSE
624
Jon Hall7eb38402015-01-08 17:19:54 -0800625 def verifyStaticGWandMAC( self, host ):
626 """
627 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800628 if self.handle:
629 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800630 # h1 arp -an
631 cmd = host + " arp -an "
632 self.handle.sendline( cmd )
633 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800634 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800635 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800636 return main.TRUE
637 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800638 main.log.error( self.name + ": EOF exception found" )
639 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800640 return main.FALSE
641
Jon Hall7eb38402015-01-08 17:19:54 -0800642 def getMacAddress( self, host ):
643 """
644 Verifies the host's ip configured or not."""
645 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700646 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800647 response = self.execute(
648 cmd=host +
649 " ifconfig",
650 prompt="mininet>",
651 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800652 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800653 main.log.error( self.name + ": EOF exception found" )
654 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700655 main.cleanup()
656 main.exit()
adminbae64d82013-08-01 10:50:15 -0700657
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700658 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800659 macAddressSearch = re.search( pattern, response, re.I )
660 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800661 main.log.info(
662 self.name +
663 ": Mac-Address of Host " +
664 host +
665 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800666 macAddress )
667 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700668 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800669 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700670
Jon Hall7eb38402015-01-08 17:19:54 -0800671 def getInterfaceMACAddress( self, host, interface ):
672 """
673 Return the IP address of the interface on the given host"""
674 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700675 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800676 response = self.execute( cmd=host + " ifconfig " + interface,
677 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800678 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800679 main.log.error( self.name + ": EOF exception found" )
680 main.log.error( self.name + ": " + self.handle.before )
681 main.cleanup()
682 main.exit()
683
684 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800685 macAddressSearch = re.search( pattern, response, re.I )
686 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800687 main.log.info( "No mac address found in %s" % response )
688 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800689 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800690 main.log.info(
691 "Mac-Address of " +
692 host +
693 ":" +
694 interface +
695 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800696 macAddress )
697 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800698 else:
699 main.log.error( "Connection failed to the host" )
700
701 def getIPAddress( self, host ):
702 """
703 Verifies the host's ip configured or not."""
704 if self.handle:
705 try:
706 response = self.execute(
707 cmd=host +
708 " ifconfig",
709 prompt="mininet>",
710 timeout=10 )
711 except pexpect.EOF:
712 main.log.error( self.name + ": EOF exception found" )
713 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700714 main.cleanup()
715 main.exit()
adminbae64d82013-08-01 10:50:15 -0700716
717 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800718 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800719 main.log.info(
720 self.name +
721 ": IP-Address of Host " +
722 host +
723 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800724 ipAddressSearch.group( 1 ) )
725 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800726 else:
727 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800728
Jon Hall7eb38402015-01-08 17:19:54 -0800729 def getSwitchDPID( self, switch ):
730 """
731 return the datapath ID of the switch"""
732 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700733 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700734 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800735 response = self.execute(
736 cmd=cmd,
737 prompt="mininet>",
738 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800739 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800740 main.log.error( self.name + ": EOF exception found" )
741 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700742 main.cleanup()
743 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800744 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800745 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700746 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800747 main.log.info(
748 "Couldn't find DPID for switch %s, found: %s" %
749 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700750 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800751 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700752 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800753 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700754
Jon Hall7eb38402015-01-08 17:19:54 -0800755 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700756 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800757 self.handle.sendline( "" )
758 self.expect( "mininet>" )
759 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700760 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800761 response = self.execute(
762 cmd=cmd,
763 prompt="mininet>",
764 timeout=10 )
765 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700766 response = self.handle.before
767 return response
768 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800769 main.log.error( self.name + ": EOF exception found" )
770 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700771 main.cleanup()
772 main.exit()
773
Jon Hall7eb38402015-01-08 17:19:54 -0800774 def getInterfaces( self, node ):
775 """
776 return information dict about interfaces connected to the node"""
777 if self.handle:
778 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800779 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700780 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700781 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800782 response = self.execute(
783 cmd=cmd,
784 prompt="mininet>",
785 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800786 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800787 main.log.error( self.name + ": EOF exception found" )
788 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700789 main.cleanup()
790 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700791 return response
792 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800793 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700794
Jon Hall7eb38402015-01-08 17:19:54 -0800795 def dump( self ):
796 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700797 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800798 response = self.execute(
799 cmd='dump',
800 prompt='mininet>',
801 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800802 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800803 main.log.error( self.name + ": EOF exception found" )
804 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700805 main.cleanup()
806 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700807 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800808
Jon Hall7eb38402015-01-08 17:19:54 -0800809 def intfs( self ):
810 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700811 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800812 response = self.execute(
813 cmd='intfs',
814 prompt='mininet>',
815 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800816 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800817 main.log.error( self.name + ": EOF exception found" )
818 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700819 main.cleanup()
820 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700821 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800822
Jon Hall7eb38402015-01-08 17:19:54 -0800823 def net( self ):
824 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700825 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800826 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800827 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800828 main.log.error( self.name + ": EOF exception found" )
829 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700830 main.cleanup()
831 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700832 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800833
834 def iperf( self, host1, host2 ):
835 main.log.info(
836 self.name +
837 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700838 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800839 cmd1 = 'iperf ' + host1 + " " + host2
840 self.handle.sendline( cmd1 )
841 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800842 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800843 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800844 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800845 return main.TRUE
846 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800847 main.log.error( self.name + ": iperf test failed" )
848 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -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 )
shahshreyae6c7cf42014-11-26 16:39:01 -0800852 main.cleanup()
853 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800854
Jon Hall7eb38402015-01-08 17:19:54 -0800855 def iperfudp( self ):
856 main.log.info(
857 self.name +
858 ": Simple iperf TCP test between two " +
859 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700860 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800861 response = self.execute(
862 cmd='iperfudp',
863 prompt='mininet>',
864 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800865 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800866 main.log.error( self.name + ": EOF exception found" )
867 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700868 main.cleanup()
869 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700870 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800871
Jon Hall7eb38402015-01-08 17:19:54 -0800872 def nodes( self ):
873 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700874 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800875 response = self.execute(
876 cmd='nodes',
877 prompt='mininet>',
878 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800879 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800880 main.log.error( self.name + ": EOF exception found" )
881 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700882 main.cleanup()
883 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700884 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800885
Jon Hall7eb38402015-01-08 17:19:54 -0800886 def pingpair( self ):
887 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700888 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800889 response = self.execute(
890 cmd='pingpair',
891 prompt='mininet>',
892 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800893 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800894 main.log.error( self.name + ": EOF exception found" )
895 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700896 main.cleanup()
897 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800898
Jon Hall7eb38402015-01-08 17:19:54 -0800899 if re.search( ',\s0\%\spacket\sloss', response ):
900 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800901 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700902 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800903 else:
904 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800905 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700906 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800907
Jon Hall7eb38402015-01-08 17:19:54 -0800908 def link( self, **linkargs ):
909 """
910 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800911 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800912 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
913 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
914 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
915 main.log.info(
916 "Bring link between '" +
917 end1 +
918 "' and '" +
919 end2 +
920 "' '" +
921 option +
922 "'" )
923 command = "link " + \
924 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -0700925 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800926 self.handle.sendline( command )
927 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800928 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800929 main.log.error( self.name + ": EOF exception found" )
930 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700931 main.cleanup()
932 main.exit()
adminbae64d82013-08-01 10:50:15 -0700933 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800934
Jon Hall7eb38402015-01-08 17:19:54 -0800935 def yank( self, **yankargs ):
936 """
937 yank a mininet switch interface to a host"""
938 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800939 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800940 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
941 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
942 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700943 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800944 response = self.execute(
945 cmd=command,
946 prompt="mininet>",
947 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800948 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800949 main.log.error( self.name + ": EOF exception found" )
950 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700951 main.cleanup()
952 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700953 return main.TRUE
954
Jon Hall7eb38402015-01-08 17:19:54 -0800955 def plug( self, **plugargs ):
956 """
957 plug the yanked mininet switch interface to a switch"""
958 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800959 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800960 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
961 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
962 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700963 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800964 response = self.execute(
965 cmd=command,
966 prompt="mininet>",
967 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800968 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800969 main.log.error( self.name + ": EOF exception found" )
970 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700971 main.cleanup()
972 main.exit()
adminbae64d82013-08-01 10:50:15 -0700973 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800974
Jon Hall7eb38402015-01-08 17:19:54 -0800975 def dpctl( self, **dpctlargs ):
976 """
977 Run dpctl command on all switches."""
978 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800979 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800980 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
981 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
982 command = "dpctl " + cmd + " " + str( cmdargs )
983 try:
984 response = self.execute(
985 cmd=command,
986 prompt="mininet>",
987 timeout=10 )
988 except pexpect.EOF:
989 main.log.error( self.name + ": EOF exception found" )
990 main.log.error( self.name + ": " + self.handle.before )
991 main.cleanup()
992 main.exit()
993 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800994
kelvin-onlabd3b64892015-01-20 13:26:24 -0800995 def getVersion( self ):
Jon Hallff6b4b22015-02-23 09:25:15 -0800996 #FIXME: What uses this? This should be refactored to get
997 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -0800998 fileInput = path + '/lib/Mininet/INSTALL'
999 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001000 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001001 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001002 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001003 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001004 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001005 return version
adminbae64d82013-08-01 10:50:15 -07001006
kelvin-onlabd3b64892015-01-20 13:26:24 -08001007 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001008 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001009 Parameters:
1010 sw: The name of an OVS switch. Example "s1"
1011 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001012 The output of the command from the mininet cli
1013 or main.FALSE on timeout"""
1014 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001015 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001016 response = self.execute(
1017 cmd=command,
1018 prompt="mininet>",
1019 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001020 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001021 return response
admin2a9548d2014-06-17 14:08:07 -07001022 else:
1023 return main.FALSE
1024 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 )
admin2a9548d2014-06-17 14:08:07 -07001027 main.cleanup()
1028 main.exit()
adminbae64d82013-08-01 10:50:15 -07001029
kelvin-onlabd3b64892015-01-20 13:26:24 -08001030 def assignSwController( self, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001031 """
1032 count is only needed if there is more than 1 controller"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001033 args = utilities.parse_args( [ "COUNT" ], **kwargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001034 count = args[ "COUNT" ] if args != {} else 1
Jon Hallf89c8552014-04-02 13:14:06 -07001035
1036 argstring = "SW"
Jon Hall7eb38402015-01-08 17:19:54 -08001037 for j in range( count ):
1038 argstring = argstring + ",IP" + \
1039 str( j + 1 ) + ",PORT" + str( j + 1 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001040 args = utilities.parse_args( argstring.split( "," ), **kwargs )
Jon Hallf89c8552014-04-02 13:14:06 -07001041
Jon Hall7eb38402015-01-08 17:19:54 -08001042 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1043 ptcpA = int( args[ "PORT1" ] ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001044 int( sw ) if args[ "PORT1" ] is not None else ""
Jon Hall7eb38402015-01-08 17:19:54 -08001045 ptcpB = "ptcp:" + str( ptcpA ) if ptcpA != "" else ""
Jon Hallfbc828e2015-01-06 17:30:19 -08001046
Jon Hall7eb38402015-01-08 17:19:54 -08001047 command = "sh ovs-vsctl set-controller s" + \
1048 str( sw ) + " " + ptcpB + " "
1049 for j in range( count ):
1050 i = j + 1
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001051 args = utilities.parse_args(
Jon Hall7eb38402015-01-08 17:19:54 -08001052 [ "IP" + str( i ), "PORT" + str( i ) ], **kwargs )
1053 ip = args[
1054 "IP" +
1055 str( i ) ] if args[
1056 "IP" +
1057 str( i ) ] is not None else ""
1058 port = args[
1059 "PORT" +
1060 str( i ) ] if args[
1061 "PORT" +
1062 str( i ) ] is not None else ""
1063 tcp = "tcp:" + str( ip ) + ":" + str( port ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001064 " " if ip != "" else ""
Jon Hallf89c8552014-04-02 13:14:06 -07001065 command = command + tcp
Jon Hall6094a362014-04-11 14:46:56 -07001066 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001067 self.execute( cmd=command, prompt="mininet>", timeout=5 )
Jon Hall6094a362014-04-11 14:46:56 -07001068 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001069 main.log.error( self.name + ": EOF exception found" )
1070 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001071 main.cleanup()
1072 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001073 except Exception:
1074 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall6094a362014-04-11 14:46:56 -07001075 main.cleanup()
1076 main.exit()
adminbae64d82013-08-01 10:50:15 -07001077
kelvin-onlabd3b64892015-01-20 13:26:24 -08001078 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001079 """
1080 Removes the controller target from sw"""
1081 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001082 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001083 response = self.execute(
1084 cmd=command,
1085 prompt="mininet>",
1086 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001087 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001088 main.log.error( self.name + ": EOF exception found" )
1089 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001090 main.cleanup()
1091 main.exit()
1092 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001093 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001094
kelvin-onlabd3b64892015-01-20 13:26:24 -08001095 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001096 """
Jon Hallb1290e82014-11-18 16:17:48 -05001097 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001098 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001099 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001100 NOTE: cannot currently specify what type of switch
1101 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001102 sw = name of the new switch as a string
1103 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001104 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001105 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001106 """
1107 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001108 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001109 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001110 response = self.execute(
1111 cmd=command,
1112 prompt="mininet>",
1113 timeout=10 )
1114 if re.search( "already exists!", response ):
1115 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001116 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001117 elif re.search( "Error", response ):
1118 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001119 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001120 elif re.search( "usage:", response ):
1121 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001122 return main.FALSE
1123 else:
1124 return main.TRUE
1125 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001126 main.log.error( self.name + ": EOF exception found" )
1127 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001128 main.cleanup()
1129 main.exit()
1130
kelvin-onlabd3b64892015-01-20 13:26:24 -08001131 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001132 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001133 delete a switch from the mininet topology
1134 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001135 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001136 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001137 sw = name of the switch as a string
1138 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001139 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001140 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001141 response = self.execute(
1142 cmd=command,
1143 prompt="mininet>",
1144 timeout=10 )
1145 if re.search( "no switch named", response ):
1146 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001147 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001148 elif re.search( "Error", response ):
1149 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001150 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001151 elif re.search( "usage:", response ):
1152 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001153 return main.FALSE
1154 else:
1155 return main.TRUE
1156 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001157 main.log.error( self.name + ": EOF exception found" )
1158 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001159 main.cleanup()
1160 main.exit()
1161
kelvin-onlabd3b64892015-01-20 13:26:24 -08001162 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001163 """
1164 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001165 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001166 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001167 NOTE: cannot currently specify what type of link
1168 required params:
1169 node1 = the string node name of the first endpoint of the link
1170 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001171 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001172 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001173 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001174 response = self.execute(
1175 cmd=command,
1176 prompt="mininet>",
1177 timeout=10 )
1178 if re.search( "doesnt exist!", response ):
1179 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001180 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001181 elif re.search( "Error", response ):
1182 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001183 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001184 elif re.search( "usage:", response ):
1185 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001186 return main.FALSE
1187 else:
1188 return main.TRUE
1189 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001190 main.log.error( self.name + ": EOF exception found" )
1191 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001192 main.cleanup()
1193 main.exit()
1194
kelvin-onlabd3b64892015-01-20 13:26:24 -08001195 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001196 """
1197 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001198 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001199 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001200 required params:
1201 node1 = the string node name of the first endpoint of the link
1202 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001203 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001204 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001205 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001206 response = self.execute(
1207 cmd=command,
1208 prompt="mininet>",
1209 timeout=10 )
1210 if re.search( "no node named", response ):
1211 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001212 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001213 elif re.search( "Error", response ):
1214 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001215 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001216 elif re.search( "usage:", response ):
1217 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001218 return main.FALSE
1219 else:
1220 return main.TRUE
1221 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001222 main.log.error( self.name + ": EOF exception found" )
1223 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001224 main.cleanup()
1225 main.exit()
1226
kelvin-onlabd3b64892015-01-20 13:26:24 -08001227 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001228 """
Jon Hallb1290e82014-11-18 16:17:48 -05001229 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001230 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001231 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001232 NOTE: cannot currently specify what type of host
1233 required params:
1234 hostname = the string hostname
1235 optional key-value params
1236 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001237 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001238 """
1239 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001240 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001241 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001242 response = self.execute(
1243 cmd=command,
1244 prompt="mininet>",
1245 timeout=10 )
1246 if re.search( "already exists!", response ):
1247 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001248 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001249 elif re.search( "doesnt exists!", response ):
1250 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001251 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001252 elif re.search( "Error", response ):
1253 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001254 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001255 elif re.search( "usage:", response ):
1256 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001257 return main.FALSE
1258 else:
1259 return main.TRUE
1260 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001261 main.log.error( self.name + ": EOF exception found" )
1262 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001263 main.cleanup()
1264 main.exit()
1265
kelvin-onlabd3b64892015-01-20 13:26:24 -08001266 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001267 """
1268 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001269 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001270 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001271 NOTE: this uses a custom mn function
1272 required params:
1273 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001274 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001275 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001276 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001277 response = self.execute(
1278 cmd=command,
1279 prompt="mininet>",
1280 timeout=10 )
1281 if re.search( "no host named", response ):
1282 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001283 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001284 elif re.search( "Error", response ):
1285 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001286 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001287 elif re.search( "usage:", response ):
1288 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001289 return main.FALSE
1290 else:
1291 return main.TRUE
1292 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001293 main.log.error( self.name + ": EOF exception found" )
1294 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001295 main.cleanup()
1296 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001297
Jon Hall7eb38402015-01-08 17:19:54 -08001298 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001299 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001300 Called at the end of the test to stop the mininet and
1301 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001302 """
1303 self.handle.sendline('')
Jon Halld61331b2015-02-17 16:35:47 -08001304 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Hallefbd9792015-03-05 16:11:36 -08001305 timeout=2)
kelvin-onlaba1484582015-02-02 15:46:20 -08001306 if i == 0:
1307 self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001308 elif i == 1:
1309 return main.TRUE
1310 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001311 # print "Disconnecting Mininet"
1312 if self.handle:
1313 self.handle.sendline( "exit" )
1314 self.handle.expect( "exit" )
1315 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001316 else:
1317 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001318 return response
1319
Hari Krishnab35c6d02015-03-18 11:13:51 -07001320 def stopNet( self, fileName = "", timeout=5):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001321 """
Jon Hall21270ac2015-02-16 17:59:55 -08001322 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001323 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001324 main.FALSE if the pexpect handle does not exist.
1325
Jon Halld61331b2015-02-17 16:35:47 -08001326 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001327 """
Jon Hall21270ac2015-02-16 17:59:55 -08001328
Jon Halld61331b2015-02-17 16:35:47 -08001329 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001330 response = ''
1331 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001332 try:
kelvin-onlab26bc17f2015-02-06 14:08:59 -08001333 self.handle.sendline("")
kelvin-onlab56a3f462015-02-06 14:04:43 -08001334 i = self.handle.expect( [ 'mininet>',
1335 '\$',
1336 pexpect.EOF,
1337 pexpect.TIMEOUT ],
1338 timeout )
1339 if i == 0:
1340 main.log.info( "Exiting mininet..." )
1341
Jon Hall7eb38402015-01-08 17:19:54 -08001342 response = self.execute(
1343 cmd="exit",
1344 prompt="(.*)",
1345 timeout=120 )
Jon Halld61331b2015-02-17 16:35:47 -08001346 main.log.info( self.name + ": Stopped")
Jon Hall7eb38402015-01-08 17:19:54 -08001347 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001348 response = main.TRUE
Hari Krishnab35c6d02015-03-18 11:13:51 -07001349
kelvin-onlab56a3f462015-02-06 14:04:43 -08001350 if i == 1:
1351 main.log.info( " Mininet trying to exit while not " +
1352 "in the mininet prompt" )
1353 elif i == 2:
1354 main.log.error( "Something went wrong exiting mininet" )
1355 elif i == 3: # timeout
1356 main.log.error( "Something went wrong exiting mininet " +
1357 "TIMEOUT" )
1358
Hari Krishnab35c6d02015-03-18 11:13:51 -07001359 if fileName:
1360 self.handle.sendline("")
1361 self.handle.expect('\$')
1362 self.handle.sendline("sudo kill -9 \`ps -ef | grep \""+ fileName +"\" | grep -v grep | awk '{print $2}'\`")
Jon Hallfbc828e2015-01-06 17:30:19 -08001363 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001364 main.log.error( self.name + ": EOF exception found" )
1365 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001366 main.cleanup()
1367 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001368 else:
1369 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001370 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001371 return response
1372
Jon Hall7eb38402015-01-08 17:19:54 -08001373 def arping( self, src, dest, destmac ):
1374 self.handle.sendline( '' )
1375 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001376
Jon Hall7eb38402015-01-08 17:19:54 -08001377 self.handle.sendline( src + ' arping ' + dest )
admin07529932013-11-22 14:58:28 -08001378 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001379 self.handle.expect( [ destmac, pexpect.EOF, pexpect.TIMEOUT ] )
1380 main.log.info( self.name + ": ARP successful" )
1381 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001382 return main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -08001383 except Exception:
Jon Hall7eb38402015-01-08 17:19:54 -08001384 main.log.warn( self.name + ": ARP FAILURE" )
1385 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001386 return main.FALSE
1387
Jon Hall7eb38402015-01-08 17:19:54 -08001388 def decToHex( self, num ):
1389 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001390
Jon Hall7eb38402015-01-08 17:19:54 -08001391 def getSwitchFlowCount( self, switch ):
1392 """
1393 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001394 if self.handle:
1395 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1396 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001397 response = self.execute(
1398 cmd=cmd,
1399 prompt="mininet>",
1400 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001401 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001402 main.log.error( self.name + ": EOF exception found" )
1403 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001404 main.cleanup()
1405 main.exit()
1406 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001407 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001408 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001409 main.log.info(
1410 "Couldn't find flows on switch %s, found: %s" %
1411 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001412 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001413 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001414 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001415 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001416
kelvin-onlabd3b64892015-01-20 13:26:24 -08001417 def checkFlows( self, sw, dumpFormat=None ):
1418 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001419 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001420 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001421 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001422 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001423 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001424 response = self.execute(
1425 cmd=command,
1426 prompt="mininet>",
1427 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001428 return response
1429 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001430 main.log.error( self.name + ": EOF exception found" )
1431 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001432 main.cleanup()
1433 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001434
kelvin-onlabd3b64892015-01-20 13:26:24 -08001435 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001436 """
Jon Hallefbd9792015-03-05 16:11:36 -08001437 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001438 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001439 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001440 self.handle.sendline( "" )
1441 self.handle.expect( "mininet>" )
1442 self.handle.sendline(
1443 "sh sudo tcpdump -n -i " +
1444 intf +
1445 " " +
1446 port +
1447 " -w " +
1448 filename.strip() +
1449 " &" )
1450 self.handle.sendline( "" )
1451 i = self.handle.expect( [ 'No\ssuch\device',
1452 'listening\son',
1453 pexpect.TIMEOUT,
1454 "mininet>" ],
1455 timeout=10 )
1456 main.log.warn( self.handle.before + self.handle.after )
1457 self.handle.sendline( "" )
1458 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001459 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001460 main.log.error(
1461 self.name +
1462 ": tcpdump - No such device exists. " +
1463 "tcpdump attempted on: " +
1464 intf )
admin2a9548d2014-06-17 14:08:07 -07001465 return main.FALSE
1466 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001467 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001468 return main.TRUE
1469 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001470 main.log.error(
1471 self.name +
1472 ": tcpdump command timed out! Check interface name," +
1473 " given interface was: " +
1474 intf )
admin2a9548d2014-06-17 14:08:07 -07001475 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001476 elif i == 3:
1477 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001478 return main.TRUE
1479 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001480 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001481 return main.FALSE
1482 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001483 main.log.error( self.name + ": EOF exception found" )
1484 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001485 main.cleanup()
1486 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001487 except Exception:
1488 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001489 main.cleanup()
1490 main.exit()
1491
kelvin-onlabd3b64892015-01-20 13:26:24 -08001492 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001493 """
1494 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001495 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001496 self.handle.sendline( "sh sudo pkill tcpdump" )
1497 self.handle.expect( "mininet>" )
1498 self.handle.sendline( "" )
1499 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001500 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001501 main.log.error( self.name + ": EOF exception found" )
1502 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001503 main.cleanup()
1504 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001505 except Exception:
1506 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001507 main.cleanup()
1508 main.exit()
1509
kelvin-onlabd3b64892015-01-20 13:26:24 -08001510 def compareSwitches( self, topo, switchesJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001511 """
1512 Compare mn and onos switches
1513 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001514 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001515
Jon Hall7eb38402015-01-08 17:19:54 -08001516 This uses the sts TestONTopology object"""
kelvin-onlabd3b64892015-01-20 13:26:24 -08001517 # main.log.debug( "Switches_json string: ", switchesJson )
Jon Hall7eb38402015-01-08 17:19:54 -08001518 output = { "switches": [] }
1519 # iterate through the MN topology and pull out switches and and port
1520 # info
1521 for switch in topo.graph.switches:
Jon Hall3d87d502014-10-17 18:37:42 -04001522 ports = []
1523 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001524 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001525 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001526 'name': port.name } )
1527 output[ 'switches' ].append( {
1528 "name": switch.name,
1529 "dpid": str( switch.dpid ).zfill( 16 ),
1530 "ports": ports } )
Jon Hall3d87d502014-10-17 18:37:42 -04001531
Jon Hall7eb38402015-01-08 17:19:54 -08001532 # print "mn"
1533 # print json.dumps( output,
Jon Hallff6b4b22015-02-23 09:25:15 -08001534 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001535 # indent=4,
1536 # separators=( ',', ': ' ) )
1537 # print "onos"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001538 # print json.dumps( switchesJson,
Jon Hallff6b4b22015-02-23 09:25:15 -08001539 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001540 # indent=4,
1541 # separators=( ',', ': ' ) )
Jon Hall3d87d502014-10-17 18:37:42 -04001542
1543 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001544 mnDPIDs = []
1545 for switch in output[ 'switches' ]:
1546 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001547 mnDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001548 # print "List of Mininet switch DPID's"
1549 # print mnDPIDs
kelvin-onlabd3b64892015-01-20 13:26:24 -08001550 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001551 main.log.error(
1552 self.name +
1553 ".compare_switches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001554 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001555 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001556 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001557 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001558 if switch[ 'available' ]:
1559 onosDPIDs.append(
1560 switch[ 'id' ].replace(
1561 ":",
1562 '' ).replace(
1563 "of",
1564 '' ).lower() )
1565 # else:
1566 # print "Switch is unavailable:"
1567 # print switch
Jon Hall3d87d502014-10-17 18:37:42 -04001568 onosDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001569 # print "List of ONOS switch DPID's"
1570 # print onosDPIDs
Jon Hall3d87d502014-10-17 18:37:42 -04001571
Jon Hall7eb38402015-01-08 17:19:54 -08001572 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001573 switchResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001574 main.log.report( "Switches in MN but not in ONOS:" )
1575 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
1576 main.log.report( str( list1 ) )
1577 main.log.report( "Switches in ONOS but not in MN:" )
1578 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
kelvin-onlabedcff052015-01-16 12:53:55 -08001579 main.log.report( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001580 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001581 switchResults = main.TRUE
1582 return switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001583
kelvin-onlabd3b64892015-01-20 13:26:24 -08001584 def comparePorts( self, topo, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001585 """
Jon Hall72cf1dc2014-10-20 21:04:50 -04001586 Compare mn and onos ports
1587 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001588 portsJson: parsed json object from the onos ports api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001589
Jon Hallfbc828e2015-01-06 17:30:19 -08001590 Dependencies:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001591 1. This uses the sts TestONTopology object
1592 2. numpy - "sudo pip install numpy"
1593
Jon Hall7eb38402015-01-08 17:19:54 -08001594 """
1595 # FIXME: this does not look for extra ports in ONOS, only checks that
1596 # ONOS has what is in MN
Jon Hall72cf1dc2014-10-20 21:04:50 -04001597 from numpy import uint64
kelvin-onlabd3b64892015-01-20 13:26:24 -08001598 portsResults = main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001599 output = { "switches": [] }
1600 # iterate through the MN topology and pull out switches and and port
1601 # info
1602 for switch in topo.graph.switches:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001603 ports = []
1604 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001605 # print port.hw_addr.toStr( separator='' )
Jon Hallefbd9792015-03-05 16:11:36 -08001606 tmpPort = { 'of_port': port.port_no,
1607 'mac': str( port.hw_addr ).replace( '\'', '' ),
1608 'name': port.name,
1609 'enabled': port.enabled }
Jon Hall39f29df2014-11-04 19:30:21 -05001610
kelvin-onlabd3b64892015-01-20 13:26:24 -08001611 ports.append( tmpPort )
Jon Hallefbd9792015-03-05 16:11:36 -08001612 tmpSwitch = { 'name': switch.name,
1613 'dpid': str( switch.dpid ).zfill( 16 ),
1614 'ports': ports }
Jon Hall39f29df2014-11-04 19:30:21 -05001615
kelvin-onlabd3b64892015-01-20 13:26:24 -08001616 output[ 'switches' ].append( tmpSwitch )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001617
Jon Hall7eb38402015-01-08 17:19:54 -08001618 # PORTS
kelvin-onlabd3b64892015-01-20 13:26:24 -08001619 for mnSwitch in output[ 'switches' ]:
1620 mnPorts = []
1621 onosPorts = []
1622 switchResult = main.TRUE
1623 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001624 if port[ 'enabled' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001625 mnPorts.append( port[ 'of_port' ] )
1626 for onosSwitch in portsJson:
Jon Hall7eb38402015-01-08 17:19:54 -08001627 # print "Iterating through a new switch as seen by ONOS"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001628 # print onosSwitch
1629 if onosSwitch[ 'device' ][ 'available' ]:
1630 if onosSwitch[ 'device' ][ 'id' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001631 ':',
1632 '' ).replace(
1633 "of",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001634 '' ) == mnSwitch[ 'dpid' ]:
1635 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001636 if port[ 'isEnabled' ]:
1637 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001638 # onosPorts.append( 'local' )
1639 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001640 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001641 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001642 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001643 mnPorts.sort( key=float )
1644 onosPorts.sort( key=float )
1645 # print "\nPorts for Switch %s:" % ( mnSwitch[ 'name' ] )
1646 # print "\tmn_ports[] = ", mnPorts
1647 # print "\tonos_ports[] = ", onosPorts
1648 mnPortsLog = mnPorts
1649 onosPortsLog = onosPorts
1650 mnPorts = [ x for x in mnPorts ]
1651 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001652
Jon Hall7eb38402015-01-08 17:19:54 -08001653 # TODO: handle other reserved port numbers besides LOCAL
1654 # NOTE: Reserved ports
1655 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1656 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001657 for mnPort in mnPortsLog:
1658 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001659 # don't set results to true here as this is just one of
1660 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001661 mnPorts.remove( mnPort )
1662 onosPorts.remove( mnPort )
Jon Hall7eb38402015-01-08 17:19:54 -08001663 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001664 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001665 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001666 if 65534 in mnPorts:
1667 mnPorts.remove( 65534 )
1668 if long( uint64( -2 ) ) in onosPorts:
1669 onosPorts.remove( long( uint64( -2 ) ) )
1670 if len( mnPorts ): # the ports of this switch don't match
1671 switchResult = main.FALSE
1672 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1673 if len( onosPorts ): # the ports of this switch don't match
1674 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001675 main.log.warn(
1676 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001677 str( onosPorts ) )
1678 if switchResult == main.FALSE:
Jon Hall7eb38402015-01-08 17:19:54 -08001679 main.log.report(
1680 "The list of ports for switch %s(%s) does not match:" %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001681 ( mnSwitch[ 'name' ], mnSwitch[ 'dpid' ] ) )
1682 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1683 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1684 portsResults = portsResults and switchResult
1685 return portsResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001686
kelvin-onlabd3b64892015-01-20 13:26:24 -08001687 def compareLinks( self, topo, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001688 """
1689 Compare mn and onos links
1690 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001691 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001692
Jon Hall7eb38402015-01-08 17:19:54 -08001693 This uses the sts TestONTopology object"""
1694 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08001695 # ONOS has what is in MN
Jon Hall7eb38402015-01-08 17:19:54 -08001696 output = { "switches": [] }
kelvin-onlabd3b64892015-01-20 13:26:24 -08001697 onos = linksJson
Jon Hall7eb38402015-01-08 17:19:54 -08001698 # iterate through the MN topology and pull out switches and and port
1699 # info
1700 for switch in topo.graph.switches:
Jon Hall38481722014-11-04 16:50:05 -05001701 # print "Iterating though switches as seen by Mininet"
1702 # print switch
Jon Hall72cf1dc2014-10-20 21:04:50 -04001703 ports = []
1704 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001705 # print port.hw_addr.toStr( separator='' )
1706 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001707 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001708 'name': port.name } )
1709 output[ 'switches' ].append( {
1710 "name": switch.name,
1711 "dpid": str( switch.dpid ).zfill( 16 ),
1712 "ports": ports } )
1713 # LINKS
Jon Hall72cf1dc2014-10-20 21:04:50 -04001714
kelvin-onlabd3b64892015-01-20 13:26:24 -08001715 mnLinks = [
kelvin-onlab9592d132015-01-20 17:18:02 -08001716 link for link in topo.patch_panel.network_links if (
Jon Hall7eb38402015-01-08 17:19:54 -08001717 link.port1.enabled and link.port2.enabled ) ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08001718 if 2 * len( mnLinks ) == len( onos ):
1719 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001720 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001721 linkResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001722 main.log.report(
Jon Hall328ddca2015-01-28 15:57:15 -08001723 "Mininet has " + str( len( mnLinks ) ) +
1724 " bidirectional links and ONOS has " +
1725 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001726
Jon Hall7eb38402015-01-08 17:19:54 -08001727 # iterate through MN links and check if an ONOS link exists in
1728 # both directions
1729 # NOTE: Will currently only show mn links as down if they are
1730 # cut through STS. We can either do everything through STS or
kelvin-onlabd3b64892015-01-20 13:26:24 -08001731 # wait for upNetworkLinks and downNetworkLinks to be
Jon Hall7eb38402015-01-08 17:19:54 -08001732 # fully implemented.
kelvin-onlabd3b64892015-01-20 13:26:24 -08001733 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08001734 # print "Link: %s" % link
1735 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04001736 node1 = None
1737 port1 = None
1738 node2 = None
1739 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08001740 firstDir = main.FALSE
1741 secondDir = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001742 for switch in output[ 'switches' ]:
1743 # print "Switch: %s" % switch[ 'name' ]
1744 if switch[ 'name' ] == link.node1.name:
1745 node1 = switch[ 'dpid' ]
1746 for port in switch[ 'ports' ]:
1747 if str( port[ 'name' ] ) == str( link.port1 ):
1748 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001749 if node1 is not None and node2 is not None:
1750 break
Jon Hall7eb38402015-01-08 17:19:54 -08001751 if switch[ 'name' ] == link.node2.name:
1752 node2 = switch[ 'dpid' ]
1753 for port in switch[ 'ports' ]:
1754 if str( port[ 'name' ] ) == str( link.port2 ):
1755 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001756 if node1 is not None and node2 is not None:
1757 break
1758
kelvin-onlabd3b64892015-01-20 13:26:24 -08001759 for onosLink in onos:
1760 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001761 ":",
1762 '' ).replace(
1763 "of",
1764 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001765 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001766 ":",
1767 '' ).replace(
1768 "of",
1769 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001770 onosPort1 = onosLink[ 'src' ][ 'port' ]
1771 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001772
Jon Hall72cf1dc2014-10-20 21:04:50 -04001773 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08001774 if str( onosNode1 ) == str( node1 ) and str(
1775 onosNode2 ) == str( node2 ):
1776 if int( onosPort1 ) == int( port1 ) and int(
1777 onosPort2 ) == int( port2 ):
1778 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001779 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001780 main.log.warn(
1781 'The port numbers do not match for ' +
1782 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001783 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001784 'link %s/%s -> %s/%s' %
1785 ( node1,
1786 port1,
1787 node2,
1788 port2 ) +
1789 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001790 ( onosNode1,
1791 onosPort1,
1792 onosNode2,
1793 onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001794
1795 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08001796 elif ( str( onosNode1 ) == str( node2 ) and
1797 str( onosNode2 ) == str( node1 ) ):
1798 if ( int( onosPort1 ) == int( port2 )
1799 and int( onosPort2 ) == int( port1 ) ):
1800 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001801 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001802 main.log.warn(
1803 'The port numbers do not match for ' +
1804 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001805 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001806 'link %s/%s -> %s/%s' %
1807 ( node2,
1808 port2,
1809 node1,
1810 port1 ) +
1811 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001812 ( onosNode2,
1813 onosPort2,
1814 onosNode1,
1815 onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001816 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04001817 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08001818 if not firstDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001819 main.log.report(
1820 'ONOS does not have the link %s/%s -> %s/%s' %
1821 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001822 if not secondDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001823 main.log.report(
1824 'ONOS does not have the link %s/%s -> %s/%s' %
1825 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001826 linkResults = linkResults and firstDir and secondDir
1827 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001828
Jon Hallff6b4b22015-02-23 09:25:15 -08001829 def compareHosts( self, topo, hostsJson ):
1830 """
1831 Compare mn and onos Hosts.
1832 Since Mininet hosts are quiet, ONOS will only know of them when they
1833 speak. For this reason, we will only check that the hosts in ONOS
1834 stores are in Mininet, and not vice versa.
1835 topo: sts TestONTopology object
1836 hostsJson: parsed json object from the onos hosts api
1837
1838 This uses the sts TestONTopology object"""
1839 import json
1840 hostResults = main.TRUE
1841 hosts = []
1842 # iterate through the MN topology and pull out hosts
1843 for mnHost in topo.graph.hosts:
1844 interfaces = []
1845 for intf in mnHost.interfaces:
1846 interfaces.append( {
1847 "name": intf.name, # str
1848 "ips": [ str( ip ) for ip in intf.ips ], # list of IPAddrs
1849 # hw_addr is of type EthAddr, Not JSON serializable
1850 "hw_addr": str( intf.hw_addr ) } )
1851 hosts.append( {
1852 "name": mnHost.name, # str
1853 "interfaces": interfaces } ) # list
1854 for onosHost in hostsJson:
1855 onosMAC = onosHost[ 'mac' ].lower()
1856 match = False
1857 for mnHost in hosts:
1858 for mnIntf in mnHost[ 'interfaces' ]:
1859 if onosMAC == mnIntf[ 'hw_addr' ].lower() :
1860 match = True
1861 for ip in mnIntf[ 'ips' ]:
1862 if ip in onosHost[ 'ips' ]:
1863 pass # all is well
1864 else:
1865 # misssing ip
1866 main.log.error( "ONOS host " + onosHost[ 'id' ]
1867 + " has a different IP than " +
1868 "the Mininet host." )
1869 output = json.dumps(
1870 onosHost,
1871 sort_keys=True,
1872 indent=4,
1873 separators=( ',', ': ' ) )
1874 main.log.info( output )
1875 hostResults = main.FALSE
1876 if not match:
1877 hostResults = main.FALSE
1878 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
1879 "corresponding Mininet host." )
1880 output = json.dumps( onosHost,
1881 sort_keys=True,
1882 indent=4,
1883 separators=( ',', ': ' ) )
1884 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08001885 return hostResults
1886
kelvin-onlabd3b64892015-01-20 13:26:24 -08001887 def getHosts( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08001888 """
1889 Returns a list of all hosts
1890 Don't ask questions just use it"""
1891 self.handle.sendline( "" )
1892 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001893
Jon Hall7eb38402015-01-08 17:19:54 -08001894 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
1895 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001896
kelvin-onlabd3b64892015-01-20 13:26:24 -08001897 handlePy = self.handle.before
1898 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
1899 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07001900
Jon Hall7eb38402015-01-08 17:19:54 -08001901 self.handle.sendline( "" )
1902 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001903
kelvin-onlabd3b64892015-01-20 13:26:24 -08001904 hostStr = handlePy.replace( "]", "" )
1905 hostStr = hostStr.replace( "'", "" )
1906 hostStr = hostStr.replace( "[", "" )
1907 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001908
kelvin-onlabd3b64892015-01-20 13:26:24 -08001909 return hostList
adminbae64d82013-08-01 10:50:15 -07001910
Jon Hall7eb38402015-01-08 17:19:54 -08001911 def update( self ):
1912 """
1913 updates the port address and status information for
1914 each port in mn"""
1915 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08001916 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05001917 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001918 self.handle.sendline( "" )
1919 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001920
Jon Hall7eb38402015-01-08 17:19:54 -08001921 self.handle.sendline( "update" )
1922 self.handle.expect( "update" )
1923 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001924
Jon Hall7eb38402015-01-08 17:19:54 -08001925 self.handle.sendline( "" )
1926 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001927
Jon Hallb1290e82014-11-18 16:17:48 -05001928 return main.TRUE
1929 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001930 main.log.error( self.name + ": EOF exception found" )
1931 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001932 main.cleanup()
1933 main.exit()
1934
adminbae64d82013-08-01 10:50:15 -07001935if __name__ != "__main__":
1936 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07001937 sys.modules[ __name__ ] = MininetCliDriver()