blob: 3337ea47343361d9eceb92117ac9c32d4ab3c8a7 [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
Jon Hallbe6dfc42015-01-12 17:37:25 -080021MininetCliDriver is the basic driver which will handle the Mininet functions
22
23Some functions rely on a modified version of Mininet. These functions
24should all be noted in the comments. To get this MN version run these commands
25from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080026 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080027 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080028 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git pull
30
Jon Hall272a4db2015-01-12 17:43:48 -080031
32 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080033changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070034import pexpect
adminbae64d82013-08-01 10:50:15 -070035import re
36import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070037import types
kelvin-onlaba4074292015-07-09 15:19:49 -070038import os
Jon Hall7eb38402015-01-08 17:19:54 -080039sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040040from math import pow
adminbae64d82013-08-01 10:50:15 -070041from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070042
Jon Hall7eb38402015-01-08 17:19:54 -080043
kelvin-onlab50907142015-04-01 13:37:45 -070044class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080045
46 """
47 MininetCliDriver is the basic driver which will handle
48 the Mininet functions"""
49 def __init__( self ):
50 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070051 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080052 self.name = None
Jon Hall7eb38402015-01-08 17:19:54 -080053 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070054 self.flag = 0
55
Jon Hall7eb38402015-01-08 17:19:54 -080056 def connect( self, **connectargs ):
57 """
58 Here the main is the TestON instance after creating
59 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080060 try:
61 for key in connectargs:
62 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080063
kelvin-onlaba1484582015-02-02 15:46:20 -080064 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070065
66 try:
67 if os.getenv( str( self.ip_address ) ) != None:
68 self.ip_address = os.getenv( str( self.ip_address ) )
69 else:
70 main.log.info( self.name +
71 ": Trying to connect to " +
72 self.ip_address )
73
74 except KeyError:
75 main.log.info( "Invalid host name," +
76 " connecting to local host instead" )
77 self.ip_address = 'localhost'
78 except Exception as inst:
79 main.log.error( "Uncaught exception: " + str( inst ) )
80
kelvin-onlaba1484582015-02-02 15:46:20 -080081 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070082 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080083 self ).connect(
84 user_name=self.user_name,
85 ip_address=self.ip_address,
86 port=None,
87 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080088
kelvin-onlaba1484582015-02-02 15:46:20 -080089 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080090 main.log.info( "Connection successful to the host " +
91 self.user_name +
92 "@" +
93 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080094 return main.TRUE
95 else:
96 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080097 self.user_name +
98 "@" +
99 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800100 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800101 return main.FALSE
102 except pexpect.EOF:
103 main.log.error( self.name + ": EOF exception found" )
104 main.log.error( self.name + ": " + self.handle.before )
105 main.cleanup()
106 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800107 except Exception:
108 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800109 main.cleanup()
110 main.exit()
111
kelvin-onlab10e8d392015-06-03 13:53:45 -0700112 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800113 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700114 Description:
115 Starts Mininet accepts a topology(.py) file and/or an optional
116 argument, to start the mininet, as a parameter.
117 Can also send regular mininet command to load up desired topology.
118 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
119 Options:
120 topoFile = file path for topology file (.py)
121 args = extra option added when starting the topology from the file
122 mnCmd = Mininet command use to start topology
123 Returns:
124 main.TRUE if the mininet starts successfully, main.FALSE
125 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800126 """
Jon Hall7eb38402015-01-08 17:19:54 -0800127 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700128 # make sure old networks are cleaned up
129 main.log.info( self.name +
130 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800131 self.handle.sendline( "sudo mn -c" )
132 i = self.handle.expect( [ 'password\sfor\s',
133 'Cleanup\scomplete',
134 pexpect.EOF,
135 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800136 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800137 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700138 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800139 main.log.info( self.name + ": Sending sudo password" )
140 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800141 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800142 '\$',
143 pexpect.EOF,
144 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800145 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800146 if i == 1:
147 main.log.info( self.name + ": Clean" )
148 elif i == 2:
149 main.log.error( self.name + ": Connection terminated" )
150 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700151 main.log.error( self.name + ": Something while cleaning " +
152 "Mininet took too long... " )
153 # Craft the string to start mininet
154 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700155 if not mnCmd:
156 if topoFile is None or topoFile == '': # If no file is given
157 main.log.info( self.name + ": building fresh Mininet" )
158 cmdString += "mn "
159 if args is None or args == '':
160 # If no args given, use args from .topo file
161 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700162 " " + self.options[ 'arg2' ] +\
163 " --mac --controller " +\
164 self.options[ 'controller' ] + " " +\
165 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700166 else: # else only use given args
167 pass
168 # TODO: allow use of topo args and method args?
169 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700170 main.log.info(
171 "Starting Mininet from topo file " +
172 topoFile )
kelvin-onlab10e8d392015-06-03 13:53:45 -0700173 cmdString += topoFile + " "
174 if args is None:
175 args = ''
176 # TODO: allow use of args from .topo file?
177 cmdString += args
178 else:
179 main.log.info( "Starting Mininet topology using '" + mnCmd +
180 "' command" )
181 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700182 # Send the command and check if network started
183 self.handle.sendline( "" )
184 self.handle.expect( '\$' )
185 main.log.info( "Sending '" + cmdString + "' to " + self.name )
186 self.handle.sendline( cmdString )
187 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800188 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700189 'Exception',
190 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800191 pexpect.EOF,
192 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700193 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800194 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700195 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800196 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800197 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700198 response = str( self.handle.before +
199 self.handle.after )
200 self.handle.expect( '\$' )
201 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700202 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700203 main.log.error(
204 self.name +
205 ": Launching Mininet failed: " + response )
206 return main.FALSE
207 elif i == 2:
208 self.handle.expect( [ "\n",
209 pexpect.EOF,
210 pexpect.TIMEOUT ],
211 timeout )
212 main.log.info( self.handle.before )
213 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800214 main.log.error( self.name + ": Connection timeout" )
215 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700216 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800217 main.log.error(
218 self.name +
219 ": Something took too long... " )
220 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700221 # Why did we hit this part?
222 main.log.error( "startNet did not return correctly" )
223 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800224 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700225 main.log.error( self.name + ": Connection failed to the host " +
226 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800227 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700228 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800229
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800230 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400231 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800232 # In tree topology, if fanout arg is not given, by default it is 2
233 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400234 fanout = 2
235 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500236 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800237 while( k <= depth - 1 ):
238 count = count + pow( fanout, k )
239 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800240 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800241 while( k <= depth - 2 ):
242 # depth-2 gives you only core links and not considering
243 # edge links as seen by ONOS. If all the links including
244 # edge links are required, do depth-1
245 count = count + pow( fanout, k )
246 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800247 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800248 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800249 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800250
Jon Hall7eb38402015-01-08 17:19:54 -0800251 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800252 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800253 # by default it is 1
254 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400255 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800256 numSwitches = depth
257 numHostsPerSw = fanout
258 totalNumHosts = numSwitches * numHostsPerSw
259 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800260 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800261 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800262 topoDict = { "num_switches": int( numSwitches ),
263 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400264 return topoDict
265
kelvin-onlabd3b64892015-01-20 13:26:24 -0800266 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700267 """
268 Calculate the number of switches and links in a topo."""
269 # TODO: combine this function and numSwitchesNlinks
270 argList = self.options[ 'arg1' ].split( "," )
271 topoArgList = argList[ 0 ].split( " " )
272 argList = map( int, argList[ 1: ] )
273 topoArgList = topoArgList[ 1: ] + argList
274
275 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400276 return topoDict
277
Jon Halld80cc142015-07-06 13:36:05 -0700278 def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800279 """
280 Verifies the reachability of the hosts using pingall command.
281 Optional parameter timeout allows you to specify how long to
282 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700283 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700284 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700285 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700286 ping
287 acceptableFailed - Set the number of acceptable failed pings for the
288 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800289 Returns:
290 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700291 otherwise main.FALSE
292 """
293 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700294 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700295 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700296 if self.handle:
297 main.log.info(
298 self.name +
299 ": Checking reachabilty to the hosts using pingall" )
300 response = ""
301 failedPings = 0
302 returnValue = main.TRUE
303 self.handle.sendline( "pingall" )
Jon Hall390696c2015-05-05 17:13:41 -0700304 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700305 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700306 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700307 pexpect.EOF,
308 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700309 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700310 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700311 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700312 response += self.handle.before
313 break
314 elif i == 1:
315 response += self.handle.before + self.handle.after
316 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700317 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700318 returnValue = main.FALSE
319 if shortCircuit:
320 main.log.error( self.name +
321 ": Aborting pingall - "
322 + str( failedPings ) +
323 " pings failed" )
324 break
Jon Hall390696c2015-05-05 17:13:41 -0700325 if ( time.time() - startTime ) > timeout:
326 returnValue = main.FALSE
327 main.log.error( self.name +
328 ": Aborting pingall - " +
329 "Function took too long " )
330 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700331 elif i == 2:
332 main.log.error( self.name +
333 ": EOF exception found" )
334 main.log.error( self.name + ": " +
335 self.handle.before )
336 main.cleanup()
337 main.exit()
338 elif i == 3:
339 response += self.handle.before
340 main.log.error( self.name +
341 ": TIMEOUT exception found" )
342 main.log.error( self.name +
343 ": " +
344 str( response ) )
345 # NOTE: Send ctrl-c to make sure pingall is done
346 self.handle.sendline( "\x03" )
347 self.handle.expect( "Interrupt" )
348 self.handle.expect( "mininet>" )
349 break
350 pattern = "Results\:"
351 main.log.info( "Pingall output: " + str( response ) )
352 if re.search( pattern, response ):
353 main.log.info( self.name + ": Pingall finished with "
354 + str( failedPings ) + " failed pings" )
355 return returnValue
356 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700357 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700358 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700359 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700360 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700362 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700363 main.log.error( self.name + ": Connection failed to the host" )
364 main.cleanup()
365 main.exit()
366 except pexpect.TIMEOUT:
367 if response:
368 main.log.info( "Pingall output: " + str( response ) )
369 main.log.error( self.name + ": pexpect.TIMEOUT found" )
370 return main.FALSE
371 except pexpect.EOF:
372 main.log.error( self.name + ": EOF exception found" )
373 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500374 main.cleanup()
375 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700376
Jon Hall7eb38402015-01-08 17:19:54 -0800377 def fpingHost( self, **pingParams ):
378 """
379 Uses the fping package for faster pinging...
380 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800381 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800382 command = args[ "SRC" ] + \
383 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
384 self.handle.sendline( command )
385 self.handle.expect(
386 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
387 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
388 response = self.handle.before
389 if re.search( ":\s-", response ):
390 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700391 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800392 elif re.search( ":\s\d{1,2}\.\d\d", response ):
393 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700394 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800395 main.log.info( self.name + ": Install fping on mininet machine... " )
396 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700397 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800398
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400399 def pingallHosts( self, hostList, pingType='ipv4' ):
400 """
kelvin-onlab2ff57022015-05-29 10:48:51 -0700401 Ping all specified hosts with a specific ping type
402
403 Acceptable pingTypes:
404 - 'ipv4'
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400405 - 'ipv6'
kelvin-onlab2ff57022015-05-29 10:48:51 -0700406
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400407 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700408 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700409
410 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400411 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700412
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400413 Returns main.FALSE if one or more of hosts specified
414 cannot reach each other"""
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400415 if pingType == "ipv4":
kelvin-onlab2ff57022015-05-29 10:48:51 -0700416 cmd = " ping -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400417 elif pingType == "ipv6":
418 cmd = " ping6 -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400419 else:
420 main.log.warn( "Invalid pingType specified" )
421 return
422
423 try:
424 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700425
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400426 isReachable = main.TRUE
427
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400428 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700429 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400430 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700431 pingList = hostList[ :listIndex ] + \
432 hostList[ ( listIndex + 1 ): ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700433
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400434 for temp in pingList:
435 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700436 pingCmd = str( host ) + cmd + str( temp )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400437 self.handle.sendline( pingCmd )
438 i = self.handle.expect( [ pingCmd, pexpect.TIMEOUT ] )
439 j = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
440 response = self.handle.before
441 if re.search( ',\s0\%\spacket\sloss', response ):
Jon Halld80cc142015-07-06 13:36:05 -0700442 main.log.info( str( host ) + " -> " + str( temp ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400443 else:
Jon Halld80cc142015-07-06 13:36:05 -0700444 main.log.info(
445 str( host ) + " -> X (" + str( temp ) + ") "
446 " Destination Unreachable" )
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400447 # One of the host to host pair is unreachable
448 isReachable = main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400449
kelvin-onlab2ff57022015-05-29 10:48:51 -0700450 return isReachable
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451
452 except pexpect.EOF:
453 main.log.error( self.name + ": EOF exception found" )
454 main.log.error( self.name + ": " + self.handle.before )
455 main.cleanup()
456 main.exit()
457
Jon Hall7eb38402015-01-08 17:19:54 -0800458 def pingHost( self, **pingParams ):
459 """
460 Ping from one mininet host to another
461 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800462 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800463 command = args[ "SRC" ] + " ping " + \
464 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700465 try:
Jon Hall61282e32015-03-19 11:34:11 -0700466 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800467 self.handle.sendline( command )
468 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700469 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800470 main.log.error(
471 self.name +
472 ": timeout when waiting for response from mininet" )
473 main.log.error( "response: " + str( self.handle.before ) )
474 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700475 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800476 main.log.error(
477 self.name +
478 ": timeout when waiting for response from mininet" )
479 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700480 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800481 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800482 main.log.error( self.name + ": EOF exception found" )
483 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700484 main.cleanup()
485 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800486 main.log.info( self.name + ": Ping Response: " + response )
487 if re.search( ',\s0\%\spacket\sloss', response ):
488 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800489 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700490 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800491 else:
492 main.log.error(
493 self.name +
494 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800495 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700496 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800497
Jon Hall7eb38402015-01-08 17:19:54 -0800498 def checkIP( self, host ):
499 """
500 Verifies the host's ip configured or not."""
501 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700502 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800503 response = self.execute(
504 cmd=host +
505 " ifconfig",
506 prompt="mininet>",
507 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800508 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800509 main.log.error( self.name + ": EOF exception found" )
510 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700511 main.cleanup()
512 main.exit()
adminbae64d82013-08-01 10:50:15 -0700513
Jon Hall7eb38402015-01-08 17:19:54 -0800514 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800515 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
516 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
517 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
518 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
519 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800520 # pattern = "inet addr:10.0.0.6"
521 if re.search( pattern, response ):
522 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700523 return main.TRUE
524 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800525 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700526 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800527 else:
528 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800529
Jon Hall7eb38402015-01-08 17:19:54 -0800530 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800531 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700532 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800533 response = self.execute(
534 cmd="h1 /usr/sbin/sshd -D&",
535 prompt="mininet>",
536 timeout=10 )
537 response = self.execute(
538 cmd="h4 /usr/sbin/sshd -D&",
539 prompt="mininet>",
540 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700541 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800542 vars( self )[ key ] = connectargs[ key ]
543 response = self.execute(
544 cmd="xterm h1 h4 ",
545 prompt="mininet>",
546 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800547 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800548 main.log.error( self.name + ": EOF exception found" )
549 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700550 main.cleanup()
551 main.exit()
adminbae64d82013-08-01 10:50:15 -0700552 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800553 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700554 if self.flag == 0:
555 self.flag = 1
556 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800557 else:
adminbae64d82013-08-01 10:50:15 -0700558 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800559
kelvin-onlaba1484582015-02-02 15:46:20 -0800560 def moveHost( self, host, oldSw, newSw, ):
561 """
562 Moves a host from one switch to another on the fly
563 Note: The intf between host and oldSw when detached
564 using detach(), will still show up in the 'net'
565 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700566 ( which is correct behavior since the interfaces
567 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800568 """
569 if self.handle:
570 try:
571 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700572 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800573 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800574 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800575 response = self.execute( cmd=cmd,
576 prompt="mininet>",
577 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700578
kelvin-onlaba1484582015-02-02 15:46:20 -0800579 # Determine hostintf and Oldswitchintf
580 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800581 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800582 print "cmd2= ", cmd
583 self.handle.sendline( cmd )
584 self.handle.expect( "mininet>" )
585
shahshreya73537862015-02-11 15:15:24 -0800586 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800587 cmd = "px ipaddr = hintf.IP()"
588 print "cmd3= ", cmd
589 self.handle.sendline( cmd )
590 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800591
592 cmd = "px macaddr = hintf.MAC()"
593 print "cmd3= ", cmd
594 self.handle.sendline( cmd )
595 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700596
kelvin-onlaba1484582015-02-02 15:46:20 -0800597 # Detach interface between oldSw-host
598 cmd = "px " + oldSw + ".detach( sintf )"
599 print "cmd4= ", cmd
600 self.handle.sendline( cmd )
601 self.handle.expect( "mininet>" )
602
603 # Add link between host-newSw
604 cmd = "py net.addLink(" + host + "," + newSw + ")"
605 print "cmd5= ", cmd
606 self.handle.sendline( cmd )
607 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700608
kelvin-onlaba1484582015-02-02 15:46:20 -0800609 # Determine hostintf and Newswitchintf
610 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800611 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800612 print "cmd6= ", cmd
613 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700614 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800615
616 # Attach interface between newSw-host
617 cmd = "px " + newSw + ".attach( sintf )"
618 print "cmd3= ", cmd
619 self.handle.sendline( cmd )
620 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700621
kelvin-onlaba1484582015-02-02 15:46:20 -0800622 # Set ipaddress of the host-newSw interface
623 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
624 print "cmd7 = ", cmd
625 self.handle.sendline( cmd )
626 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800627
628 # Set macaddress of the host-newSw interface
629 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
630 print "cmd8 = ", cmd
631 self.handle.sendline( cmd )
632 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700633
kelvin-onlaba1484582015-02-02 15:46:20 -0800634 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800635 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800636 self.handle.sendline( cmd )
637 self.handle.expect( "mininet>" )
638 print "output = ", self.handle.before
639
640 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800641 cmd = host + " ifconfig"
642 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800643 self.handle.sendline( cmd )
644 self.handle.expect( "mininet>" )
645 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700646
kelvin-onlaba1484582015-02-02 15:46:20 -0800647 return main.TRUE
648 except pexpect.EOF:
649 main.log.error( self.name + ": EOF exception found" )
650 main.log.error( self.name + ": " + self.handle.before )
651 return main.FALSE
652
Jon Hall7eb38402015-01-08 17:19:54 -0800653 def changeIP( self, host, intf, newIP, newNetmask ):
654 """
655 Changes the ip address of a host on the fly
656 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800657 if self.handle:
658 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800659 cmd = host + " ifconfig " + intf + " " + \
660 newIP + " " + 'netmask' + " " + newNetmask
661 self.handle.sendline( cmd )
662 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800663 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800664 main.log.info( "response = " + response )
665 main.log.info(
666 "Ip of host " +
667 host +
668 " changed to new IP " +
669 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800670 return main.TRUE
671 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800672 main.log.error( self.name + ": EOF exception found" )
673 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800674 return main.FALSE
675
Jon Hall7eb38402015-01-08 17:19:54 -0800676 def changeDefaultGateway( self, host, newGW ):
677 """
678 Changes the default gateway of a host
679 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800680 if self.handle:
681 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800682 cmd = host + " route add default gw " + newGW
683 self.handle.sendline( cmd )
684 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800685 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800686 main.log.info( "response = " + response )
687 main.log.info(
688 "Default gateway of host " +
689 host +
690 " changed to " +
691 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800692 return main.TRUE
693 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800694 main.log.error( self.name + ": EOF exception found" )
695 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800696 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800697
Jon Hall7eb38402015-01-08 17:19:54 -0800698 def addStaticMACAddress( self, host, GW, macaddr ):
699 """
Jon Hallefbd9792015-03-05 16:11:36 -0800700 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800701 if self.handle:
702 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800703 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
704 cmd = host + " arp -s " + GW + " " + macaddr
705 self.handle.sendline( cmd )
706 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800707 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800708 main.log.info( "response = " + response )
709 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800710 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800711 GW +
712 " changed to " +
713 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800714 return main.TRUE
715 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800716 main.log.error( self.name + ": EOF exception found" )
717 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800718 return main.FALSE
719
Jon Hall7eb38402015-01-08 17:19:54 -0800720 def verifyStaticGWandMAC( self, host ):
721 """
722 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800723 if self.handle:
724 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800725 # h1 arp -an
726 cmd = host + " arp -an "
727 self.handle.sendline( cmd )
728 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800729 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800730 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800731 return main.TRUE
732 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800733 main.log.error( self.name + ": EOF exception found" )
734 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800735 return main.FALSE
736
Jon Hall7eb38402015-01-08 17:19:54 -0800737 def getMacAddress( self, host ):
738 """
739 Verifies the host's ip configured or not."""
740 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700741 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800742 response = self.execute(
743 cmd=host +
744 " ifconfig",
745 prompt="mininet>",
746 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800747 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800748 main.log.error( self.name + ": EOF exception found" )
749 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700750 main.cleanup()
751 main.exit()
adminbae64d82013-08-01 10:50:15 -0700752
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700753 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800754 macAddressSearch = re.search( pattern, response, re.I )
755 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800756 main.log.info(
757 self.name +
758 ": Mac-Address of Host " +
759 host +
760 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800761 macAddress )
762 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700763 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800764 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700765
Jon Hall7eb38402015-01-08 17:19:54 -0800766 def getInterfaceMACAddress( self, host, interface ):
767 """
768 Return the IP address of the interface on the given host"""
769 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700770 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800771 response = self.execute( cmd=host + " ifconfig " + interface,
772 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800773 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800774 main.log.error( self.name + ": EOF exception found" )
775 main.log.error( self.name + ": " + self.handle.before )
776 main.cleanup()
777 main.exit()
778
779 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800780 macAddressSearch = re.search( pattern, response, re.I )
781 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800782 main.log.info( "No mac address found in %s" % response )
783 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800784 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800785 main.log.info(
786 "Mac-Address of " +
787 host +
788 ":" +
789 interface +
790 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800791 macAddress )
792 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800793 else:
794 main.log.error( "Connection failed to the host" )
795
796 def getIPAddress( self, host ):
797 """
798 Verifies the host's ip configured or not."""
799 if self.handle:
800 try:
801 response = self.execute(
802 cmd=host +
803 " ifconfig",
804 prompt="mininet>",
805 timeout=10 )
806 except pexpect.EOF:
807 main.log.error( self.name + ": EOF exception found" )
808 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700809 main.cleanup()
810 main.exit()
adminbae64d82013-08-01 10:50:15 -0700811
812 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800813 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800814 main.log.info(
815 self.name +
816 ": IP-Address of Host " +
817 host +
818 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800819 ipAddressSearch.group( 1 ) )
820 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800821 else:
822 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800823
Jon Hall7eb38402015-01-08 17:19:54 -0800824 def getSwitchDPID( self, switch ):
825 """
826 return the datapath ID of the switch"""
827 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700828 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700829 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800830 response = self.execute(
831 cmd=cmd,
832 prompt="mininet>",
833 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800834 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800835 main.log.error( self.name + ": EOF exception found" )
836 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700837 main.cleanup()
838 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800839 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800840 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700841 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800842 main.log.info(
843 "Couldn't find DPID for switch %s, found: %s" %
844 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700845 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800846 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700847 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800848 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700849
Jon Hall7eb38402015-01-08 17:19:54 -0800850 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700851 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800852 self.handle.sendline( "" )
853 self.expect( "mininet>" )
854 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700855 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800856 response = self.execute(
857 cmd=cmd,
858 prompt="mininet>",
859 timeout=10 )
860 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700861 response = self.handle.before
862 return response
863 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800864 main.log.error( self.name + ": EOF exception found" )
865 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700866 main.cleanup()
867 main.exit()
868
Jon Hall7eb38402015-01-08 17:19:54 -0800869 def getInterfaces( self, node ):
870 """
871 return information dict about interfaces connected to the node"""
872 if self.handle:
873 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800874 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700875 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700876 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800877 response = self.execute(
878 cmd=cmd,
879 prompt="mininet>",
880 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800881 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800882 main.log.error( self.name + ": EOF exception found" )
883 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700884 main.cleanup()
885 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700886 return response
887 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800888 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700889
Jon Hall7eb38402015-01-08 17:19:54 -0800890 def dump( self ):
891 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700892 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800893 response = self.execute(
894 cmd='dump',
895 prompt='mininet>',
896 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800897 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800898 main.log.error( self.name + ": EOF exception found" )
899 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700900 main.cleanup()
901 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700902 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800903
Jon Hall7eb38402015-01-08 17:19:54 -0800904 def intfs( self ):
905 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700906 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800907 response = self.execute(
908 cmd='intfs',
909 prompt='mininet>',
910 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800911 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800912 main.log.error( self.name + ": EOF exception found" )
913 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700914 main.cleanup()
915 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700916 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800917
Jon Hall7eb38402015-01-08 17:19:54 -0800918 def net( self ):
919 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700920 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800921 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800922 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800923 main.log.error( self.name + ": EOF exception found" )
924 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700925 main.cleanup()
926 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700927 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800928
Jon Hallafa8a472015-06-12 14:02:42 -0700929 def links( self ):
930 main.log.info( self.name + ": List network links" )
931 try:
932 response = self.execute( cmd='links', prompt='mininet>',
933 timeout=10 )
934 except pexpect.EOF:
935 main.log.error( self.name + ": EOF exception found" )
936 main.log.error( self.name + ": " + self.handle.before )
937 main.cleanup()
938 main.exit()
939 return response
940
GlennRC61321f22015-07-16 13:36:54 -0700941 def iperftcpAll(self, hosts, timeout=6):
942 '''
943 Runs the iperftcp function with a given set of hosts and specified timeout.
944
945 @parm:
946 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
947 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
948 '''
949 for host1 in hosts:
950 for host2 in hosts:
951 if host1 != host2:
952 if self.iperftcp(host1, host2, timeout) == main.FALSE:
953 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
954
955 def iperftcp(self, host1="h1", host2="h2", timeout=6):
956 '''
957 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
958 are valid.
959
960 @parm:
961 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
962 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
963 '''
964 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
965 try:
966 # Setup the mininet command
967 cmd1 = 'iperf ' + host1 + " " + host2
968 self.handle.sendline( cmd1 )
969 outcome = self.handle.expect( "mininet>", timeout )
970 response = self.handle.before
971
972 # checks if there are results in the mininet response
973 if "Results:" in response:
974 main.log.report(self.name + ": iperf test completed")
975 # parse the mn results
976 response = response.split("\r\n")
977 response = response[len(response)-2]
978 response = response.split(": ")
979 response = response[len(response)-1]
980 response = response.replace("[", "")
981 response = response.replace("]", "")
982 response = response.replace("\'", "")
983
984 # this is the bandwith two and from the two hosts
985 bandwidth = response.split(", ")
986
987 # there should be two elements in the bandwidth list
988 # ['host1 to host2', 'host2 to host1"]
989 if len(bandwidth) == 2:
990 main.log.report(self.name + ": iperf test successful")
shahshreyae6c7cf42014-11-26 16:39:01 -0800991 return main.TRUE
992 else:
GlennRC61321f22015-07-16 13:36:54 -0700993 main.log.error(self.name + ": invalid iperf results")
Jon Hall7eb38402015-01-08 17:19:54 -0800994 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -0700995 else:
996 main.log.error( self.name + ": iperf test failed" )
997 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800998
GlennRC61321f22015-07-16 13:36:54 -0700999 except pexpect.TIMEOUT:
1000 main.log.error( self.name + ": TIMEOUT exception found")
1001 main.log.error( self.name + ": Exception: Cannot connect to iperf on port 5001" )
1002 return main.FALSE
1003
Jon Hallfbc828e2015-01-06 17:30:19 -08001004 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001005 main.log.error( self.name + ": EOF exception found" )
1006 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001007 main.cleanup()
GlennRC61321f22015-07-16 13:36:54 -07001008 main.exit()
1009
1010 def iperfudpAll(self, hosts, bandwidth="10M"):
1011 '''
1012 Runs the iperfudp function with a given set of hosts and specified
1013 bandwidth
1014
1015 @param:
1016 bandwidth: the targeted bandwidth, in megabits ('M')
1017 '''
1018 for host1 in hosts:
1019 for host2 in hosts:
1020 if host1 != host2:
1021 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1022 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1023
1024 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1025
1026 '''
1027 Creates an iperf UDP test with a specific bandwidth.
1028 Returns true if results are valid.
1029
1030 @param:
1031 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1032 '''
1033 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1034 try:
1035 # setup the mininet command
1036 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1037 self.handle.sendline(cmd)
1038 self.handle.expect("mininet>")
1039 response = self.handle.before
1040
1041 # check if there are in results in the mininet response
1042 if "Results:" in response:
1043 main.log.report(self.name + ": iperfudp test completed")
1044 # parse the results
1045 response = response.split("\r\n")
1046 response = response[len(response)-2]
1047 response = response.split(": ")
1048 response = response[len(response)-1]
1049 response = response.replace("[", "")
1050 response = response.replace("]", "")
1051 response = response.replace("\'", "")
1052
1053 mnBandwidth = response.split(", ")
1054
1055 # check to see if there are at least three entries
1056 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1057 if len(mnBandwidth) == 3:
1058 # if one entry is blank then something is wrong
1059 for item in mnBandwidth:
1060 if item == "":
1061 main.log.error(self.name + ": Could not parse iperf output")
1062 main.log.error(self.name + ": invalid iperfudp results")
1063 return main.FALSE
1064 # otherwise results are vaild
1065 main.log.report(self.name + ": iperfudp test successful")
1066 return main.TRUE
1067 else:
1068 main.log.error(self.name + ": invalid iperfudp results")
1069 return main.FALSE
1070
1071 except pexpect.EOF:
1072 main.log.error( self.name + ": EOF exception found" )
1073 main.log.error( self.name + ": " + self.handle.before )
1074 main.cleanup()
1075 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001076
Jon Hall7eb38402015-01-08 17:19:54 -08001077 def nodes( self ):
1078 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001079 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001080 response = self.execute(
1081 cmd='nodes',
1082 prompt='mininet>',
1083 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001084 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001085 main.log.error( self.name + ": EOF exception found" )
1086 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001087 main.cleanup()
1088 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001089 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001090
Jon Hall7eb38402015-01-08 17:19:54 -08001091 def pingpair( self ):
1092 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001093 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001094 response = self.execute(
1095 cmd='pingpair',
1096 prompt='mininet>',
1097 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001098 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001099 main.log.error( self.name + ": EOF exception found" )
1100 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001101 main.cleanup()
1102 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001103
Jon Hall7eb38402015-01-08 17:19:54 -08001104 if re.search( ',\s0\%\spacket\sloss', response ):
1105 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001106 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -07001107 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001108 else:
1109 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001110 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -07001111 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001112
Jon Hall7eb38402015-01-08 17:19:54 -08001113 def link( self, **linkargs ):
1114 """
1115 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001116 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001117 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1118 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1119 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1120 main.log.info(
1121 "Bring link between '" +
1122 end1 +
1123 "' and '" +
1124 end2 +
1125 "' '" +
1126 option +
1127 "'" )
1128 command = "link " + \
1129 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001130 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001131 self.handle.sendline( command )
1132 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001133 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001134 main.log.error( self.name + ": EOF exception found" )
1135 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001136 main.cleanup()
1137 main.exit()
adminbae64d82013-08-01 10:50:15 -07001138 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001139
Jon Hall7eb38402015-01-08 17:19:54 -08001140 def yank( self, **yankargs ):
1141 """
1142 yank a mininet switch interface to a host"""
1143 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001144 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001145 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1146 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1147 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001148 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001149 response = self.execute(
1150 cmd=command,
1151 prompt="mininet>",
1152 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001153 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001154 main.log.error( self.name + ": EOF exception found" )
1155 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001156 main.cleanup()
1157 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001158 return main.TRUE
1159
Jon Hall7eb38402015-01-08 17:19:54 -08001160 def plug( self, **plugargs ):
1161 """
1162 plug the yanked mininet switch interface to a switch"""
1163 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001164 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001165 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1166 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1167 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001168 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001169 response = self.execute(
1170 cmd=command,
1171 prompt="mininet>",
1172 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001173 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001174 main.log.error( self.name + ": EOF exception found" )
1175 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001176 main.cleanup()
1177 main.exit()
adminbae64d82013-08-01 10:50:15 -07001178 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001179
Jon Hall7eb38402015-01-08 17:19:54 -08001180 def dpctl( self, **dpctlargs ):
1181 """
1182 Run dpctl command on all switches."""
1183 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001184 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001185 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1186 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1187 command = "dpctl " + cmd + " " + str( cmdargs )
1188 try:
1189 response = self.execute(
1190 cmd=command,
1191 prompt="mininet>",
1192 timeout=10 )
1193 except pexpect.EOF:
1194 main.log.error( self.name + ": EOF exception found" )
1195 main.log.error( self.name + ": " + self.handle.before )
1196 main.cleanup()
1197 main.exit()
1198 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001199
kelvin-onlabd3b64892015-01-20 13:26:24 -08001200 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001201 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001202 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001203 fileInput = path + '/lib/Mininet/INSTALL'
1204 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001205 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001206 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001207 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001208 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001209 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001210 return version
adminbae64d82013-08-01 10:50:15 -07001211
kelvin-onlabd3b64892015-01-20 13:26:24 -08001212 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001213 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001214 Parameters:
1215 sw: The name of an OVS switch. Example "s1"
1216 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001217 The output of the command from the mininet cli
1218 or main.FALSE on timeout"""
1219 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001220 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001221 response = self.execute(
1222 cmd=command,
1223 prompt="mininet>",
1224 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001225 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001226 return response
admin2a9548d2014-06-17 14:08:07 -07001227 else:
1228 return main.FALSE
1229 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001230 main.log.error( self.name + ": EOF exception found" )
1231 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001232 main.cleanup()
1233 main.exit()
adminbae64d82013-08-01 10:50:15 -07001234
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001235 def assignSwController( self, sw, ip, port="6633", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001236 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001237 Description:
1238 Assign switches to the controllers ( for ovs use only )
1239 Required:
1240 sw - Name of the switch. This can be a list or a string.
1241 ip - Ip addresses of controllers. This can be a list or a string.
1242 Optional:
1243 port - ONOS use port 6633, if no list of ports is passed, then
1244 the all the controller will use 6633 as their port number
1245 ptcp - ptcp number, This can be a string or a list that has
1246 the same length as switch. This is optional and not required
1247 when using ovs switches.
1248 NOTE: If switches and ptcp are given in a list type they should have the
1249 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1250 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001251
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001252 Return:
1253 Returns main.TRUE if mininet correctly assigned switches to
1254 controllers, otherwise it will return main.FALSE or an appropriate
1255 exception(s)
1256 """
1257 assignResult = main.TRUE
1258 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001259 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001260 command = "sh ovs-vsctl set-controller "
1261 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001262 try:
1263 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001264 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001265 if isinstance( port, types.StringType ) or \
1266 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001267 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001268 elif isinstance( port, types.ListType ):
1269 main.log.error( self.name + ": Only one controller " +
1270 "assigned and a list of ports has" +
1271 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001272 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001273 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001274 main.log.error( self.name + ": Invalid controller port " +
1275 "number. Please specify correct " +
1276 "controller port" )
1277 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001278
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001279 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001280 if isinstance( port, types.StringType ) or \
1281 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001282 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001283 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1284 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001285 elif isinstance( port, types.ListType ):
1286 if ( len( ip ) != len( port ) ):
1287 main.log.error( self.name + ": Port list = " +
1288 str( len( port ) ) +
1289 "should be the same as controller" +
1290 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001291 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001292 else:
1293 onosIp = ""
1294 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001295 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1296 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001297 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001298 main.log.error( self.name + ": Invalid controller port " +
1299 "number. Please specify correct " +
1300 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001301 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001302 else:
1303 main.log.error( self.name + ": Invalid ip address" )
1304 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001305
1306 if isinstance( sw, types.StringType ):
1307 command += sw + " "
1308 if ptcp:
1309 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001310 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001311 elif isinstance( ptcp, types.ListType ):
1312 main.log.error( self.name + ": Only one switch is " +
1313 "being set and multiple PTCP is " +
1314 "being passed " )
1315 else:
1316 main.log.error( self.name + ": Invalid PTCP" )
1317 ptcp = ""
1318 command += onosIp
1319 commandList.append( command )
1320
1321 elif isinstance( sw, types.ListType ):
1322 if ptcp:
1323 if isinstance( ptcp, types.ListType ):
1324 if len( ptcp ) != len( sw ):
1325 main.log.error( self.name + ": PTCP length = " +
1326 str( len( ptcp ) ) +
1327 " is not the same as switch" +
1328 " length = " +
1329 str( len( sw ) ) )
1330 return main.FALSE
1331 else:
1332 for switch, ptcpNum in zip( sw, ptcp ):
1333 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001334 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001335 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001336 tempCmd += onosIp
1337 commandList.append( tempCmd )
1338 else:
1339 main.log.error( self.name + ": Invalid PTCP" )
1340 return main.FALSE
1341 else:
1342 for switch in sw:
1343 tempCmd = "sh ovs-vsctl set-controller "
1344 tempCmd += switch + " " + onosIp
1345 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001346 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001347 main.log.error( self.name + ": Invalid switch type " )
1348 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001349
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001350 for cmd in commandList:
1351 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001352 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001353 except pexpect.TIMEOUT:
1354 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1355 return main.FALSE
1356 except pexpect.EOF:
1357 main.log.error( self.name + ": EOF exception found" )
1358 main.log.error( self.name + ": " + self.handle.before )
1359 main.cleanup()
1360 main.exit()
1361 return main.TRUE
1362 except Exception:
1363 main.log.exception( self.name + ": Uncaught exception!" )
1364 main.cleanup()
1365 main.exit()
adminbae64d82013-08-01 10:50:15 -07001366
kelvin-onlabd3b64892015-01-20 13:26:24 -08001367 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001368 """
1369 Removes the controller target from sw"""
1370 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001371 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001372 response = self.execute(
1373 cmd=command,
1374 prompt="mininet>",
1375 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001376 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001377 main.log.error( self.name + ": EOF exception found" )
1378 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001379 main.cleanup()
1380 main.exit()
1381 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001382 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001383
kelvin-onlabd3b64892015-01-20 13:26:24 -08001384 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001385 """
Jon Hallb1290e82014-11-18 16:17:48 -05001386 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001387 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001388 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001389 NOTE: cannot currently specify what type of switch
1390 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001391 sw = name of the new switch as a string
1392 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001393 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001394 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001395 """
1396 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001397 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001398 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001399 response = self.execute(
1400 cmd=command,
1401 prompt="mininet>",
1402 timeout=10 )
1403 if re.search( "already exists!", response ):
1404 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001405 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001406 elif re.search( "Error", response ):
1407 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001408 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001409 elif re.search( "usage:", response ):
1410 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001411 return main.FALSE
1412 else:
1413 return main.TRUE
1414 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001415 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001416 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001417 main.cleanup()
1418 main.exit()
1419
kelvin-onlabd3b64892015-01-20 13:26:24 -08001420 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001421 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001422 delete a switch from the mininet topology
1423 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001424 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001425 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001426 sw = name of the switch as a string
1427 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001428 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001429 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001430 response = self.execute(
1431 cmd=command,
1432 prompt="mininet>",
1433 timeout=10 )
1434 if re.search( "no switch named", response ):
1435 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001436 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001437 elif re.search( "Error", response ):
1438 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001439 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001440 elif re.search( "usage:", response ):
1441 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001442 return main.FALSE
1443 else:
1444 return main.TRUE
1445 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001446 main.log.error( self.name + ": EOF exception found" )
1447 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001448 main.cleanup()
1449 main.exit()
1450
kelvin-onlabd3b64892015-01-20 13:26:24 -08001451 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001452 """
1453 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001454 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001455 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001456 NOTE: cannot currently specify what type of link
1457 required params:
1458 node1 = the string node name of the first endpoint of the link
1459 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001460 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001461 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001462 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001463 response = self.execute(
1464 cmd=command,
1465 prompt="mininet>",
1466 timeout=10 )
1467 if re.search( "doesnt exist!", response ):
1468 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001469 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001470 elif re.search( "Error", response ):
1471 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001472 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001473 elif re.search( "usage:", response ):
1474 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001475 return main.FALSE
1476 else:
1477 return main.TRUE
1478 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001479 main.log.error( self.name + ": EOF exception found" )
1480 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001481 main.cleanup()
1482 main.exit()
1483
kelvin-onlabd3b64892015-01-20 13:26:24 -08001484 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001485 """
1486 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001487 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001488 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001489 required params:
1490 node1 = the string node name of the first endpoint of the link
1491 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001492 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001493 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001494 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001495 response = self.execute(
1496 cmd=command,
1497 prompt="mininet>",
1498 timeout=10 )
1499 if re.search( "no node named", response ):
1500 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001501 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001502 elif re.search( "Error", response ):
1503 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001504 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001505 elif re.search( "usage:", response ):
1506 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001507 return main.FALSE
1508 else:
1509 return main.TRUE
1510 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001511 main.log.error( self.name + ": EOF exception found" )
1512 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001513 main.cleanup()
1514 main.exit()
1515
kelvin-onlabd3b64892015-01-20 13:26:24 -08001516 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001517 """
Jon Hallb1290e82014-11-18 16:17:48 -05001518 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001519 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001520 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001521 NOTE: cannot currently specify what type of host
1522 required params:
1523 hostname = the string hostname
1524 optional key-value params
1525 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001526 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001527 """
1528 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001529 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001530 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001531 response = self.execute(
1532 cmd=command,
1533 prompt="mininet>",
1534 timeout=10 )
1535 if re.search( "already exists!", response ):
1536 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001537 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001538 elif re.search( "doesnt exists!", response ):
1539 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001540 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001541 elif re.search( "Error", response ):
1542 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001543 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001544 elif re.search( "usage:", response ):
1545 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001546 return main.FALSE
1547 else:
1548 return main.TRUE
1549 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001550 main.log.error( self.name + ": EOF exception found" )
1551 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001552 main.cleanup()
1553 main.exit()
1554
kelvin-onlabd3b64892015-01-20 13:26:24 -08001555 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001556 """
1557 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001558 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001559 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001560 NOTE: this uses a custom mn function
1561 required params:
1562 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001563 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001564 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001565 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001566 response = self.execute(
1567 cmd=command,
1568 prompt="mininet>",
1569 timeout=10 )
1570 if re.search( "no host named", response ):
1571 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001572 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001573 elif re.search( "Error", response ):
1574 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001575 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001576 elif re.search( "usage:", response ):
1577 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001578 return main.FALSE
1579 else:
1580 return main.TRUE
1581 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001582 main.log.error( self.name + ": EOF exception found" )
1583 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001584 main.cleanup()
1585 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001586
Jon Hall7eb38402015-01-08 17:19:54 -08001587 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001588 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001589 Called at the end of the test to stop the mininet and
1590 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001591 """
Jon Halld80cc142015-07-06 13:36:05 -07001592 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001593 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001594 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001595 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001596 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001597 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001598 elif i == 1:
1599 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001600 # print "Disconnecting Mininet"
1601 if self.handle:
1602 self.handle.sendline( "exit" )
1603 self.handle.expect( "exit" )
1604 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001605 else:
1606 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001607 return response
1608
Jon Halld80cc142015-07-06 13:36:05 -07001609 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001610 """
Jon Hall21270ac2015-02-16 17:59:55 -08001611 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001612 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001613 main.FALSE if the pexpect handle does not exist.
1614
Jon Halld61331b2015-02-17 16:35:47 -08001615 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001616 """
Jon Halld61331b2015-02-17 16:35:47 -08001617 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001618 response = ''
1619 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001620 try:
Jon Halld80cc142015-07-06 13:36:05 -07001621 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001622 i = self.handle.expect( [ 'mininet>',
1623 '\$',
1624 pexpect.EOF,
1625 pexpect.TIMEOUT ],
1626 timeout )
1627 if i == 0:
1628 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001629 response = self.execute(
1630 cmd="exit",
1631 prompt="(.*)",
1632 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001633 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001634 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001635 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001636
kelvin-onlab56a3f462015-02-06 14:04:43 -08001637 if i == 1:
1638 main.log.info( " Mininet trying to exit while not " +
1639 "in the mininet prompt" )
1640 elif i == 2:
1641 main.log.error( "Something went wrong exiting mininet" )
1642 elif i == 3: # timeout
1643 main.log.error( "Something went wrong exiting mininet " +
1644 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001645
Hari Krishnab35c6d02015-03-18 11:13:51 -07001646 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001647 self.handle.sendline( "" )
1648 self.handle.expect( '\$' )
1649 self.handle.sendline(
1650 "sudo kill -9 \`ps -ef | grep \"" +
1651 fileName +
1652 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001653 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001654 main.log.error( self.name + ": EOF exception found" )
1655 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001656 main.cleanup()
1657 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001658 else:
1659 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001660 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001661 return response
1662
kelvin-onlabf0594d72015-05-19 17:25:12 -07001663 def arping( self, host="", ip="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001664 """
1665 Description:
1666 Sends arp message from mininet host for hosts discovery
1667 Required:
1668 host - hosts name
1669 Optional:
1670 ip - ip address that does not exist in the network so there would
1671 be no reply.
1672 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001673 if ethDevice:
1674 ethDevice = '-I ' + ethDevice + ' '
Jon Halld80cc142015-07-06 13:36:05 -07001675 cmd = " py " + host + ".cmd(\"arping -c 1 " + ethDevice + ip + "\")"
admin07529932013-11-22 14:58:28 -08001676 try:
kelvin-onlab65782a82015-05-07 14:12:13 -07001677 main.log.warn( "Sending: " + cmd )
1678 self.handle.sendline( cmd )
1679 response = self.handle.before
1680 self.handle.sendline( "" )
1681 self.handle.expect( "mininet>" )
admin07529932013-11-22 14:58:28 -08001682 return main.TRUE
kelvin-onlab65782a82015-05-07 14:12:13 -07001683
1684 except pexpect.EOF:
1685 main.log.error( self.name + ": EOF exception found" )
1686 main.log.error( self.name + ": " + self.handle.before )
1687 main.cleanup()
1688 main.exit()
admin07529932013-11-22 14:58:28 -08001689
Jon Hall7eb38402015-01-08 17:19:54 -08001690 def decToHex( self, num ):
1691 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001692
Jon Hall7eb38402015-01-08 17:19:54 -08001693 def getSwitchFlowCount( self, switch ):
1694 """
1695 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001696 if self.handle:
1697 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1698 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001699 response = self.execute(
1700 cmd=cmd,
1701 prompt="mininet>",
1702 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001703 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001704 main.log.error( self.name + ": EOF exception found" )
1705 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001706 main.cleanup()
1707 main.exit()
1708 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001709 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001710 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001711 main.log.info(
1712 "Couldn't find flows on switch %s, found: %s" %
1713 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001714 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001715 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001716 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001717 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001718
kelvin-onlabd3b64892015-01-20 13:26:24 -08001719 def checkFlows( self, sw, dumpFormat=None ):
1720 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001721 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001722 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001723 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001724 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001725 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001726 response = self.execute(
1727 cmd=command,
1728 prompt="mininet>",
1729 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001730 return response
1731 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001732 main.log.error( self.name + ": EOF exception found" )
1733 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001734 main.cleanup()
1735 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001736
kelvin-onlabd3b64892015-01-20 13:26:24 -08001737 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001738 """
Jon Hallefbd9792015-03-05 16:11:36 -08001739 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001740 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001741 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001742 self.handle.sendline( "" )
1743 self.handle.expect( "mininet>" )
1744 self.handle.sendline(
1745 "sh sudo tcpdump -n -i " +
1746 intf +
1747 " " +
1748 port +
1749 " -w " +
1750 filename.strip() +
1751 " &" )
1752 self.handle.sendline( "" )
1753 i = self.handle.expect( [ 'No\ssuch\device',
1754 'listening\son',
1755 pexpect.TIMEOUT,
1756 "mininet>" ],
1757 timeout=10 )
1758 main.log.warn( self.handle.before + self.handle.after )
1759 self.handle.sendline( "" )
1760 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001761 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001762 main.log.error(
1763 self.name +
1764 ": tcpdump - No such device exists. " +
1765 "tcpdump attempted on: " +
1766 intf )
admin2a9548d2014-06-17 14:08:07 -07001767 return main.FALSE
1768 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001769 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001770 return main.TRUE
1771 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001772 main.log.error(
1773 self.name +
1774 ": tcpdump command timed out! Check interface name," +
1775 " given interface was: " +
1776 intf )
admin2a9548d2014-06-17 14:08:07 -07001777 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001778 elif i == 3:
1779 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001780 return main.TRUE
1781 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001782 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001783 return main.FALSE
1784 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001785 main.log.error( self.name + ": EOF exception found" )
1786 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001787 main.cleanup()
1788 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001789 except Exception:
1790 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001791 main.cleanup()
1792 main.exit()
1793
kelvin-onlabd3b64892015-01-20 13:26:24 -08001794 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001795 """
1796 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001797 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001798 self.handle.sendline( "sh sudo pkill tcpdump" )
1799 self.handle.expect( "mininet>" )
1800 self.handle.sendline( "" )
1801 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001802 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001803 main.log.error( self.name + ": EOF exception found" )
1804 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001805 main.cleanup()
1806 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001807 except Exception:
1808 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001809 main.cleanup()
1810 main.exit()
1811
Jon Halld80cc142015-07-06 13:36:05 -07001812 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001813 """
1814 Read ports from a Mininet switch.
1815
1816 Returns a json structure containing information about the
1817 ports of the given switch.
1818 """
1819 response = self.getInterfaces( nodeName )
1820 # TODO: Sanity check on response. log if no such switch exists
1821 ports = []
1822 for line in response.split( "\n" ):
1823 if not line.startswith( "name=" ):
1824 continue
1825 portVars = {}
1826 for var in line.split( "," ):
1827 key, value = var.split( "=" )
1828 portVars[ key ] = value
1829 isUp = portVars.pop( 'enabled', "True" )
1830 isUp = "True" in isUp
1831 if verbose:
1832 main.log.info( "Reading switch port %s(%s)" %
1833 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1834 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001835 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001836 mac = None
1837 ips = []
1838 ip = portVars[ 'ip' ]
1839 if ip == 'None':
1840 ip = None
1841 ips.append( ip )
1842 name = portVars[ 'name' ]
1843 if name == 'None':
1844 name = None
1845 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
1846 if name == 'lo':
1847 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
1848 else:
1849 portNo = re.search( portRe, name ).group( 'port' )
1850 ports.append( { 'of_port': portNo,
1851 'mac': str( mac ).replace( '\'', '' ),
1852 'name': name,
1853 'ips': ips,
1854 'enabled': isUp } )
1855 return ports
1856
Jon Halld80cc142015-07-06 13:36:05 -07001857 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001858 """
1859 Read switches from Mininet.
1860
1861 Returns a dictionary whose keys are the switch names and the value is
1862 a dictionary containing information about the switch.
1863 """
1864 # FIXME: This currently only works with OVS Switches
1865
1866 # Regex patterns to parse dump output
1867 # Example Switch:
1868 # <OVSSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=5238>
Jon Halld80cc142015-07-06 13:36:05 -07001869 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Hallafa8a472015-06-12 14:02:42 -07001870 swRE = r"<OVSSwitch(\{.*\})?\s(?P<name>[^:]+)\:\s" +\
1871 "(?P<ports>([^,]+,)*[^,\s]+)"
1872 # Update mn port info
1873 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07001874 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001875 dump = self.dump().split( "\n" )
1876 for line in dump:
1877 if line.startswith( "<OVSSwitch" ):
1878 result = re.search( swRE, line, re.I )
1879 name = result.group( 'name' )
1880 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
1881 if verbose:
1882 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
1883 ports = self.getPorts( name )
1884 output[ name ] = { "dpid": dpid, "ports": ports }
1885 return output
1886
Jon Halld80cc142015-07-06 13:36:05 -07001887 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001888 """
1889 Read hosts from Mininet.
1890
1891 Returns a dictionary whose keys are the host names and the value is
1892 a dictionary containing information about the host.
1893 """
1894 # Regex patterns to parse dump output
1895 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07001896 # <Host h1: pid=12725>
1897 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
1898 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
1899 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07001900 # NOTE: Does not correctly match hosts with multi-links
1901 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
1902 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001903 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07001904 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07001905 # update mn port info
1906 self.update()
1907 # Get mininet dump
1908 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07001909 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001910 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001911 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07001912 result = re.search( hostRE, line )
1913 name = result.group( 'name' )
1914 interfaces = []
1915 response = self.getInterfaces( name )
1916 # Populate interface info
1917 for line in response.split( "\n" ):
1918 if line.startswith( "name=" ):
1919 portVars = {}
1920 for var in line.split( "," ):
1921 key, value = var.split( "=" )
1922 portVars[ key ] = value
1923 isUp = portVars.pop( 'enabled', "True" )
1924 isUp = "True" in isUp
1925 if verbose:
1926 main.log.info( "Reading host port %s(%s)" %
1927 ( portVars[ 'name' ],
1928 portVars[ 'mac' ] ) )
1929 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001930 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001931 mac = None
1932 ips = []
1933 ip = portVars[ 'ip' ]
1934 if ip == 'None':
1935 ip = None
1936 ips.append( ip )
1937 intfName = portVars[ 'name' ]
1938 if name == 'None':
1939 name = None
1940 interfaces.append( {
1941 "name": intfName,
1942 "ips": ips,
1943 "mac": str( mac ),
1944 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07001945 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07001946 return hosts
1947
1948 def getLinks( self ):
1949 """
1950 Gathers information about current Mininet links. These links may not
1951 be up if one of the ports is down.
1952
1953 Returns a list of dictionaries with link endpoints.
1954
1955 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07001956 { 'node1': str( node1 name )
1957 'node2': str( node2 name )
1958 'port1': str( port1 of_port )
1959 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07001960 Note: The port number returned is the eth#, not necessarily the of_port
1961 number. In Mininet, for OVS switch, these should be the same. For
1962 hosts, this is just the eth#.
1963 """
1964 self.update()
1965 response = self.links().split( '\n' )
1966
1967 # Examples:
1968 # s1-eth3<->s2-eth1 (OK OK)
1969 # s13-eth3<->h27-eth0 (OK OK)
1970 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
1971 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
1972 links = []
1973 for line in response:
1974 match = re.search( linkRE, line )
1975 if match:
1976 node1 = match.group( 'node1' )
1977 node2 = match.group( 'node2' )
1978 port1 = match.group( 'port1' )
1979 port2 = match.group( 'port2' )
1980 links.append( { 'node1': node1,
1981 'node2': node2,
1982 'port1': port1,
1983 'port2': port2 } )
1984 return links
1985
1986 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001987 """
1988 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07001989 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001990
Jon Hallafa8a472015-06-12 14:02:42 -07001991 Dependencies:
1992 1. numpy - "sudo pip install numpy"
1993 """
1994 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04001995 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001996 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07001997 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08001998 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001999 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002000 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002001 main.log.error(
2002 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002003 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002004 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002005 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002006 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002007 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002008 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002009 onosDPIDs.append(
2010 switch[ 'id' ].replace(
2011 ":",
2012 '' ).replace(
2013 "of",
2014 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002015 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002016
Jon Hall7eb38402015-01-08 17:19:54 -08002017 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002018 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002019 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002020 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002021 main.log.error( str( list1 ) )
2022 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002023 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002024 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002025 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002026 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002027 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002028
Jon Hall7eb38402015-01-08 17:19:54 -08002029 # FIXME: this does not look for extra ports in ONOS, only checks that
2030 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002031 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002032
Jon Hall7eb38402015-01-08 17:19:54 -08002033 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002034 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002035 mnPorts = []
2036 onosPorts = []
2037 switchResult = main.TRUE
2038 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002039 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002040 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002041 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002042 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002043 if onosSwitch[ 'device' ][ 'id' ].replace(
2044 ':',
2045 '' ).replace(
2046 "of",
2047 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002048 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002049 if port[ 'isEnabled' ]:
2050 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002051 # onosPorts.append( 'local' )
2052 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002053 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002054 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002055 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002056 mnPorts.sort( key=float )
2057 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002058
kelvin-onlabd3b64892015-01-20 13:26:24 -08002059 mnPortsLog = mnPorts
2060 onosPortsLog = onosPorts
2061 mnPorts = [ x for x in mnPorts ]
2062 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002063
Jon Hall7eb38402015-01-08 17:19:54 -08002064 # TODO: handle other reserved port numbers besides LOCAL
2065 # NOTE: Reserved ports
2066 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2067 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002068 for mnPort in mnPortsLog:
2069 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002070 # don't set results to true here as this is just one of
2071 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002072 mnPorts.remove( mnPort )
2073 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002074
Jon Hall7eb38402015-01-08 17:19:54 -08002075 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002076 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002077 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002078 if 65534 in mnPorts:
2079 mnPorts.remove( 65534 )
2080 if long( uint64( -2 ) ) in onosPorts:
2081 onosPorts.remove( long( uint64( -2 ) ) )
2082 if len( mnPorts ): # the ports of this switch don't match
2083 switchResult = main.FALSE
2084 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2085 if len( onosPorts ): # the ports of this switch don't match
2086 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002087 main.log.warn(
2088 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002089 str( onosPorts ) )
2090 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002091 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002092 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002093 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002094 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2095 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2096 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002097 finalResults = finalResults and portsResults
2098 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002099
Jon Hallafa8a472015-06-12 14:02:42 -07002100 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002101 """
2102 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002103 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002104
Jon Hallafa8a472015-06-12 14:02:42 -07002105 """
Jon Hall7eb38402015-01-08 17:19:54 -08002106 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002107 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002108 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002109
Jon Halld80cc142015-07-06 13:36:05 -07002110 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002111 for l in links:
2112 try:
2113 node1 = switches[ l[ 'node1' ] ]
2114 node2 = switches[ l[ 'node2' ] ]
2115 enabled = True
2116 for port in node1[ 'ports' ]:
2117 if port[ 'of_port' ] == l[ 'port1' ]:
2118 enabled = enabled and port[ 'enabled' ]
2119 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002120 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002121 enabled = enabled and port[ 'enabled' ]
2122 if enabled:
2123 mnLinks.append( l )
2124 except KeyError:
2125 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002126 if 2 * len( mnLinks ) == len( onos ):
2127 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002128 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002129 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002130 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002131 "Mininet has " + str( len( mnLinks ) ) +
2132 " bidirectional links and ONOS has " +
2133 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002134
Jon Hall7eb38402015-01-08 17:19:54 -08002135 # iterate through MN links and check if an ONOS link exists in
2136 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002137 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002138 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002139 node1 = None
2140 port1 = None
2141 node2 = None
2142 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002143 firstDir = main.FALSE
2144 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002145 for swName, switch in switches.iteritems():
2146 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002147 node1 = switch[ 'dpid' ]
2148 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002149 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002150 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002151 if node1 is not None and node2 is not None:
2152 break
Jon Hallafa8a472015-06-12 14:02:42 -07002153 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002154 node2 = switch[ 'dpid' ]
2155 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002156 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002157 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002158 if node1 is not None and node2 is not None:
2159 break
2160
kelvin-onlabd3b64892015-01-20 13:26:24 -08002161 for onosLink in onos:
2162 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002163 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002164 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002165 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002166 onosPort1 = onosLink[ 'src' ][ 'port' ]
2167 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002168
Jon Hall72cf1dc2014-10-20 21:04:50 -04002169 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002170 if str( onosNode1 ) == str( node1 ) and str(
2171 onosNode2 ) == str( node2 ):
2172 if int( onosPort1 ) == int( port1 ) and int(
2173 onosPort2 ) == int( port2 ):
2174 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002175 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002176 main.log.warn(
2177 'The port numbers do not match for ' +
2178 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002179 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002180 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002181 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002182 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002183 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002184
2185 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002186 elif ( str( onosNode1 ) == str( node2 ) and
2187 str( onosNode2 ) == str( node1 ) ):
2188 if ( int( onosPort1 ) == int( port2 )
2189 and int( onosPort2 ) == int( port1 ) ):
2190 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002191 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002192 main.log.warn(
2193 'The port numbers do not match for ' +
2194 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002195 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002196 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002197 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002198 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002199 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002200 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002201 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002202 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002203 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002204 'ONOS does not have the link %s/%s -> %s/%s' %
2205 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002206 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002207 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002208 'ONOS does not have the link %s/%s -> %s/%s' %
2209 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002210 linkResults = linkResults and firstDir and secondDir
2211 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002212
Jon Hallafa8a472015-06-12 14:02:42 -07002213 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002214 """
Jon Hallafa8a472015-06-12 14:02:42 -07002215 Compare mn and onos Hosts.
2216 Since Mininet hosts are quiet, ONOS will only know of them when they
2217 speak. For this reason, we will only check that the hosts in ONOS
2218 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002219
Jon Hallafa8a472015-06-12 14:02:42 -07002220 Arguments:
2221 hostsJson: parsed json object from the onos hosts api
2222 Returns:
2223 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002224 import json
2225 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002226 for onosHost in hostsJson:
2227 onosMAC = onosHost[ 'mac' ].lower()
2228 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002229 for mnHost, info in hosts.iteritems():
2230 for mnIntf in info[ 'interfaces' ]:
2231 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002232 match = True
2233 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002234 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002235 pass # all is well
2236 else:
2237 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002238 main.log.error( "ONOS host " +
2239 onosHost[ 'id' ] +
2240 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002241 str( onosHost[ 'ipAddresses' ] ) +
2242 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002243 str( ip ) +
2244 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002245 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002246 onosHost,
2247 sort_keys=True,
2248 indent=4,
2249 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002250 main.log.info( output )
2251 hostResults = main.FALSE
2252 if not match:
2253 hostResults = main.FALSE
2254 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2255 "corresponding Mininet host." )
2256 output = json.dumps( onosHost,
2257 sort_keys=True,
2258 indent=4,
2259 separators=( ',', ': ' ) )
2260 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002261 return hostResults
2262
Jon Hallafa8a472015-06-12 14:02:42 -07002263 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002264 """
2265 Returns a list of all hosts
2266 Don't ask questions just use it"""
2267 self.handle.sendline( "" )
2268 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002269
Jon Hall7eb38402015-01-08 17:19:54 -08002270 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2271 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002272
kelvin-onlabd3b64892015-01-20 13:26:24 -08002273 handlePy = self.handle.before
2274 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2275 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002276
Jon Hall7eb38402015-01-08 17:19:54 -08002277 self.handle.sendline( "" )
2278 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002279
kelvin-onlabd3b64892015-01-20 13:26:24 -08002280 hostStr = handlePy.replace( "]", "" )
2281 hostStr = hostStr.replace( "'", "" )
2282 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002283 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002284 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002285
kelvin-onlabd3b64892015-01-20 13:26:24 -08002286 return hostList
adminbae64d82013-08-01 10:50:15 -07002287
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002288 def getSwitch( self ):
2289 """
2290 Returns a list of all switches
2291 Again, don't ask question just use it...
2292 """
2293 # get host list...
2294 hostList = self.getHosts()
2295 # Make host set
2296 hostSet = set( hostList )
2297
2298 # Getting all the nodes in mininet
2299 self.handle.sendline( "" )
2300 self.handle.expect( "mininet>" )
2301
2302 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2303 self.handle.expect( "mininet>" )
2304
2305 handlePy = self.handle.before
2306 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2307 handlePy = handlePy.rstrip()
2308
2309 self.handle.sendline( "" )
2310 self.handle.expect( "mininet>" )
2311
2312 nodesStr = handlePy.replace( "]", "" )
2313 nodesStr = nodesStr.replace( "'", "" )
2314 nodesStr = nodesStr.replace( "[", "" )
2315 nodesStr = nodesStr.replace( " ", "" )
2316 nodesList = nodesStr.split( "," )
2317
2318 nodesSet = set( nodesList )
2319 # discarding default controller(s) node
2320 nodesSet.discard( 'c0' )
2321 nodesSet.discard( 'c1' )
2322 nodesSet.discard( 'c2' )
2323
2324 switchSet = nodesSet - hostSet
2325 switchList = list( switchSet )
2326
2327 return switchList
2328
Jon Hall7eb38402015-01-08 17:19:54 -08002329 def update( self ):
2330 """
2331 updates the port address and status information for
2332 each port in mn"""
2333 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002334 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002335 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002336 self.handle.sendline( "" )
2337 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002338
Jon Hall7eb38402015-01-08 17:19:54 -08002339 self.handle.sendline( "update" )
2340 self.handle.expect( "update" )
2341 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002342
Jon Hall7eb38402015-01-08 17:19:54 -08002343 self.handle.sendline( "" )
2344 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002345
Jon Hallb1290e82014-11-18 16:17:48 -05002346 return main.TRUE
2347 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002348 main.log.error( self.name + ": EOF exception found" )
2349 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002350 main.cleanup()
2351 main.exit()
2352
Jon Halld80cc142015-07-06 13:36:05 -07002353 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002354 """
2355 Add vlan tag to a host.
2356 Dependencies:
2357 This class depends on the "vlan" package
2358 $ sudo apt-get install vlan
2359 Configuration:
2360 Load the 8021q module into the kernel
2361 $sudo modprobe 8021q
2362
2363 To make this setup permanent:
2364 $ sudo su -c 'echo "8021q" >> /etc/modules'
2365 """
2366 if self.handle:
2367 try:
Jon Halld80cc142015-07-06 13:36:05 -07002368 # get the ip address of the host
2369 main.log.info( "Get the ip address of the host" )
2370 ipaddr = self.getIPAddress( host )
2371 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002372
Jon Halld80cc142015-07-06 13:36:05 -07002373 # remove IP from interface intf
2374 # Ex: h1 ifconfig h1-eth0 inet 0
2375 main.log.info( "Remove IP from interface " )
2376 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2377 self.handle.sendline( cmd2 )
2378 self.handle.expect( "mininet>" )
2379 response = self.handle.before
2380 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002381
Jon Halld80cc142015-07-06 13:36:05 -07002382 # create VLAN interface
2383 # Ex: h1 vconfig add h1-eth0 100
2384 main.log.info( "Create Vlan" )
2385 cmd3 = host + " vconfig add " + intf + " " + vlan
2386 self.handle.sendline( cmd3 )
2387 self.handle.expect( "mininet>" )
2388 response = self.handle.before
2389 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002390
Jon Halld80cc142015-07-06 13:36:05 -07002391 # assign the host's IP to the VLAN interface
2392 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2393 main.log.info( "Assign the host IP to the vlan interface" )
2394 vintf = intf + "." + vlan
2395 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2396 self.handle.sendline( cmd4 )
2397 self.handle.expect( "mininet>" )
2398 response = self.handle.before
2399 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002400
2401 return main.TRUE
2402 except pexpect.EOF:
2403 main.log.error( self.name + ": EOF exception found" )
2404 main.log.error( self.name + ": " + self.handle.before )
2405 return main.FALSE
2406
adminbae64d82013-08-01 10:50:15 -07002407if __name__ != "__main__":
2408 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002409 sys.modules[ __name__ ] = MininetCliDriver()