blob: b877d9366076e7b33ec7018b2a6c5a477c955bf5 [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
Jon Hall7eb38402015-01-08 17:19:54 -0800941 def iperf( self, host1, host2 ):
942 main.log.info(
943 self.name +
944 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700945 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800946 cmd1 = 'iperf ' + host1 + " " + host2
947 self.handle.sendline( cmd1 )
948 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800949 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800950 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800951 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800952 return main.TRUE
953 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800954 main.log.error( self.name + ": iperf test failed" )
955 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800956 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800957 main.log.error( self.name + ": EOF exception found" )
958 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800959 main.cleanup()
960 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800961
Jon Hall7eb38402015-01-08 17:19:54 -0800962 def iperfudp( self ):
963 main.log.info(
964 self.name +
965 ": Simple iperf TCP test between two " +
966 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700967 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800968 response = self.execute(
969 cmd='iperfudp',
970 prompt='mininet>',
971 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800972 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800973 main.log.error( self.name + ": EOF exception found" )
974 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700975 main.cleanup()
976 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700977 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800978
Jon Hall7eb38402015-01-08 17:19:54 -0800979 def nodes( self ):
980 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700981 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800982 response = self.execute(
983 cmd='nodes',
984 prompt='mininet>',
985 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800986 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800987 main.log.error( self.name + ": EOF exception found" )
988 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700989 main.cleanup()
990 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700991 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800992
Jon Hall7eb38402015-01-08 17:19:54 -0800993 def pingpair( self ):
994 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700995 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800996 response = self.execute(
997 cmd='pingpair',
998 prompt='mininet>',
999 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001000 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001001 main.log.error( self.name + ": EOF exception found" )
1002 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001003 main.cleanup()
1004 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001005
Jon Hall7eb38402015-01-08 17:19:54 -08001006 if re.search( ',\s0\%\spacket\sloss', response ):
1007 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001008 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -07001009 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001010 else:
1011 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001012 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -07001013 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001014
Jon Hall7eb38402015-01-08 17:19:54 -08001015 def link( self, **linkargs ):
1016 """
1017 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001018 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001019 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1020 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1021 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1022 main.log.info(
1023 "Bring link between '" +
1024 end1 +
1025 "' and '" +
1026 end2 +
1027 "' '" +
1028 option +
1029 "'" )
1030 command = "link " + \
1031 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001032 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001033 self.handle.sendline( command )
1034 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001035 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001036 main.log.error( self.name + ": EOF exception found" )
1037 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001038 main.cleanup()
1039 main.exit()
adminbae64d82013-08-01 10:50:15 -07001040 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001041
Jon Hall7eb38402015-01-08 17:19:54 -08001042 def yank( self, **yankargs ):
1043 """
1044 yank a mininet switch interface to a host"""
1045 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001046 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001047 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1048 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1049 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001050 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001051 response = self.execute(
1052 cmd=command,
1053 prompt="mininet>",
1054 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001055 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001056 main.log.error( self.name + ": EOF exception found" )
1057 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001058 main.cleanup()
1059 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001060 return main.TRUE
1061
Jon Hall7eb38402015-01-08 17:19:54 -08001062 def plug( self, **plugargs ):
1063 """
1064 plug the yanked mininet switch interface to a switch"""
1065 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001066 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001067 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1068 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1069 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001070 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001071 response = self.execute(
1072 cmd=command,
1073 prompt="mininet>",
1074 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001075 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001076 main.log.error( self.name + ": EOF exception found" )
1077 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001078 main.cleanup()
1079 main.exit()
adminbae64d82013-08-01 10:50:15 -07001080 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001081
Jon Hall7eb38402015-01-08 17:19:54 -08001082 def dpctl( self, **dpctlargs ):
1083 """
1084 Run dpctl command on all switches."""
1085 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001086 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001087 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1088 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1089 command = "dpctl " + cmd + " " + str( cmdargs )
1090 try:
1091 response = self.execute(
1092 cmd=command,
1093 prompt="mininet>",
1094 timeout=10 )
1095 except pexpect.EOF:
1096 main.log.error( self.name + ": EOF exception found" )
1097 main.log.error( self.name + ": " + self.handle.before )
1098 main.cleanup()
1099 main.exit()
1100 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001101
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001103 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001104 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001105 fileInput = path + '/lib/Mininet/INSTALL'
1106 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001107 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001108 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001109 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001110 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001111 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001112 return version
adminbae64d82013-08-01 10:50:15 -07001113
kelvin-onlabd3b64892015-01-20 13:26:24 -08001114 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001115 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001116 Parameters:
1117 sw: The name of an OVS switch. Example "s1"
1118 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001119 The output of the command from the mininet cli
1120 or main.FALSE on timeout"""
1121 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001122 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001123 response = self.execute(
1124 cmd=command,
1125 prompt="mininet>",
1126 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001127 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001128 return response
admin2a9548d2014-06-17 14:08:07 -07001129 else:
1130 return main.FALSE
1131 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001132 main.log.error( self.name + ": EOF exception found" )
1133 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001134 main.cleanup()
1135 main.exit()
adminbae64d82013-08-01 10:50:15 -07001136
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001137 def assignSwController( self, sw, ip, port="6633", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001138 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001139 Description:
1140 Assign switches to the controllers ( for ovs use only )
1141 Required:
1142 sw - Name of the switch. This can be a list or a string.
1143 ip - Ip addresses of controllers. This can be a list or a string.
1144 Optional:
1145 port - ONOS use port 6633, if no list of ports is passed, then
1146 the all the controller will use 6633 as their port number
1147 ptcp - ptcp number, This can be a string or a list that has
1148 the same length as switch. This is optional and not required
1149 when using ovs switches.
1150 NOTE: If switches and ptcp are given in a list type they should have the
1151 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1152 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001153
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001154 Return:
1155 Returns main.TRUE if mininet correctly assigned switches to
1156 controllers, otherwise it will return main.FALSE or an appropriate
1157 exception(s)
1158 """
1159 assignResult = main.TRUE
1160 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001161 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001162 command = "sh ovs-vsctl set-controller "
1163 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001164 try:
1165 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001166 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001167 if isinstance( port, types.StringType ) or \
1168 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001169 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001170 elif isinstance( port, types.ListType ):
1171 main.log.error( self.name + ": Only one controller " +
1172 "assigned and a list of ports has" +
1173 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001174 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001175 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001176 main.log.error( self.name + ": Invalid controller port " +
1177 "number. Please specify correct " +
1178 "controller port" )
1179 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001180
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001181 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001182 if isinstance( port, types.StringType ) or \
1183 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001184 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001185 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1186 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001187 elif isinstance( port, types.ListType ):
1188 if ( len( ip ) != len( port ) ):
1189 main.log.error( self.name + ": Port list = " +
1190 str( len( port ) ) +
1191 "should be the same as controller" +
1192 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001193 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001194 else:
1195 onosIp = ""
1196 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001197 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1198 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001199 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001200 main.log.error( self.name + ": Invalid controller port " +
1201 "number. Please specify correct " +
1202 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001203 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001204 else:
1205 main.log.error( self.name + ": Invalid ip address" )
1206 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001207
1208 if isinstance( sw, types.StringType ):
1209 command += sw + " "
1210 if ptcp:
1211 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001212 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001213 elif isinstance( ptcp, types.ListType ):
1214 main.log.error( self.name + ": Only one switch is " +
1215 "being set and multiple PTCP is " +
1216 "being passed " )
1217 else:
1218 main.log.error( self.name + ": Invalid PTCP" )
1219 ptcp = ""
1220 command += onosIp
1221 commandList.append( command )
1222
1223 elif isinstance( sw, types.ListType ):
1224 if ptcp:
1225 if isinstance( ptcp, types.ListType ):
1226 if len( ptcp ) != len( sw ):
1227 main.log.error( self.name + ": PTCP length = " +
1228 str( len( ptcp ) ) +
1229 " is not the same as switch" +
1230 " length = " +
1231 str( len( sw ) ) )
1232 return main.FALSE
1233 else:
1234 for switch, ptcpNum in zip( sw, ptcp ):
1235 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001236 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001237 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001238 tempCmd += onosIp
1239 commandList.append( tempCmd )
1240 else:
1241 main.log.error( self.name + ": Invalid PTCP" )
1242 return main.FALSE
1243 else:
1244 for switch in sw:
1245 tempCmd = "sh ovs-vsctl set-controller "
1246 tempCmd += switch + " " + onosIp
1247 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001248 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001249 main.log.error( self.name + ": Invalid switch type " )
1250 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001251
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001252 for cmd in commandList:
1253 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001254 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001255 except pexpect.TIMEOUT:
1256 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1257 return main.FALSE
1258 except pexpect.EOF:
1259 main.log.error( self.name + ": EOF exception found" )
1260 main.log.error( self.name + ": " + self.handle.before )
1261 main.cleanup()
1262 main.exit()
1263 return main.TRUE
1264 except Exception:
1265 main.log.exception( self.name + ": Uncaught exception!" )
1266 main.cleanup()
1267 main.exit()
adminbae64d82013-08-01 10:50:15 -07001268
kelvin-onlabd3b64892015-01-20 13:26:24 -08001269 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001270 """
1271 Removes the controller target from sw"""
1272 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001273 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001274 response = self.execute(
1275 cmd=command,
1276 prompt="mininet>",
1277 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001278 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001279 main.log.error( self.name + ": EOF exception found" )
1280 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001281 main.cleanup()
1282 main.exit()
1283 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001284 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001285
kelvin-onlabd3b64892015-01-20 13:26:24 -08001286 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001287 """
Jon Hallb1290e82014-11-18 16:17:48 -05001288 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001289 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001290 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001291 NOTE: cannot currently specify what type of switch
1292 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001293 sw = name of the new switch as a string
1294 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001295 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001296 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001297 """
1298 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001299 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001300 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001301 response = self.execute(
1302 cmd=command,
1303 prompt="mininet>",
1304 timeout=10 )
1305 if re.search( "already exists!", response ):
1306 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001307 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001308 elif re.search( "Error", response ):
1309 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001310 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001311 elif re.search( "usage:", response ):
1312 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001313 return main.FALSE
1314 else:
1315 return main.TRUE
1316 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001317 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001318 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001319 main.cleanup()
1320 main.exit()
1321
kelvin-onlabd3b64892015-01-20 13:26:24 -08001322 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001323 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001324 delete a switch from the mininet topology
1325 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001326 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001327 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001328 sw = name of the switch as a string
1329 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001330 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001331 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001332 response = self.execute(
1333 cmd=command,
1334 prompt="mininet>",
1335 timeout=10 )
1336 if re.search( "no switch named", response ):
1337 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001338 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001339 elif re.search( "Error", response ):
1340 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001341 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001342 elif re.search( "usage:", response ):
1343 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001344 return main.FALSE
1345 else:
1346 return main.TRUE
1347 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001348 main.log.error( self.name + ": EOF exception found" )
1349 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001350 main.cleanup()
1351 main.exit()
1352
kelvin-onlabd3b64892015-01-20 13:26:24 -08001353 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001354 """
1355 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001356 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001357 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001358 NOTE: cannot currently specify what type of link
1359 required params:
1360 node1 = the string node name of the first endpoint of the link
1361 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001362 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001363 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001364 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001365 response = self.execute(
1366 cmd=command,
1367 prompt="mininet>",
1368 timeout=10 )
1369 if re.search( "doesnt exist!", response ):
1370 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001371 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001372 elif re.search( "Error", response ):
1373 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001374 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001375 elif re.search( "usage:", response ):
1376 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001377 return main.FALSE
1378 else:
1379 return main.TRUE
1380 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001381 main.log.error( self.name + ": EOF exception found" )
1382 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001383 main.cleanup()
1384 main.exit()
1385
kelvin-onlabd3b64892015-01-20 13:26:24 -08001386 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001387 """
1388 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001389 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001390 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001391 required params:
1392 node1 = the string node name of the first endpoint of the link
1393 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001394 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001395 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001396 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001397 response = self.execute(
1398 cmd=command,
1399 prompt="mininet>",
1400 timeout=10 )
1401 if re.search( "no node named", response ):
1402 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001403 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001404 elif re.search( "Error", response ):
1405 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001406 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001407 elif re.search( "usage:", response ):
1408 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001409 return main.FALSE
1410 else:
1411 return main.TRUE
1412 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001413 main.log.error( self.name + ": EOF exception found" )
1414 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001415 main.cleanup()
1416 main.exit()
1417
kelvin-onlabd3b64892015-01-20 13:26:24 -08001418 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001419 """
Jon Hallb1290e82014-11-18 16:17:48 -05001420 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001421 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001422 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001423 NOTE: cannot currently specify what type of host
1424 required params:
1425 hostname = the string hostname
1426 optional key-value params
1427 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001428 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001429 """
1430 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001431 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001432 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001433 response = self.execute(
1434 cmd=command,
1435 prompt="mininet>",
1436 timeout=10 )
1437 if re.search( "already exists!", 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( "doesnt exists!", response ):
1441 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001442 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001443 elif re.search( "Error", response ):
1444 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001445 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001446 elif re.search( "usage:", response ):
1447 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001448 return main.FALSE
1449 else:
1450 return main.TRUE
1451 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001452 main.log.error( self.name + ": EOF exception found" )
1453 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001454 main.cleanup()
1455 main.exit()
1456
kelvin-onlabd3b64892015-01-20 13:26:24 -08001457 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001458 """
1459 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001460 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001461 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001462 NOTE: this uses a custom mn function
1463 required params:
1464 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001465 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001466 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001467 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001468 response = self.execute(
1469 cmd=command,
1470 prompt="mininet>",
1471 timeout=10 )
1472 if re.search( "no host named", response ):
1473 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001474 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001475 elif re.search( "Error", response ):
1476 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001477 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001478 elif re.search( "usage:", response ):
1479 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001480 return main.FALSE
1481 else:
1482 return main.TRUE
1483 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001484 main.log.error( self.name + ": EOF exception found" )
1485 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001486 main.cleanup()
1487 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001488
Jon Hall7eb38402015-01-08 17:19:54 -08001489 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001490 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001491 Called at the end of the test to stop the mininet and
1492 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001493 """
Jon Halld80cc142015-07-06 13:36:05 -07001494 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001495 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001496 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001497 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001498 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001499 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001500 elif i == 1:
1501 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001502 # print "Disconnecting Mininet"
1503 if self.handle:
1504 self.handle.sendline( "exit" )
1505 self.handle.expect( "exit" )
1506 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001507 else:
1508 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001509 return response
1510
Jon Halld80cc142015-07-06 13:36:05 -07001511 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001512 """
Jon Hall21270ac2015-02-16 17:59:55 -08001513 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001514 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001515 main.FALSE if the pexpect handle does not exist.
1516
Jon Halld61331b2015-02-17 16:35:47 -08001517 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001518 """
Jon Halld61331b2015-02-17 16:35:47 -08001519 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001520 response = ''
1521 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001522 try:
Jon Halld80cc142015-07-06 13:36:05 -07001523 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001524 i = self.handle.expect( [ 'mininet>',
1525 '\$',
1526 pexpect.EOF,
1527 pexpect.TIMEOUT ],
1528 timeout )
1529 if i == 0:
1530 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001531 response = self.execute(
1532 cmd="exit",
1533 prompt="(.*)",
1534 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001535 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001536 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001537 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001538
kelvin-onlab56a3f462015-02-06 14:04:43 -08001539 if i == 1:
1540 main.log.info( " Mininet trying to exit while not " +
1541 "in the mininet prompt" )
1542 elif i == 2:
1543 main.log.error( "Something went wrong exiting mininet" )
1544 elif i == 3: # timeout
1545 main.log.error( "Something went wrong exiting mininet " +
1546 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001547
Hari Krishnab35c6d02015-03-18 11:13:51 -07001548 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001549 self.handle.sendline( "" )
1550 self.handle.expect( '\$' )
1551 self.handle.sendline(
1552 "sudo kill -9 \`ps -ef | grep \"" +
1553 fileName +
1554 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001555 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001556 main.log.error( self.name + ": EOF exception found" )
1557 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001558 main.cleanup()
1559 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001560 else:
1561 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001562 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001563 return response
1564
kelvin-onlabf0594d72015-05-19 17:25:12 -07001565 def arping( self, host="", ip="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001566 """
1567 Description:
1568 Sends arp message from mininet host for hosts discovery
1569 Required:
1570 host - hosts name
1571 Optional:
1572 ip - ip address that does not exist in the network so there would
1573 be no reply.
1574 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001575 if ethDevice:
1576 ethDevice = '-I ' + ethDevice + ' '
Jon Halld80cc142015-07-06 13:36:05 -07001577 cmd = " py " + host + ".cmd(\"arping -c 1 " + ethDevice + ip + "\")"
admin07529932013-11-22 14:58:28 -08001578 try:
kelvin-onlab65782a82015-05-07 14:12:13 -07001579 main.log.warn( "Sending: " + cmd )
1580 self.handle.sendline( cmd )
1581 response = self.handle.before
1582 self.handle.sendline( "" )
1583 self.handle.expect( "mininet>" )
admin07529932013-11-22 14:58:28 -08001584 return main.TRUE
kelvin-onlab65782a82015-05-07 14:12:13 -07001585
1586 except pexpect.EOF:
1587 main.log.error( self.name + ": EOF exception found" )
1588 main.log.error( self.name + ": " + self.handle.before )
1589 main.cleanup()
1590 main.exit()
admin07529932013-11-22 14:58:28 -08001591
Jon Hall7eb38402015-01-08 17:19:54 -08001592 def decToHex( self, num ):
1593 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001594
Jon Hall7eb38402015-01-08 17:19:54 -08001595 def getSwitchFlowCount( self, switch ):
1596 """
1597 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001598 if self.handle:
1599 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1600 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001601 response = self.execute(
1602 cmd=cmd,
1603 prompt="mininet>",
1604 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001605 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001606 main.log.error( self.name + ": EOF exception found" )
1607 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001608 main.cleanup()
1609 main.exit()
1610 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001611 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001612 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001613 main.log.info(
1614 "Couldn't find flows on switch %s, found: %s" %
1615 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001616 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001617 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001618 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001619 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001620
kelvin-onlabd3b64892015-01-20 13:26:24 -08001621 def checkFlows( self, sw, dumpFormat=None ):
1622 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001623 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001624 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001625 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001626 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001627 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001628 response = self.execute(
1629 cmd=command,
1630 prompt="mininet>",
1631 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001632 return response
1633 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001634 main.log.error( self.name + ": EOF exception found" )
1635 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001636 main.cleanup()
1637 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001638
kelvin-onlabd3b64892015-01-20 13:26:24 -08001639 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001640 """
Jon Hallefbd9792015-03-05 16:11:36 -08001641 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001642 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001643 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001644 self.handle.sendline( "" )
1645 self.handle.expect( "mininet>" )
1646 self.handle.sendline(
1647 "sh sudo tcpdump -n -i " +
1648 intf +
1649 " " +
1650 port +
1651 " -w " +
1652 filename.strip() +
1653 " &" )
1654 self.handle.sendline( "" )
1655 i = self.handle.expect( [ 'No\ssuch\device',
1656 'listening\son',
1657 pexpect.TIMEOUT,
1658 "mininet>" ],
1659 timeout=10 )
1660 main.log.warn( self.handle.before + self.handle.after )
1661 self.handle.sendline( "" )
1662 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001663 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001664 main.log.error(
1665 self.name +
1666 ": tcpdump - No such device exists. " +
1667 "tcpdump attempted on: " +
1668 intf )
admin2a9548d2014-06-17 14:08:07 -07001669 return main.FALSE
1670 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001671 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001672 return main.TRUE
1673 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001674 main.log.error(
1675 self.name +
1676 ": tcpdump command timed out! Check interface name," +
1677 " given interface was: " +
1678 intf )
admin2a9548d2014-06-17 14:08:07 -07001679 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001680 elif i == 3:
1681 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001682 return main.TRUE
1683 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001684 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001685 return main.FALSE
1686 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001687 main.log.error( self.name + ": EOF exception found" )
1688 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001689 main.cleanup()
1690 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001691 except Exception:
1692 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001693 main.cleanup()
1694 main.exit()
1695
kelvin-onlabd3b64892015-01-20 13:26:24 -08001696 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001697 """
1698 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001699 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001700 self.handle.sendline( "sh sudo pkill tcpdump" )
1701 self.handle.expect( "mininet>" )
1702 self.handle.sendline( "" )
1703 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001704 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001705 main.log.error( self.name + ": EOF exception found" )
1706 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001707 main.cleanup()
1708 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001709 except Exception:
1710 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001711 main.cleanup()
1712 main.exit()
1713
Jon Halld80cc142015-07-06 13:36:05 -07001714 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001715 """
1716 Read ports from a Mininet switch.
1717
1718 Returns a json structure containing information about the
1719 ports of the given switch.
1720 """
1721 response = self.getInterfaces( nodeName )
1722 # TODO: Sanity check on response. log if no such switch exists
1723 ports = []
1724 for line in response.split( "\n" ):
1725 if not line.startswith( "name=" ):
1726 continue
1727 portVars = {}
1728 for var in line.split( "," ):
1729 key, value = var.split( "=" )
1730 portVars[ key ] = value
1731 isUp = portVars.pop( 'enabled', "True" )
1732 isUp = "True" in isUp
1733 if verbose:
1734 main.log.info( "Reading switch port %s(%s)" %
1735 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1736 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001737 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001738 mac = None
1739 ips = []
1740 ip = portVars[ 'ip' ]
1741 if ip == 'None':
1742 ip = None
1743 ips.append( ip )
1744 name = portVars[ 'name' ]
1745 if name == 'None':
1746 name = None
1747 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
1748 if name == 'lo':
1749 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
1750 else:
1751 portNo = re.search( portRe, name ).group( 'port' )
1752 ports.append( { 'of_port': portNo,
1753 'mac': str( mac ).replace( '\'', '' ),
1754 'name': name,
1755 'ips': ips,
1756 'enabled': isUp } )
1757 return ports
1758
Jon Halld80cc142015-07-06 13:36:05 -07001759 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001760 """
1761 Read switches from Mininet.
1762
1763 Returns a dictionary whose keys are the switch names and the value is
1764 a dictionary containing information about the switch.
1765 """
1766 # FIXME: This currently only works with OVS Switches
1767
1768 # Regex patterns to parse dump output
1769 # Example Switch:
1770 # <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 -07001771 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Hallafa8a472015-06-12 14:02:42 -07001772 swRE = r"<OVSSwitch(\{.*\})?\s(?P<name>[^:]+)\:\s" +\
1773 "(?P<ports>([^,]+,)*[^,\s]+)"
1774 # Update mn port info
1775 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07001776 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001777 dump = self.dump().split( "\n" )
1778 for line in dump:
1779 if line.startswith( "<OVSSwitch" ):
1780 result = re.search( swRE, line, re.I )
1781 name = result.group( 'name' )
1782 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
1783 if verbose:
1784 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
1785 ports = self.getPorts( name )
1786 output[ name ] = { "dpid": dpid, "ports": ports }
1787 return output
1788
Jon Halld80cc142015-07-06 13:36:05 -07001789 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001790 """
1791 Read hosts from Mininet.
1792
1793 Returns a dictionary whose keys are the host names and the value is
1794 a dictionary containing information about the host.
1795 """
1796 # Regex patterns to parse dump output
1797 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
1798 # or <Host h1: pid=12725>
1799 # NOTE: Does not correctly match hosts with multi-links
1800 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
1801 # FIXME: Fix that
1802 hostRE = r"<Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07001803 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07001804 # update mn port info
1805 self.update()
1806 # Get mininet dump
1807 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07001808 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001809 for line in dump:
1810 if line.startswith( "<Host" ):
1811 result = re.search( hostRE, line )
1812 name = result.group( 'name' )
1813 interfaces = []
1814 response = self.getInterfaces( name )
1815 # Populate interface info
1816 for line in response.split( "\n" ):
1817 if line.startswith( "name=" ):
1818 portVars = {}
1819 for var in line.split( "," ):
1820 key, value = var.split( "=" )
1821 portVars[ key ] = value
1822 isUp = portVars.pop( 'enabled', "True" )
1823 isUp = "True" in isUp
1824 if verbose:
1825 main.log.info( "Reading host port %s(%s)" %
1826 ( portVars[ 'name' ],
1827 portVars[ 'mac' ] ) )
1828 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001829 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001830 mac = None
1831 ips = []
1832 ip = portVars[ 'ip' ]
1833 if ip == 'None':
1834 ip = None
1835 ips.append( ip )
1836 intfName = portVars[ 'name' ]
1837 if name == 'None':
1838 name = None
1839 interfaces.append( {
1840 "name": intfName,
1841 "ips": ips,
1842 "mac": str( mac ),
1843 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07001844 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07001845 return hosts
1846
1847 def getLinks( self ):
1848 """
1849 Gathers information about current Mininet links. These links may not
1850 be up if one of the ports is down.
1851
1852 Returns a list of dictionaries with link endpoints.
1853
1854 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07001855 { 'node1': str( node1 name )
1856 'node2': str( node2 name )
1857 'port1': str( port1 of_port )
1858 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07001859 Note: The port number returned is the eth#, not necessarily the of_port
1860 number. In Mininet, for OVS switch, these should be the same. For
1861 hosts, this is just the eth#.
1862 """
1863 self.update()
1864 response = self.links().split( '\n' )
1865
1866 # Examples:
1867 # s1-eth3<->s2-eth1 (OK OK)
1868 # s13-eth3<->h27-eth0 (OK OK)
1869 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
1870 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
1871 links = []
1872 for line in response:
1873 match = re.search( linkRE, line )
1874 if match:
1875 node1 = match.group( 'node1' )
1876 node2 = match.group( 'node2' )
1877 port1 = match.group( 'port1' )
1878 port2 = match.group( 'port2' )
1879 links.append( { 'node1': node1,
1880 'node2': node2,
1881 'port1': port1,
1882 'port2': port2 } )
1883 return links
1884
1885 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001886 """
1887 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07001888 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001889
Jon Hallafa8a472015-06-12 14:02:42 -07001890 Dependencies:
1891 1. numpy - "sudo pip install numpy"
1892 """
1893 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04001894 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001895 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07001896 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08001897 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001898 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08001899 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001900 main.log.error(
1901 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07001902 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001903 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001904 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001905 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001906 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001907 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07001908 onosDPIDs.append(
1909 switch[ 'id' ].replace(
1910 ":",
1911 '' ).replace(
1912 "of",
1913 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001914 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04001915
Jon Hall7eb38402015-01-08 17:19:54 -08001916 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001917 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07001918 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001919 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001920 main.log.error( str( list1 ) )
1921 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001922 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001923 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001924 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001925 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001926 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001927
Jon Hall7eb38402015-01-08 17:19:54 -08001928 # FIXME: this does not look for extra ports in ONOS, only checks that
1929 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08001930 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001931
Jon Hall7eb38402015-01-08 17:19:54 -08001932 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07001933 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08001934 mnPorts = []
1935 onosPorts = []
1936 switchResult = main.TRUE
1937 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001938 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07001939 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001940 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001941 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07001942 if onosSwitch[ 'device' ][ 'id' ].replace(
1943 ':',
1944 '' ).replace(
1945 "of",
1946 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001947 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001948 if port[ 'isEnabled' ]:
1949 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001950 # onosPorts.append( 'local' )
1951 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001952 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001953 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001954 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001955 mnPorts.sort( key=float )
1956 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07001957
kelvin-onlabd3b64892015-01-20 13:26:24 -08001958 mnPortsLog = mnPorts
1959 onosPortsLog = onosPorts
1960 mnPorts = [ x for x in mnPorts ]
1961 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001962
Jon Hall7eb38402015-01-08 17:19:54 -08001963 # TODO: handle other reserved port numbers besides LOCAL
1964 # NOTE: Reserved ports
1965 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1966 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001967 for mnPort in mnPortsLog:
1968 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001969 # don't set results to true here as this is just one of
1970 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001971 mnPorts.remove( mnPort )
1972 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07001973
Jon Hall7eb38402015-01-08 17:19:54 -08001974 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001975 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001976 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001977 if 65534 in mnPorts:
1978 mnPorts.remove( 65534 )
1979 if long( uint64( -2 ) ) in onosPorts:
1980 onosPorts.remove( long( uint64( -2 ) ) )
1981 if len( mnPorts ): # the ports of this switch don't match
1982 switchResult = main.FALSE
1983 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1984 if len( onosPorts ): # the ports of this switch don't match
1985 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001986 main.log.warn(
1987 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001988 str( onosPorts ) )
1989 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07001990 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08001991 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07001992 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001993 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1994 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1995 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07001996 finalResults = finalResults and portsResults
1997 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001998
Jon Hallafa8a472015-06-12 14:02:42 -07001999 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002000 """
2001 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002002 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002003
Jon Hallafa8a472015-06-12 14:02:42 -07002004 """
Jon Hall7eb38402015-01-08 17:19:54 -08002005 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002006 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002007 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002008
Jon Halld80cc142015-07-06 13:36:05 -07002009 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002010 for l in links:
2011 try:
2012 node1 = switches[ l[ 'node1' ] ]
2013 node2 = switches[ l[ 'node2' ] ]
2014 enabled = True
2015 for port in node1[ 'ports' ]:
2016 if port[ 'of_port' ] == l[ 'port1' ]:
2017 enabled = enabled and port[ 'enabled' ]
2018 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002019 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002020 enabled = enabled and port[ 'enabled' ]
2021 if enabled:
2022 mnLinks.append( l )
2023 except KeyError:
2024 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002025 if 2 * len( mnLinks ) == len( onos ):
2026 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002027 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002028 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002029 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002030 "Mininet has " + str( len( mnLinks ) ) +
2031 " bidirectional links and ONOS has " +
2032 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002033
Jon Hall7eb38402015-01-08 17:19:54 -08002034 # iterate through MN links and check if an ONOS link exists in
2035 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002036 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002037 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002038 node1 = None
2039 port1 = None
2040 node2 = None
2041 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002042 firstDir = main.FALSE
2043 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002044 for swName, switch in switches.iteritems():
2045 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002046 node1 = switch[ 'dpid' ]
2047 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002048 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002049 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002050 if node1 is not None and node2 is not None:
2051 break
Jon Hallafa8a472015-06-12 14:02:42 -07002052 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002053 node2 = switch[ 'dpid' ]
2054 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002055 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002056 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002057 if node1 is not None and node2 is not None:
2058 break
2059
kelvin-onlabd3b64892015-01-20 13:26:24 -08002060 for onosLink in onos:
2061 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002062 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002063 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002064 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002065 onosPort1 = onosLink[ 'src' ][ 'port' ]
2066 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002067
Jon Hall72cf1dc2014-10-20 21:04:50 -04002068 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002069 if str( onosNode1 ) == str( node1 ) and str(
2070 onosNode2 ) == str( node2 ):
2071 if int( onosPort1 ) == int( port1 ) and int(
2072 onosPort2 ) == int( port2 ):
2073 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002074 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002075 main.log.warn(
2076 'The port numbers do not match for ' +
2077 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002078 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002079 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002080 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002081 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002082 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002083
2084 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002085 elif ( str( onosNode1 ) == str( node2 ) and
2086 str( onosNode2 ) == str( node1 ) ):
2087 if ( int( onosPort1 ) == int( port2 )
2088 and int( onosPort2 ) == int( port1 ) ):
2089 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002090 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002091 main.log.warn(
2092 'The port numbers do not match for ' +
2093 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002094 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002095 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002096 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002097 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002098 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002099 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002100 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002101 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002102 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002103 'ONOS does not have the link %s/%s -> %s/%s' %
2104 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002105 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002106 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002107 'ONOS does not have the link %s/%s -> %s/%s' %
2108 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002109 linkResults = linkResults and firstDir and secondDir
2110 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002111
Jon Hallafa8a472015-06-12 14:02:42 -07002112 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002113 """
Jon Hallafa8a472015-06-12 14:02:42 -07002114 Compare mn and onos Hosts.
2115 Since Mininet hosts are quiet, ONOS will only know of them when they
2116 speak. For this reason, we will only check that the hosts in ONOS
2117 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002118
Jon Hallafa8a472015-06-12 14:02:42 -07002119 Arguments:
2120 hostsJson: parsed json object from the onos hosts api
2121 Returns:
2122 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002123 import json
2124 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002125 for onosHost in hostsJson:
2126 onosMAC = onosHost[ 'mac' ].lower()
2127 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002128 for mnHost, info in hosts.iteritems():
2129 for mnIntf in info[ 'interfaces' ]:
2130 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002131 match = True
2132 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002133 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002134 pass # all is well
2135 else:
2136 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002137 main.log.error( "ONOS host " +
2138 onosHost[ 'id' ] +
2139 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002140 str( onosHost[ 'ipAddresses' ] ) +
2141 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002142 str( ip ) +
2143 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002144 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002145 onosHost,
2146 sort_keys=True,
2147 indent=4,
2148 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002149 main.log.info( output )
2150 hostResults = main.FALSE
2151 if not match:
2152 hostResults = main.FALSE
2153 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2154 "corresponding Mininet host." )
2155 output = json.dumps( onosHost,
2156 sort_keys=True,
2157 indent=4,
2158 separators=( ',', ': ' ) )
2159 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002160 return hostResults
2161
Jon Hallafa8a472015-06-12 14:02:42 -07002162 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002163 """
2164 Returns a list of all hosts
2165 Don't ask questions just use it"""
2166 self.handle.sendline( "" )
2167 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002168
Jon Hall7eb38402015-01-08 17:19:54 -08002169 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2170 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002171
kelvin-onlabd3b64892015-01-20 13:26:24 -08002172 handlePy = self.handle.before
2173 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2174 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002175
Jon Hall7eb38402015-01-08 17:19:54 -08002176 self.handle.sendline( "" )
2177 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002178
kelvin-onlabd3b64892015-01-20 13:26:24 -08002179 hostStr = handlePy.replace( "]", "" )
2180 hostStr = hostStr.replace( "'", "" )
2181 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002182 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002183 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002184
kelvin-onlabd3b64892015-01-20 13:26:24 -08002185 return hostList
adminbae64d82013-08-01 10:50:15 -07002186
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002187 def getSwitch( self ):
2188 """
2189 Returns a list of all switches
2190 Again, don't ask question just use it...
2191 """
2192 # get host list...
2193 hostList = self.getHosts()
2194 # Make host set
2195 hostSet = set( hostList )
2196
2197 # Getting all the nodes in mininet
2198 self.handle.sendline( "" )
2199 self.handle.expect( "mininet>" )
2200
2201 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2202 self.handle.expect( "mininet>" )
2203
2204 handlePy = self.handle.before
2205 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2206 handlePy = handlePy.rstrip()
2207
2208 self.handle.sendline( "" )
2209 self.handle.expect( "mininet>" )
2210
2211 nodesStr = handlePy.replace( "]", "" )
2212 nodesStr = nodesStr.replace( "'", "" )
2213 nodesStr = nodesStr.replace( "[", "" )
2214 nodesStr = nodesStr.replace( " ", "" )
2215 nodesList = nodesStr.split( "," )
2216
2217 nodesSet = set( nodesList )
2218 # discarding default controller(s) node
2219 nodesSet.discard( 'c0' )
2220 nodesSet.discard( 'c1' )
2221 nodesSet.discard( 'c2' )
2222
2223 switchSet = nodesSet - hostSet
2224 switchList = list( switchSet )
2225
2226 return switchList
2227
Jon Hall7eb38402015-01-08 17:19:54 -08002228 def update( self ):
2229 """
2230 updates the port address and status information for
2231 each port in mn"""
2232 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002233 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002234 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002235 self.handle.sendline( "" )
2236 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002237
Jon Hall7eb38402015-01-08 17:19:54 -08002238 self.handle.sendline( "update" )
2239 self.handle.expect( "update" )
2240 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002241
Jon Hall7eb38402015-01-08 17:19:54 -08002242 self.handle.sendline( "" )
2243 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002244
Jon Hallb1290e82014-11-18 16:17:48 -05002245 return main.TRUE
2246 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002247 main.log.error( self.name + ": EOF exception found" )
2248 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002249 main.cleanup()
2250 main.exit()
2251
Jon Halld80cc142015-07-06 13:36:05 -07002252 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002253 """
2254 Add vlan tag to a host.
2255 Dependencies:
2256 This class depends on the "vlan" package
2257 $ sudo apt-get install vlan
2258 Configuration:
2259 Load the 8021q module into the kernel
2260 $sudo modprobe 8021q
2261
2262 To make this setup permanent:
2263 $ sudo su -c 'echo "8021q" >> /etc/modules'
2264 """
2265 if self.handle:
2266 try:
Jon Halld80cc142015-07-06 13:36:05 -07002267 # get the ip address of the host
2268 main.log.info( "Get the ip address of the host" )
2269 ipaddr = self.getIPAddress( host )
2270 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002271
Jon Halld80cc142015-07-06 13:36:05 -07002272 # remove IP from interface intf
2273 # Ex: h1 ifconfig h1-eth0 inet 0
2274 main.log.info( "Remove IP from interface " )
2275 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2276 self.handle.sendline( cmd2 )
2277 self.handle.expect( "mininet>" )
2278 response = self.handle.before
2279 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002280
Jon Halld80cc142015-07-06 13:36:05 -07002281 # create VLAN interface
2282 # Ex: h1 vconfig add h1-eth0 100
2283 main.log.info( "Create Vlan" )
2284 cmd3 = host + " vconfig add " + intf + " " + vlan
2285 self.handle.sendline( cmd3 )
2286 self.handle.expect( "mininet>" )
2287 response = self.handle.before
2288 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002289
Jon Halld80cc142015-07-06 13:36:05 -07002290 # assign the host's IP to the VLAN interface
2291 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2292 main.log.info( "Assign the host IP to the vlan interface" )
2293 vintf = intf + "." + vlan
2294 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2295 self.handle.sendline( cmd4 )
2296 self.handle.expect( "mininet>" )
2297 response = self.handle.before
2298 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002299
2300 return main.TRUE
2301 except pexpect.EOF:
2302 main.log.error( self.name + ": EOF exception found" )
2303 main.log.error( self.name + ": " + self.handle.before )
2304 return main.FALSE
2305
adminbae64d82013-08-01 10:50:15 -07002306if __name__ != "__main__":
2307 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002308 sys.modules[ __name__ ] = MininetCliDriver()