blob: fd05a41623969c2a0b619645daac8de4d8c8567e [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 Hall1ccf82c2014-10-15 14:55:16 -040039from math import pow
adminbae64d82013-08-01 10:50:15 -070040from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070041
Jon Hall7eb38402015-01-08 17:19:54 -080042
kelvin-onlab50907142015-04-01 13:37:45 -070043class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080044
45 """
46 MininetCliDriver is the basic driver which will handle
47 the Mininet functions"""
48 def __init__( self ):
49 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070050 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080051 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070052 self.home = 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 ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070063 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080064 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070065 for key in self.options:
66 if key == "home":
67 self.home = self.options[ 'home' ]
68 break
69 if self.home is None or self.home == "":
70 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070071
72 try:
73 if os.getenv( str( self.ip_address ) ) != None:
74 self.ip_address = os.getenv( str( self.ip_address ) )
75 else:
76 main.log.info( self.name +
77 ": Trying to connect to " +
78 self.ip_address )
79
80 except KeyError:
81 main.log.info( "Invalid host name," +
82 " connecting to local host instead" )
83 self.ip_address = 'localhost'
84 except Exception as inst:
85 main.log.error( "Uncaught exception: " + str( inst ) )
86
kelvin-onlaba1484582015-02-02 15:46:20 -080087 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070088 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080089 self ).connect(
90 user_name=self.user_name,
91 ip_address=self.ip_address,
92 port=None,
93 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080094
kelvin-onlaba1484582015-02-02 15:46:20 -080095 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080096 main.log.info( "Connection successful to the host " +
97 self.user_name +
98 "@" +
99 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800100 return main.TRUE
101 else:
102 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800103 self.user_name +
104 "@" +
105 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800106 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800107 return main.FALSE
108 except pexpect.EOF:
109 main.log.error( self.name + ": EOF exception found" )
110 main.log.error( self.name + ": " + self.handle.before )
111 main.cleanup()
112 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800113 except Exception:
114 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800115 main.cleanup()
116 main.exit()
117
kelvin-onlab10e8d392015-06-03 13:53:45 -0700118 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800119 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700120 Description:
121 Starts Mininet accepts a topology(.py) file and/or an optional
122 argument, to start the mininet, as a parameter.
123 Can also send regular mininet command to load up desired topology.
124 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
125 Options:
126 topoFile = file path for topology file (.py)
127 args = extra option added when starting the topology from the file
128 mnCmd = Mininet command use to start topology
129 Returns:
130 main.TRUE if the mininet starts successfully, main.FALSE
131 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800132 """
Jon Hall7eb38402015-01-08 17:19:54 -0800133 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700134 # make sure old networks are cleaned up
135 main.log.info( self.name +
136 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800137 self.handle.sendline( "sudo mn -c" )
138 i = self.handle.expect( [ 'password\sfor\s',
139 'Cleanup\scomplete',
140 pexpect.EOF,
141 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800142 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800143 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700144 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800145 main.log.info( self.name + ": Sending sudo password" )
146 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800147 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800148 '\$',
149 pexpect.EOF,
150 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800151 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800152 if i == 1:
153 main.log.info( self.name + ": Clean" )
154 elif i == 2:
155 main.log.error( self.name + ": Connection terminated" )
156 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700157 main.log.error( self.name + ": Something while cleaning " +
158 "Mininet took too long... " )
159 # Craft the string to start mininet
160 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700161 if not mnCmd:
162 if topoFile is None or topoFile == '': # If no file is given
163 main.log.info( self.name + ": building fresh Mininet" )
164 cmdString += "mn "
165 if args is None or args == '':
166 # If no args given, use args from .topo file
167 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700168 " " + self.options[ 'arg2' ] +\
169 " --mac --controller " +\
170 self.options[ 'controller' ] + " " +\
171 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700172 else: # else only use given args
173 pass
174 # TODO: allow use of topo args and method args?
175 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700176 main.log.info(
177 "Starting Mininet from topo file " +
178 topoFile )
kelvin-onlab10e8d392015-06-03 13:53:45 -0700179 cmdString += topoFile + " "
180 if args is None:
181 args = ''
182 # TODO: allow use of args from .topo file?
183 cmdString += args
184 else:
185 main.log.info( "Starting Mininet topology using '" + mnCmd +
186 "' command" )
187 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700188 # Send the command and check if network started
189 self.handle.sendline( "" )
190 self.handle.expect( '\$' )
191 main.log.info( "Sending '" + cmdString + "' to " + self.name )
192 self.handle.sendline( cmdString )
193 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800194 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700195 'Exception',
196 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800197 pexpect.EOF,
198 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700199 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800200 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700201 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800202 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800203 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700204 response = str( self.handle.before +
205 self.handle.after )
206 self.handle.expect( '\$' )
207 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700208 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700209 main.log.error(
210 self.name +
211 ": Launching Mininet failed: " + response )
212 return main.FALSE
213 elif i == 2:
214 self.handle.expect( [ "\n",
215 pexpect.EOF,
216 pexpect.TIMEOUT ],
217 timeout )
218 main.log.info( self.handle.before )
219 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800220 main.log.error( self.name + ": Connection timeout" )
221 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700222 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800223 main.log.error(
224 self.name +
225 ": Something took too long... " )
226 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700227 # Why did we hit this part?
228 main.log.error( "startNet did not return correctly" )
229 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800230 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700231 main.log.error( self.name + ": Connection failed to the host " +
232 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800233 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700234 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800235
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800236 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400237 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800238 # In tree topology, if fanout arg is not given, by default it is 2
239 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400240 fanout = 2
241 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500242 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800243 while( k <= depth - 1 ):
244 count = count + pow( fanout, k )
245 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800246 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800247 while( k <= depth - 2 ):
248 # depth-2 gives you only core links and not considering
249 # edge links as seen by ONOS. If all the links including
250 # edge links are required, do depth-1
251 count = count + pow( fanout, k )
252 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800253 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800254 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800255 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800256
Jon Hall7eb38402015-01-08 17:19:54 -0800257 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800258 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800259 # by default it is 1
260 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400261 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800262 numSwitches = depth
263 numHostsPerSw = fanout
264 totalNumHosts = numSwitches * numHostsPerSw
265 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800266 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800267 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800268 topoDict = { "num_switches": int( numSwitches ),
269 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400270 return topoDict
271
kelvin-onlabd3b64892015-01-20 13:26:24 -0800272 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700273 """
274 Calculate the number of switches and links in a topo."""
275 # TODO: combine this function and numSwitchesNlinks
276 argList = self.options[ 'arg1' ].split( "," )
277 topoArgList = argList[ 0 ].split( " " )
278 argList = map( int, argList[ 1: ] )
279 topoArgList = topoArgList[ 1: ] + argList
280
281 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400282 return topoDict
283
GlennRCf07c44a2015-09-18 13:33:46 -0700284 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800285 """
286 Verifies the reachability of the hosts using pingall command.
287 Optional parameter timeout allows you to specify how long to
288 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700289 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700290 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700291 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700292 ping
293 acceptableFailed - Set the number of acceptable failed pings for the
294 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800295 Returns:
296 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700297 otherwise main.FALSE
298 """
299 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700300 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700301 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700302 if self.handle:
303 main.log.info(
304 self.name +
305 ": Checking reachabilty to the hosts using pingall" )
306 response = ""
307 failedPings = 0
308 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700309 cmd = "pingall"
310 if protocol == "IPv6":
311 cmd = "py net.pingAll6()"
312 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700313 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700314 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700315 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700316 pexpect.EOF,
317 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700318 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700319 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700320 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700321 response += self.handle.before
322 break
323 elif i == 1:
324 response += self.handle.before + self.handle.after
325 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700326 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700327 returnValue = main.FALSE
328 if shortCircuit:
329 main.log.error( self.name +
330 ": Aborting pingall - "
331 + str( failedPings ) +
332 " pings failed" )
333 break
Jon Hall390696c2015-05-05 17:13:41 -0700334 if ( time.time() - startTime ) > timeout:
335 returnValue = main.FALSE
336 main.log.error( self.name +
337 ": Aborting pingall - " +
338 "Function took too long " )
339 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700340 elif i == 2:
341 main.log.error( self.name +
342 ": EOF exception found" )
343 main.log.error( self.name + ": " +
344 self.handle.before )
345 main.cleanup()
346 main.exit()
347 elif i == 3:
348 response += self.handle.before
349 main.log.error( self.name +
350 ": TIMEOUT exception found" )
351 main.log.error( self.name +
352 ": " +
353 str( response ) )
354 # NOTE: Send ctrl-c to make sure pingall is done
355 self.handle.sendline( "\x03" )
356 self.handle.expect( "Interrupt" )
357 self.handle.expect( "mininet>" )
358 break
359 pattern = "Results\:"
360 main.log.info( "Pingall output: " + str( response ) )
361 if re.search( pattern, response ):
362 main.log.info( self.name + ": Pingall finished with "
363 + str( failedPings ) + " failed pings" )
364 return returnValue
365 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700366 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700367 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700368 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700369 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700370 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700371 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700372 main.log.error( self.name + ": Connection failed to the host" )
373 main.cleanup()
374 main.exit()
375 except pexpect.TIMEOUT:
376 if response:
377 main.log.info( "Pingall output: " + str( response ) )
378 main.log.error( self.name + ": pexpect.TIMEOUT found" )
379 return main.FALSE
380 except pexpect.EOF:
381 main.log.error( self.name + ": EOF exception found" )
382 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500383 main.cleanup()
384 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700385
Jon Hall7eb38402015-01-08 17:19:54 -0800386 def fpingHost( self, **pingParams ):
387 """
388 Uses the fping package for faster pinging...
389 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800390 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800391 command = args[ "SRC" ] + \
392 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
393 self.handle.sendline( command )
394 self.handle.expect(
395 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
396 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
397 response = self.handle.before
398 if re.search( ":\s-", response ):
399 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700400 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800401 elif re.search( ":\s\d{1,2}\.\d\d", response ):
402 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700403 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800404 main.log.info( self.name + ": Install fping on mininet machine... " )
405 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700406 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800407
Jon Hall3b489db2015-10-05 14:38:37 -0700408 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400409 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700410 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700411
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400412 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700413 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700414
415 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400416 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700417
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400418 Returns main.FALSE if one or more of hosts specified
419 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700420 wait = int( wait )
421 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400422
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
GlennRC6d506272015-09-25 11:36:07 -0700427 pingResponse = "IPv4 ping across specified hosts\n"
428 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400429 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700430 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400431 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700432 pingList = hostList[ :listIndex ] + \
433 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700434
435 pingResponse += str(str(host) + " -> ")
436
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400437 for temp in pingList:
438 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700439 pingCmd = str( host ) + cmd + str( temp )
Jon Hall3b489db2015-10-05 14:38:37 -0700440 self.handle.sendline( pingCmd, timeout=wait + 1 )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700441 self.handle.expect( "mininet>" )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400442 response = self.handle.before
443 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRCd10d3cc2015-09-24 12:47:16 -0700444 pingResponse += str(" h" + str( temp[1:] ))
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400445 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700446 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400447 # One of the host to host pair is unreachable
448 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700449 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700450 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700451 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700453 except pexpect.TIMEOUT:
454 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700455 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400456 except pexpect.EOF:
457 main.log.error( self.name + ": EOF exception found" )
458 main.log.error( self.name + ": " + self.handle.before )
459 main.cleanup()
460 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700461 except Exception:
462 main.log.exception( self.name + ": Uncaught exception!" )
463 main.cleanup()
464 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400465
Jon Hall3b489db2015-10-05 14:38:37 -0700466 def pingIpv6Hosts( self, hostList, prefix='1000::', wait=1 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700467 """
Jon Hall3b489db2015-10-05 14:38:37 -0700468 IPv6 ping all hosts in hostList. If no prefix passed this will use
469 default prefix of 1000::
Hari Krishna9592fc82015-07-31 15:11:15 -0700470
Jon Hall3b489db2015-10-05 14:38:37 -0700471 Returns main.TRUE if all hosts specified can reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700472
Jon Hall3b489db2015-10-05 14:38:37 -0700473 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700474 """
475 try:
476 main.log.info( "Testing reachability between specified IPv6 hosts" )
477 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700478 wait = int( wait )
479 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700480 pingResponse = "IPv6 Pingall output:\n"
481 failedPings = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700482 for host in hostList:
483 listIndex = hostList.index( host )
484 # List of hosts to ping other than itself
485 pingList = hostList[ :listIndex ] + \
486 hostList[ ( listIndex + 1 ): ]
487
GlennRC2cf7d952015-09-11 16:32:13 -0700488 pingResponse += str(str(host) + " -> ")
489
Hari Krishna9592fc82015-07-31 15:11:15 -0700490 for temp in pingList:
491 # Current host pings all other hosts specified
492 pingCmd = str( host ) + cmd + prefix + str( temp[1:] )
Jon Hall3b489db2015-10-05 14:38:37 -0700493 self.handle.sendline( pingCmd, timeout=wait + 1 )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700494 self.handle.expect( "mininet>" )
Hari Krishna9592fc82015-07-31 15:11:15 -0700495 response = self.handle.before
496 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700497 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700498 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700499 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700500 # One of the host to host pair is unreachable
501 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700502 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700503 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700504 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700505 return isReachable
506
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700507 except pexpect.TIMEOUT:
508 main.log.exception( self.name + ": TIMEOUT exception" )
509 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700510 except pexpect.EOF:
511 main.log.error( self.name + ": EOF exception found" )
512 main.log.error( self.name + ": " + self.handle.before )
513 main.cleanup()
514 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700515 except Exception:
516 main.log.exception( self.name + ": Uncaught exception!" )
517 main.cleanup()
518 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700519
Jon Hall7eb38402015-01-08 17:19:54 -0800520 def pingHost( self, **pingParams ):
521 """
Jon Hall3b489db2015-10-05 14:38:37 -0700522 Ping from one mininet host to another
523 Currently the only supported Params: SRC, TARGET, and WAIT
524 """
525 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
526 wait = args['WAIT']
527 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800528 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700529 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700530 try:
Jon Hall61282e32015-03-19 11:34:11 -0700531 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800532 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700533 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
534 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700535 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800536 main.log.error(
537 self.name +
538 ": timeout when waiting for response from mininet" )
539 main.log.error( "response: " + str( self.handle.before ) )
540 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700541 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800542 main.log.error(
543 self.name +
544 ": timeout when waiting for response from mininet" )
545 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700546 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700547 if re.search( ',\s0\%\spacket\sloss', response ):
548 main.log.info( self.name + ": no packets lost, host is reachable" )
549 return main.TRUE
550 else:
551 main.log.error(
552 self.name +
553 ": PACKET LOST, HOST IS NOT REACHABLE" )
554 return main.FALSE
555
Jon Hallfbc828e2015-01-06 17:30:19 -0800556 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800557 main.log.error( self.name + ": EOF exception found" )
558 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700559 main.cleanup()
560 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700561 except Exception:
562 main.log.exception( self.name + ": Uncaught exception!" )
563 main.cleanup()
564 main.exit()
565
566 def ping6pair( self, **pingParams ):
567 """
GlennRC2cf7d952015-09-11 16:32:13 -0700568 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700569 Currently the only supported Params are: SRC, TARGET, and WAIT
Hari Krishna012a1c12015-08-25 14:23:58 -0700570 FLOWLABEL and -I (src interface) will be added later after running some tests.
571 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
572 """
Jon Hall3b489db2015-10-05 14:38:37 -0700573 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
574 wait = args['WAIT']
575 wait = int( wait if wait else 1 )
576 command = args[ "SRC" ] + " ping " + \
577 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700578 try:
579 main.log.info( "Sending: " + command )
580 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700581 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
582 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700583 if i == 1:
584 main.log.error(
585 self.name +
586 ": timeout when waiting for response from mininet" )
587 main.log.error( "response: " + str( self.handle.before ) )
588 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
589 if i == 1:
590 main.log.error(
591 self.name +
592 ": timeout when waiting for response from mininet" )
593 main.log.error( "response: " + str( self.handle.before ) )
594 response = self.handle.before
595 main.log.info( self.name + ": Ping Response: " + response )
596 if re.search( ',\s0\%\spacket\sloss', response ):
597 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700598 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700599 else:
600 main.log.error(
601 self.name +
602 ": PACKET LOST, HOST IS NOT REACHABLE" )
603 return main.FALSE
604
605 except pexpect.EOF:
606 main.log.error( self.name + ": EOF exception found" )
607 main.log.error( self.name + ": " + self.handle.before )
608 main.cleanup()
609 main.exit()
610 except Exception:
611 main.log.exception( self.name + ": Uncaught exception!" )
612 main.cleanup()
613 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800614
Jon Hall7eb38402015-01-08 17:19:54 -0800615 def checkIP( self, host ):
616 """
617 Verifies the host's ip configured or not."""
618 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700619 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800620 response = self.execute(
621 cmd=host +
622 " ifconfig",
623 prompt="mininet>",
624 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800625 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800626 main.log.error( self.name + ": EOF exception found" )
627 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700628 main.cleanup()
629 main.exit()
adminbae64d82013-08-01 10:50:15 -0700630
Jon Hall7eb38402015-01-08 17:19:54 -0800631 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800632 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
633 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
634 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
635 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
636 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800637 # pattern = "inet addr:10.0.0.6"
638 if re.search( pattern, response ):
639 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700640 return main.TRUE
641 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800642 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700643 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800644 else:
645 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800646
Jon Hall7eb38402015-01-08 17:19:54 -0800647 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800648 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700649 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800650 response = self.execute(
651 cmd="h1 /usr/sbin/sshd -D&",
652 prompt="mininet>",
653 timeout=10 )
654 response = self.execute(
655 cmd="h4 /usr/sbin/sshd -D&",
656 prompt="mininet>",
657 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700658 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800659 vars( self )[ key ] = connectargs[ key ]
660 response = self.execute(
661 cmd="xterm h1 h4 ",
662 prompt="mininet>",
663 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800664 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800665 main.log.error( self.name + ": EOF exception found" )
666 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700667 main.cleanup()
668 main.exit()
adminbae64d82013-08-01 10:50:15 -0700669 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800670 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700671 if self.flag == 0:
672 self.flag = 1
673 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800674 else:
adminbae64d82013-08-01 10:50:15 -0700675 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800676
kelvin-onlaba1484582015-02-02 15:46:20 -0800677 def moveHost( self, host, oldSw, newSw, ):
678 """
679 Moves a host from one switch to another on the fly
680 Note: The intf between host and oldSw when detached
681 using detach(), will still show up in the 'net'
682 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700683 ( which is correct behavior since the interfaces
684 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800685 """
686 if self.handle:
687 try:
688 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700689 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800690 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800691 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800692 response = self.execute( cmd=cmd,
693 prompt="mininet>",
694 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700695
kelvin-onlaba1484582015-02-02 15:46:20 -0800696 # Determine hostintf and Oldswitchintf
697 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800698 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800699 print "cmd2= ", cmd
700 self.handle.sendline( cmd )
701 self.handle.expect( "mininet>" )
702
shahshreya73537862015-02-11 15:15:24 -0800703 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800704 cmd = "px ipaddr = hintf.IP()"
705 print "cmd3= ", cmd
706 self.handle.sendline( cmd )
707 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800708
709 cmd = "px macaddr = hintf.MAC()"
710 print "cmd3= ", cmd
711 self.handle.sendline( cmd )
712 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700713
kelvin-onlaba1484582015-02-02 15:46:20 -0800714 # Detach interface between oldSw-host
715 cmd = "px " + oldSw + ".detach( sintf )"
716 print "cmd4= ", cmd
717 self.handle.sendline( cmd )
718 self.handle.expect( "mininet>" )
719
720 # Add link between host-newSw
721 cmd = "py net.addLink(" + host + "," + newSw + ")"
722 print "cmd5= ", cmd
723 self.handle.sendline( cmd )
724 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700725
kelvin-onlaba1484582015-02-02 15:46:20 -0800726 # Determine hostintf and Newswitchintf
727 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800728 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800729 print "cmd6= ", cmd
730 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700731 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800732
733 # Attach interface between newSw-host
734 cmd = "px " + newSw + ".attach( sintf )"
735 print "cmd3= ", cmd
736 self.handle.sendline( cmd )
737 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700738
kelvin-onlaba1484582015-02-02 15:46:20 -0800739 # Set ipaddress of the host-newSw interface
740 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
741 print "cmd7 = ", cmd
742 self.handle.sendline( cmd )
743 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800744
745 # Set macaddress of the host-newSw interface
746 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
747 print "cmd8 = ", cmd
748 self.handle.sendline( cmd )
749 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700750
kelvin-onlaba1484582015-02-02 15:46:20 -0800751 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800752 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800753 self.handle.sendline( cmd )
754 self.handle.expect( "mininet>" )
755 print "output = ", self.handle.before
756
757 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800758 cmd = host + " ifconfig"
759 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800760 self.handle.sendline( cmd )
761 self.handle.expect( "mininet>" )
762 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700763
kelvin-onlaba1484582015-02-02 15:46:20 -0800764 return main.TRUE
765 except pexpect.EOF:
766 main.log.error( self.name + ": EOF exception found" )
767 main.log.error( self.name + ": " + self.handle.before )
768 return main.FALSE
769
Jon Hall7eb38402015-01-08 17:19:54 -0800770 def changeIP( self, host, intf, newIP, newNetmask ):
771 """
772 Changes the ip address of a host on the fly
773 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800774 if self.handle:
775 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800776 cmd = host + " ifconfig " + intf + " " + \
777 newIP + " " + 'netmask' + " " + newNetmask
778 self.handle.sendline( cmd )
779 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800780 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800781 main.log.info( "response = " + response )
782 main.log.info(
783 "Ip of host " +
784 host +
785 " changed to new IP " +
786 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800787 return main.TRUE
788 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800789 main.log.error( self.name + ": EOF exception found" )
790 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800791 return main.FALSE
792
Jon Hall7eb38402015-01-08 17:19:54 -0800793 def changeDefaultGateway( self, host, newGW ):
794 """
795 Changes the default gateway of a host
796 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800797 if self.handle:
798 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800799 cmd = host + " route add default gw " + newGW
800 self.handle.sendline( cmd )
801 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800802 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800803 main.log.info( "response = " + response )
804 main.log.info(
805 "Default gateway of host " +
806 host +
807 " changed to " +
808 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800809 return main.TRUE
810 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800811 main.log.error( self.name + ": EOF exception found" )
812 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800813 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800814
Jon Hall7eb38402015-01-08 17:19:54 -0800815 def addStaticMACAddress( self, host, GW, macaddr ):
816 """
Jon Hallefbd9792015-03-05 16:11:36 -0800817 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800818 if self.handle:
819 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800820 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
821 cmd = host + " arp -s " + GW + " " + macaddr
822 self.handle.sendline( cmd )
823 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800824 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800825 main.log.info( "response = " + response )
826 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800827 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800828 GW +
829 " changed to " +
830 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800831 return main.TRUE
832 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800833 main.log.error( self.name + ": EOF exception found" )
834 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800835 return main.FALSE
836
Jon Hall7eb38402015-01-08 17:19:54 -0800837 def verifyStaticGWandMAC( self, host ):
838 """
839 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800840 if self.handle:
841 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800842 # h1 arp -an
843 cmd = host + " arp -an "
844 self.handle.sendline( cmd )
845 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800846 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800847 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800848 return main.TRUE
849 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800850 main.log.error( self.name + ": EOF exception found" )
851 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800852 return main.FALSE
853
Jon Hall7eb38402015-01-08 17:19:54 -0800854 def getMacAddress( self, host ):
855 """
856 Verifies the host's ip configured or not."""
857 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700858 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800859 response = self.execute(
860 cmd=host +
861 " ifconfig",
862 prompt="mininet>",
863 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800864 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800865 main.log.error( self.name + ": EOF exception found" )
866 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700867 main.cleanup()
868 main.exit()
adminbae64d82013-08-01 10:50:15 -0700869
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700870 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800871 macAddressSearch = re.search( pattern, response, re.I )
872 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800873 main.log.info(
874 self.name +
875 ": Mac-Address of Host " +
876 host +
877 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800878 macAddress )
879 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700880 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800881 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700882
Jon Hall7eb38402015-01-08 17:19:54 -0800883 def getInterfaceMACAddress( self, host, interface ):
884 """
885 Return the IP address of the interface on the given host"""
886 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700887 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800888 response = self.execute( cmd=host + " ifconfig " + interface,
889 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800890 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800891 main.log.error( self.name + ": EOF exception found" )
892 main.log.error( self.name + ": " + self.handle.before )
893 main.cleanup()
894 main.exit()
895
896 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800897 macAddressSearch = re.search( pattern, response, re.I )
898 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800899 main.log.info( "No mac address found in %s" % response )
900 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800901 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800902 main.log.info(
903 "Mac-Address of " +
904 host +
905 ":" +
906 interface +
907 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800908 macAddress )
909 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800910 else:
911 main.log.error( "Connection failed to the host" )
912
913 def getIPAddress( self, host ):
914 """
915 Verifies the host's ip configured or not."""
916 if self.handle:
917 try:
918 response = self.execute(
919 cmd=host +
920 " ifconfig",
921 prompt="mininet>",
922 timeout=10 )
923 except pexpect.EOF:
924 main.log.error( self.name + ": EOF exception found" )
925 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700926 main.cleanup()
927 main.exit()
adminbae64d82013-08-01 10:50:15 -0700928
929 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800930 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800931 main.log.info(
932 self.name +
933 ": IP-Address of Host " +
934 host +
935 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800936 ipAddressSearch.group( 1 ) )
937 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800938 else:
939 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800940
Jon Hall7eb38402015-01-08 17:19:54 -0800941 def getSwitchDPID( self, switch ):
942 """
943 return the datapath ID of the switch"""
944 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700945 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700946 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800947 response = self.execute(
948 cmd=cmd,
949 prompt="mininet>",
950 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800951 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800952 main.log.error( self.name + ": EOF exception found" )
953 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700954 main.cleanup()
955 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800956 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800957 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700958 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800959 main.log.info(
960 "Couldn't find DPID for switch %s, found: %s" %
961 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700962 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800963 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700964 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800965 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700966
Jon Hall7eb38402015-01-08 17:19:54 -0800967 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700968 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800969 self.handle.sendline( "" )
970 self.expect( "mininet>" )
971 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700972 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800973 response = self.execute(
974 cmd=cmd,
975 prompt="mininet>",
976 timeout=10 )
977 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700978 response = self.handle.before
979 return response
980 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800981 main.log.error( self.name + ": EOF exception found" )
982 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700983 main.cleanup()
984 main.exit()
985
Jon Hall7eb38402015-01-08 17:19:54 -0800986 def getInterfaces( self, node ):
987 """
988 return information dict about interfaces connected to the node"""
989 if self.handle:
990 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800991 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700992 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700993 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800994 response = self.execute(
995 cmd=cmd,
996 prompt="mininet>",
997 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800998 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800999 main.log.error( self.name + ": EOF exception found" )
1000 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001001 main.cleanup()
1002 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001003 return response
1004 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001005 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001006
Jon Hall7eb38402015-01-08 17:19:54 -08001007 def dump( self ):
1008 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001009 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001010 response = self.execute(
1011 cmd='dump',
1012 prompt='mininet>',
1013 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001014 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001015 main.log.error( self.name + ": EOF exception found" )
1016 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001017 main.cleanup()
1018 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001019 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001020
Jon Hall7eb38402015-01-08 17:19:54 -08001021 def intfs( self ):
1022 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001023 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001024 response = self.execute(
1025 cmd='intfs',
1026 prompt='mininet>',
1027 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001028 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001029 main.log.error( self.name + ": EOF exception found" )
1030 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001031 main.cleanup()
1032 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001033 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001034
Jon Hall7eb38402015-01-08 17:19:54 -08001035 def net( self ):
1036 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001037 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001038 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001039 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001040 main.log.error( self.name + ": EOF exception found" )
1041 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001042 main.cleanup()
1043 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001044 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001045
Jon Hallafa8a472015-06-12 14:02:42 -07001046 def links( self ):
1047 main.log.info( self.name + ": List network links" )
1048 try:
1049 response = self.execute( cmd='links', prompt='mininet>',
Jon Hall3b489db2015-10-05 14:38:37 -07001050 timeout=20 )
Jon Hallafa8a472015-06-12 14:02:42 -07001051 except pexpect.EOF:
1052 main.log.error( self.name + ": EOF exception found" )
1053 main.log.error( self.name + ": " + self.handle.before )
1054 main.cleanup()
1055 main.exit()
1056 return response
1057
GlennRC61321f22015-07-16 13:36:54 -07001058 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001059 '''
1060 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001061
kelvin-onlab7cce9382015-07-17 10:21:03 -07001062 @parm:
1063 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1064 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1065 '''
1066 for host1 in hosts:
1067 for host2 in hosts:
1068 if host1 != host2:
1069 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1070 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001071
1072 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001073 '''
1074 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1075 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001076
kelvin-onlab7cce9382015-07-17 10:21:03 -07001077 @parm:
1078 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1079 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1080 '''
1081 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1082 try:
1083 # Setup the mininet command
1084 cmd1 = 'iperf ' + host1 + " " + host2
1085 self.handle.sendline( cmd1 )
1086 outcome = self.handle.expect( "mininet>", timeout )
1087 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001088
kelvin-onlab7cce9382015-07-17 10:21:03 -07001089 # checks if there are results in the mininet response
1090 if "Results:" in response:
1091 main.log.report(self.name + ": iperf test completed")
1092 # parse the mn results
1093 response = response.split("\r\n")
1094 response = response[len(response)-2]
1095 response = response.split(": ")
1096 response = response[len(response)-1]
1097 response = response.replace("[", "")
1098 response = response.replace("]", "")
1099 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001100
kelvin-onlab7cce9382015-07-17 10:21:03 -07001101 # this is the bandwith two and from the two hosts
1102 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001103
kelvin-onlab7cce9382015-07-17 10:21:03 -07001104 # there should be two elements in the bandwidth list
1105 # ['host1 to host2', 'host2 to host1"]
1106 if len(bandwidth) == 2:
1107 main.log.report(self.name + ": iperf test successful")
1108 return main.TRUE
1109 else:
1110 main.log.error(self.name + ": invalid iperf results")
1111 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001112 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001113 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001114 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001115 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001116 main.log.error( self.name + ": TIMEOUT exception found" )
1117 main.log.error( self.name + " response: " +
1118 repr ( self.handle.before ) )
1119 # NOTE: Send ctrl-c to make sure iperf is done
1120 self.handle.sendline( "\x03" )
1121 self.handle.expect( "Interrupt" )
1122 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001123 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001124 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001125 main.log.error( self.name + ": EOF exception found" )
1126 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001127 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001128 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001129
1130 def iperfudpAll(self, hosts, bandwidth="10M"):
1131 '''
1132 Runs the iperfudp function with a given set of hosts and specified
1133 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001134
GlennRC61321f22015-07-16 13:36:54 -07001135 @param:
1136 bandwidth: the targeted bandwidth, in megabits ('M')
1137 '''
1138 for host1 in hosts:
1139 for host2 in hosts:
1140 if host1 != host2:
1141 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1142 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1143
1144 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1145
kelvin-onlab7cce9382015-07-17 10:21:03 -07001146 '''
1147 Creates an iperf UDP test with a specific bandwidth.
1148 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001149
kelvin-onlab7cce9382015-07-17 10:21:03 -07001150 @param:
1151 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1152 '''
1153 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1154 try:
1155 # setup the mininet command
1156 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1157 self.handle.sendline(cmd)
1158 self.handle.expect("mininet>")
1159 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001160
kelvin-onlab7cce9382015-07-17 10:21:03 -07001161 # check if there are in results in the mininet response
1162 if "Results:" in response:
1163 main.log.report(self.name + ": iperfudp test completed")
1164 # parse the results
1165 response = response.split("\r\n")
1166 response = response[len(response)-2]
1167 response = response.split(": ")
1168 response = response[len(response)-1]
1169 response = response.replace("[", "")
1170 response = response.replace("]", "")
1171 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001172
kelvin-onlab7cce9382015-07-17 10:21:03 -07001173 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001174
kelvin-onlab7cce9382015-07-17 10:21:03 -07001175 # check to see if there are at least three entries
1176 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1177 if len(mnBandwidth) == 3:
1178 # if one entry is blank then something is wrong
1179 for item in mnBandwidth:
1180 if item == "":
1181 main.log.error(self.name + ": Could not parse iperf output")
1182 main.log.error(self.name + ": invalid iperfudp results")
1183 return main.FALSE
1184 # otherwise results are vaild
1185 main.log.report(self.name + ": iperfudp test successful")
1186 return main.TRUE
1187 else:
1188 main.log.error(self.name + ": invalid iperfudp results")
1189 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001190
kelvin-onlab7cce9382015-07-17 10:21:03 -07001191 except pexpect.EOF:
1192 main.log.error( self.name + ": EOF exception found" )
1193 main.log.error( self.name + ": " + self.handle.before )
1194 main.cleanup()
1195 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001196
Jon Hall7eb38402015-01-08 17:19:54 -08001197 def nodes( self ):
1198 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001199 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001200 response = self.execute(
1201 cmd='nodes',
1202 prompt='mininet>',
1203 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001204 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001205 main.log.error( self.name + ": EOF exception found" )
1206 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001207 main.cleanup()
1208 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001209 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001210
Jon Hall7eb38402015-01-08 17:19:54 -08001211 def pingpair( self ):
1212 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001213 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001214 response = self.execute(
1215 cmd='pingpair',
1216 prompt='mininet>',
1217 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001218 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001219 main.log.error( self.name + ": EOF exception found" )
1220 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001221 main.cleanup()
1222 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001223
Jon Hall7eb38402015-01-08 17:19:54 -08001224 if re.search( ',\s0\%\spacket\sloss', response ):
1225 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001226 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001227 else:
1228 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001229 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001230
Jon Hall7eb38402015-01-08 17:19:54 -08001231 def link( self, **linkargs ):
1232 """
1233 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001234 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001235 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1236 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1237 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1238 main.log.info(
1239 "Bring link between '" +
1240 end1 +
1241 "' and '" +
1242 end2 +
1243 "' '" +
1244 option +
1245 "'" )
1246 command = "link " + \
1247 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001248 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001249 self.handle.sendline( command )
1250 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001251 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001252 main.log.error( self.name + ": EOF exception found" )
1253 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001254 main.cleanup()
1255 main.exit()
adminbae64d82013-08-01 10:50:15 -07001256 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001257
pingping-lin8244a3b2015-09-16 13:36:56 -07001258 def switch( self, **switchargs ):
1259 """
1260 start/stop a switch
1261 """
1262 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1263 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1264 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1265 command = "switch " + str( sw ) + " " + str( option )
1266 main.log.info( command )
1267 try:
1268 self.handle.sendline( command )
1269 self.handle.expect( "mininet>" )
1270 except pexpect.TIMEOUT:
1271 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1272 main.cleanup()
1273 main.exit()
1274 except pexpect.EOF:
1275 main.log.error( self.name + ": EOF exception found" )
1276 main.log.error( self.name + ": " + self.handle.before )
1277 main.cleanup()
1278 main.exit()
1279 return main.TRUE
1280
pingping-lin5bb663b2015-09-24 11:47:50 -07001281 def node( self, nodeName, commandStr ):
1282 """
1283 Carry out a command line on a given node
1284 @parm:
1285 nodeName: the node name in Mininet testbed
1286 commandStr: the command line will be carried out on the node
1287 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1288 """
1289 command = str( nodeName ) + " " + str( commandStr )
1290 main.log.info( command )
1291
1292 try:
1293 response = self.execute( cmd = command, prompt = "mininet>" )
1294 if re.search( "Unknown command", response ):
1295 main.log.warn( response )
1296 return main.FALSE
1297 except pexpect.TIMEOUT:
1298 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1299 main.cleanup()
1300 main.exit()
1301 except pexpect.EOF:
1302 main.log.error( self.name + ": EOF exception found" )
1303 main.log.error( self.name + ": " + self.handle.before )
1304 main.cleanup()
1305 main.exit()
1306 main.log.info( " response is :" )
1307 main.log.info( response )
1308 return response
1309
Jon Hall7eb38402015-01-08 17:19:54 -08001310 def yank( self, **yankargs ):
1311 """
1312 yank a mininet switch interface to a host"""
1313 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001314 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001315 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1316 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1317 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001318 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001319 response = self.execute(
1320 cmd=command,
1321 prompt="mininet>",
1322 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001323 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001324 main.log.error( self.name + ": EOF exception found" )
1325 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001326 main.cleanup()
1327 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001328 return main.TRUE
1329
Jon Hall7eb38402015-01-08 17:19:54 -08001330 def plug( self, **plugargs ):
1331 """
1332 plug the yanked mininet switch interface to a switch"""
1333 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001334 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001335 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1336 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1337 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001338 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001339 response = self.execute(
1340 cmd=command,
1341 prompt="mininet>",
1342 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001343 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001344 main.log.error( self.name + ": EOF exception found" )
1345 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001346 main.cleanup()
1347 main.exit()
adminbae64d82013-08-01 10:50:15 -07001348 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001349
Jon Hall7eb38402015-01-08 17:19:54 -08001350 def dpctl( self, **dpctlargs ):
1351 """
1352 Run dpctl command on all switches."""
1353 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001354 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001355 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1356 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1357 command = "dpctl " + cmd + " " + str( cmdargs )
1358 try:
1359 response = self.execute(
1360 cmd=command,
1361 prompt="mininet>",
1362 timeout=10 )
1363 except pexpect.EOF:
1364 main.log.error( self.name + ": EOF exception found" )
1365 main.log.error( self.name + ": " + self.handle.before )
1366 main.cleanup()
1367 main.exit()
1368 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001369
kelvin-onlabd3b64892015-01-20 13:26:24 -08001370 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001371 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001372 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001373 fileInput = path + '/lib/Mininet/INSTALL'
1374 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001375 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001376 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001377 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001378 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001379 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001380 return version
adminbae64d82013-08-01 10:50:15 -07001381
kelvin-onlabd3b64892015-01-20 13:26:24 -08001382 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001383 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001384 Parameters:
1385 sw: The name of an OVS switch. Example "s1"
1386 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001387 The output of the command from the mininet cli
1388 or main.FALSE on timeout"""
1389 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001390 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001391 response = self.execute(
1392 cmd=command,
1393 prompt="mininet>",
1394 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001395 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001396 return response
admin2a9548d2014-06-17 14:08:07 -07001397 else:
1398 return main.FALSE
1399 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001400 main.log.error( self.name + ": EOF exception found" )
1401 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001402 main.cleanup()
1403 main.exit()
adminbae64d82013-08-01 10:50:15 -07001404
Charles Chan029be652015-08-24 01:46:10 +08001405 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001406 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001407 Description:
1408 Assign switches to the controllers ( for ovs use only )
1409 Required:
1410 sw - Name of the switch. This can be a list or a string.
1411 ip - Ip addresses of controllers. This can be a list or a string.
1412 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001413 port - ONOS use port 6653, if no list of ports is passed, then
1414 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001415 ptcp - ptcp number, This can be a string or a list that has
1416 the same length as switch. This is optional and not required
1417 when using ovs switches.
1418 NOTE: If switches and ptcp are given in a list type they should have the
1419 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1420 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001421
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001422 Return:
1423 Returns main.TRUE if mininet correctly assigned switches to
1424 controllers, otherwise it will return main.FALSE or an appropriate
1425 exception(s)
1426 """
1427 assignResult = main.TRUE
1428 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001429 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001430 command = "sh ovs-vsctl set-controller "
1431 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001432 try:
1433 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001434 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001435 if isinstance( port, types.StringType ) or \
1436 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001437 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001438 elif isinstance( port, types.ListType ):
1439 main.log.error( self.name + ": Only one controller " +
1440 "assigned and a list of ports has" +
1441 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001442 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001443 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001444 main.log.error( self.name + ": Invalid controller port " +
1445 "number. Please specify correct " +
1446 "controller port" )
1447 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001448
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001449 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001450 if isinstance( port, types.StringType ) or \
1451 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001452 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001453 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1454 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001455 elif isinstance( port, types.ListType ):
1456 if ( len( ip ) != len( port ) ):
1457 main.log.error( self.name + ": Port list = " +
1458 str( len( port ) ) +
1459 "should be the same as controller" +
1460 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001461 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001462 else:
1463 onosIp = ""
1464 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001465 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1466 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001467 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001468 main.log.error( self.name + ": Invalid controller port " +
1469 "number. Please specify correct " +
1470 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001471 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001472 else:
1473 main.log.error( self.name + ": Invalid ip address" )
1474 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001475
1476 if isinstance( sw, types.StringType ):
1477 command += sw + " "
1478 if ptcp:
1479 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001480 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001481 elif isinstance( ptcp, types.ListType ):
1482 main.log.error( self.name + ": Only one switch is " +
1483 "being set and multiple PTCP is " +
1484 "being passed " )
1485 else:
1486 main.log.error( self.name + ": Invalid PTCP" )
1487 ptcp = ""
1488 command += onosIp
1489 commandList.append( command )
1490
1491 elif isinstance( sw, types.ListType ):
1492 if ptcp:
1493 if isinstance( ptcp, types.ListType ):
1494 if len( ptcp ) != len( sw ):
1495 main.log.error( self.name + ": PTCP length = " +
1496 str( len( ptcp ) ) +
1497 " is not the same as switch" +
1498 " length = " +
1499 str( len( sw ) ) )
1500 return main.FALSE
1501 else:
1502 for switch, ptcpNum in zip( sw, ptcp ):
1503 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001504 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001505 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001506 tempCmd += onosIp
1507 commandList.append( tempCmd )
1508 else:
1509 main.log.error( self.name + ": Invalid PTCP" )
1510 return main.FALSE
1511 else:
1512 for switch in sw:
1513 tempCmd = "sh ovs-vsctl set-controller "
1514 tempCmd += switch + " " + onosIp
1515 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001516 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001517 main.log.error( self.name + ": Invalid switch type " )
1518 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001519
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001520 for cmd in commandList:
1521 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001522 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001523 except pexpect.TIMEOUT:
1524 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1525 return main.FALSE
1526 except pexpect.EOF:
1527 main.log.error( self.name + ": EOF exception found" )
1528 main.log.error( self.name + ": " + self.handle.before )
1529 main.cleanup()
1530 main.exit()
1531 return main.TRUE
1532 except Exception:
1533 main.log.exception( self.name + ": Uncaught exception!" )
1534 main.cleanup()
1535 main.exit()
adminbae64d82013-08-01 10:50:15 -07001536
kelvin-onlabd3b64892015-01-20 13:26:24 -08001537 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001538 """
1539 Removes the controller target from sw"""
1540 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001541 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001542 response = self.execute(
1543 cmd=command,
1544 prompt="mininet>",
1545 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001546 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001547 main.log.error( self.name + ": EOF exception found" )
1548 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001549 main.cleanup()
1550 main.exit()
1551 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001552 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001553
kelvin-onlabd3b64892015-01-20 13:26:24 -08001554 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001555 """
Jon Hallb1290e82014-11-18 16:17:48 -05001556 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001557 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001558 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001559 NOTE: cannot currently specify what type of switch
1560 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001561 sw = name of the new switch as a string
1562 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001563 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001564 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001565 """
1566 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001567 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001568 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001569 response = self.execute(
1570 cmd=command,
1571 prompt="mininet>",
1572 timeout=10 )
1573 if re.search( "already exists!", response ):
1574 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001575 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001576 elif re.search( "Error", response ):
1577 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001578 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001579 elif re.search( "usage:", response ):
1580 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001581 return main.FALSE
1582 else:
1583 return main.TRUE
1584 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001585 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001586 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001587 main.cleanup()
1588 main.exit()
1589
kelvin-onlabd3b64892015-01-20 13:26:24 -08001590 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001591 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001592 delete a switch from the mininet topology
1593 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001594 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001595 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001596 sw = name of the switch as a string
1597 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001598 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001599 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001600 response = self.execute(
1601 cmd=command,
1602 prompt="mininet>",
1603 timeout=10 )
1604 if re.search( "no switch named", response ):
1605 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001606 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001607 elif re.search( "Error", response ):
1608 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001609 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001610 elif re.search( "usage:", response ):
1611 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001612 return main.FALSE
1613 else:
1614 return main.TRUE
1615 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001616 main.log.error( self.name + ": EOF exception found" )
1617 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001618 main.cleanup()
1619 main.exit()
1620
kelvin-onlabd3b64892015-01-20 13:26:24 -08001621 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001622 """
1623 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001624 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001625 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001626 NOTE: cannot currently specify what type of link
1627 required params:
1628 node1 = the string node name of the first endpoint of the link
1629 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001630 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001631 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001632 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001633 response = self.execute(
1634 cmd=command,
1635 prompt="mininet>",
1636 timeout=10 )
1637 if re.search( "doesnt exist!", response ):
1638 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001639 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001640 elif re.search( "Error", response ):
1641 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001642 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001643 elif re.search( "usage:", response ):
1644 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001645 return main.FALSE
1646 else:
1647 return main.TRUE
1648 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001649 main.log.error( self.name + ": EOF exception found" )
1650 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001651 main.cleanup()
1652 main.exit()
1653
kelvin-onlabd3b64892015-01-20 13:26:24 -08001654 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001655 """
1656 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001657 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001658 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001659 required params:
1660 node1 = the string node name of the first endpoint of the link
1661 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001662 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001663 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001664 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001665 response = self.execute(
1666 cmd=command,
1667 prompt="mininet>",
1668 timeout=10 )
1669 if re.search( "no node named", response ):
1670 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001671 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001672 elif re.search( "Error", response ):
1673 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001674 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001675 elif re.search( "usage:", response ):
1676 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001677 return main.FALSE
1678 else:
1679 return main.TRUE
1680 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001681 main.log.error( self.name + ": EOF exception found" )
1682 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001683 main.cleanup()
1684 main.exit()
1685
kelvin-onlabd3b64892015-01-20 13:26:24 -08001686 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001687 """
Jon Hallb1290e82014-11-18 16:17:48 -05001688 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001689 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001690 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001691 NOTE: cannot currently specify what type of host
1692 required params:
1693 hostname = the string hostname
1694 optional key-value params
1695 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001696 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001697 """
1698 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001699 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001700 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001701 response = self.execute(
1702 cmd=command,
1703 prompt="mininet>",
1704 timeout=10 )
1705 if re.search( "already exists!", response ):
1706 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001707 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001708 elif re.search( "doesnt exists!", response ):
1709 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001710 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001711 elif re.search( "Error", response ):
1712 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001713 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001714 elif re.search( "usage:", response ):
1715 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001716 return main.FALSE
1717 else:
1718 return main.TRUE
1719 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001720 main.log.error( self.name + ": EOF exception found" )
1721 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001722 main.cleanup()
1723 main.exit()
1724
kelvin-onlabd3b64892015-01-20 13:26:24 -08001725 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001726 """
1727 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001728 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001729 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001730 NOTE: this uses a custom mn function
1731 required params:
1732 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001733 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001734 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001735 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001736 response = self.execute(
1737 cmd=command,
1738 prompt="mininet>",
1739 timeout=10 )
1740 if re.search( "no host named", response ):
1741 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001742 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001743 elif re.search( "Error", response ):
1744 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001745 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001746 elif re.search( "usage:", response ):
1747 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001748 return main.FALSE
1749 else:
1750 return main.TRUE
1751 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001752 main.log.error( self.name + ": EOF exception found" )
1753 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001754 main.cleanup()
1755 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001756
Jon Hall7eb38402015-01-08 17:19:54 -08001757 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001758 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001759 Called at the end of the test to stop the mininet and
1760 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001761 """
Jon Halld80cc142015-07-06 13:36:05 -07001762 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001763 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001764 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001765 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001766 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001767 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001768 elif i == 1:
1769 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001770 # print "Disconnecting Mininet"
1771 if self.handle:
1772 self.handle.sendline( "exit" )
1773 self.handle.expect( "exit" )
1774 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001775 else:
1776 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001777 return response
1778
Jon Halld80cc142015-07-06 13:36:05 -07001779 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001780 """
Jon Hall21270ac2015-02-16 17:59:55 -08001781 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001782 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001783 main.FALSE if the pexpect handle does not exist.
1784
Jon Halld61331b2015-02-17 16:35:47 -08001785 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001786 """
Jon Halld61331b2015-02-17 16:35:47 -08001787 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001788 response = ''
1789 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001790 try:
Jon Halld80cc142015-07-06 13:36:05 -07001791 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001792 i = self.handle.expect( [ 'mininet>',
1793 '\$',
1794 pexpect.EOF,
1795 pexpect.TIMEOUT ],
1796 timeout )
1797 if i == 0:
1798 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001799 response = self.execute(
1800 cmd="exit",
1801 prompt="(.*)",
1802 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001803 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001804 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001805 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001806
kelvin-onlab56a3f462015-02-06 14:04:43 -08001807 if i == 1:
1808 main.log.info( " Mininet trying to exit while not " +
1809 "in the mininet prompt" )
1810 elif i == 2:
1811 main.log.error( "Something went wrong exiting mininet" )
1812 elif i == 3: # timeout
1813 main.log.error( "Something went wrong exiting mininet " +
1814 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001815
Hari Krishnab35c6d02015-03-18 11:13:51 -07001816 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001817 self.handle.sendline( "" )
1818 self.handle.expect( '\$' )
1819 self.handle.sendline(
1820 "sudo kill -9 \`ps -ef | grep \"" +
1821 fileName +
1822 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001823 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001824 main.log.error( self.name + ": EOF exception found" )
1825 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001826 main.cleanup()
1827 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001828 else:
1829 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001830 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001831 return response
1832
Jon Halla5cb3412015-08-18 14:08:22 -07001833 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001834 """
1835 Description:
1836 Sends arp message from mininet host for hosts discovery
1837 Required:
1838 host - hosts name
1839 Optional:
1840 ip - ip address that does not exist in the network so there would
1841 be no reply.
1842 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001843 if ethDevice:
1844 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001845 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001846 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001847 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001848 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001849 i = self.handle.expect( [ "mininet>", "arping: " ] )
1850 if i == 0:
1851 return main.TRUE
1852 elif i == 1:
1853 response = self.handle.before + self.handle.after
1854 self.handle.expect( "mininet>" )
1855 response += self.handle.before + self.handle.after
1856 main.log.warn( "Error sending arping, output was: " +
1857 response )
1858 return main.FALSE
1859 except pexpect.TIMEOUT:
1860 main.log.error( self.name + ": TIMEOUT exception found" )
1861 main.log.warn( self.handle.before )
1862 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001863 except pexpect.EOF:
1864 main.log.error( self.name + ": EOF exception found" )
1865 main.log.error( self.name + ": " + self.handle.before )
1866 main.cleanup()
1867 main.exit()
admin07529932013-11-22 14:58:28 -08001868
Jon Hall7eb38402015-01-08 17:19:54 -08001869 def decToHex( self, num ):
1870 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001871
Jon Hall7eb38402015-01-08 17:19:54 -08001872 def getSwitchFlowCount( self, switch ):
1873 """
1874 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001875 if self.handle:
1876 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1877 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001878 response = self.execute(
1879 cmd=cmd,
1880 prompt="mininet>",
1881 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001882 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001883 main.log.error( self.name + ": EOF exception found" )
1884 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001885 main.cleanup()
1886 main.exit()
1887 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001888 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001889 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001890 main.log.info(
1891 "Couldn't find flows on switch %s, found: %s" %
1892 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001893 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001894 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001895 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001896 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001897
kelvin-onlabd3b64892015-01-20 13:26:24 -08001898 def checkFlows( self, sw, dumpFormat=None ):
1899 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001900 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001901 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001902 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001903 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001904 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001905 response = self.execute(
1906 cmd=command,
1907 prompt="mininet>",
1908 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001909 return response
1910 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001911 main.log.error( self.name + ": EOF exception found" )
1912 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001913 main.cleanup()
1914 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001915
Jon Hall9043c902015-07-30 14:23:44 -07001916 def getFlowTable( self, protoVersion, sw ):
1917 """
1918 Returns certain fields of an OVS flow table. Will force output to
1919 either OF 1.0 or 1.3 format for consistency.
1920
1921 TODO add option to look at cookies. ignoring them for now
1922
1923 NOTE: Use format to force consistent flow table output across
1924 versions
1925 """
1926 try:
1927 self.handle.sendline( "" )
1928 self.handle.expect( "mininet>" )
1929 command = "sh ovs-ofctl dump-flows " + sw
1930 if protoVersion == 1.0:
1931 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\
1932 " print $1 $3 $6 $7 $8}' | "
1933 elif protoVersion == 1.3:
1934 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\
1935 " print $1 $3 $6 $7}' | "
1936 else:
1937 main.log.error(
1938 "Unknown protoVersion in getFlowTable(). given: (" +
1939 str( type( protoVersion ) ) +
1940 ") '" + str( protoVersion ) + "'" )
1941 return None
1942 command += "cut -d ',' -f 2- | sort -n -k1 -r"
1943 self.handle.sendline( command )
1944 self.handle.expect( "sort" )
1945 self.handle.expect( "OFPST_FLOW" )
1946 response = self.handle.before
1947 return response
1948 except pexpect.EOF:
1949 main.log.error( self.name + ": EOF exception found" )
1950 main.log.error( self.name + ": " + self.handle.before )
1951 main.cleanup()
1952 main.exit()
1953 except pexpect.TIMEOUT:
1954 main.log.exception( self.name + ": Timeout exception: " )
1955 return None
1956
1957 def flowComp( self, flow1, flow2 ):
1958 if flow1 == flow2:
1959 return main.TRUE
1960 else:
1961 main.log.info( "Flow tables do not match, printing tables:" )
1962 main.log.info( "Flow Table 1:" )
1963 main.log.info( flow1 )
1964 main.log.info( "Flow Table 2:" )
1965 main.log.info( flow2 )
1966 return main.FALSE
1967
Charles Chan029be652015-08-24 01:46:10 +08001968 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001969 """
Jon Hallefbd9792015-03-05 16:11:36 -08001970 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001971 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001972 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001973 self.handle.sendline( "" )
1974 self.handle.expect( "mininet>" )
1975 self.handle.sendline(
1976 "sh sudo tcpdump -n -i " +
1977 intf +
1978 " " +
1979 port +
1980 " -w " +
1981 filename.strip() +
1982 " &" )
1983 self.handle.sendline( "" )
1984 i = self.handle.expect( [ 'No\ssuch\device',
1985 'listening\son',
1986 pexpect.TIMEOUT,
1987 "mininet>" ],
1988 timeout=10 )
1989 main.log.warn( self.handle.before + self.handle.after )
1990 self.handle.sendline( "" )
1991 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001992 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001993 main.log.error(
1994 self.name +
1995 ": tcpdump - No such device exists. " +
1996 "tcpdump attempted on: " +
1997 intf )
admin2a9548d2014-06-17 14:08:07 -07001998 return main.FALSE
1999 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002000 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002001 return main.TRUE
2002 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002003 main.log.error(
2004 self.name +
2005 ": tcpdump command timed out! Check interface name," +
2006 " given interface was: " +
2007 intf )
admin2a9548d2014-06-17 14:08:07 -07002008 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002009 elif i == 3:
2010 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002011 return main.TRUE
2012 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002013 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002014 return main.FALSE
2015 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002016 main.log.error( self.name + ": EOF exception found" )
2017 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002018 main.cleanup()
2019 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002020 except Exception:
2021 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002022 main.cleanup()
2023 main.exit()
2024
kelvin-onlabd3b64892015-01-20 13:26:24 -08002025 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002026 """
2027 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002028 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002029 self.handle.sendline( "sh sudo pkill tcpdump" )
2030 self.handle.expect( "mininet>" )
2031 self.handle.sendline( "" )
2032 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002033 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002034 main.log.error( self.name + ": EOF exception found" )
2035 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002036 main.cleanup()
2037 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002038 except Exception:
2039 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002040 main.cleanup()
2041 main.exit()
2042
Jon Halld80cc142015-07-06 13:36:05 -07002043 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002044 """
2045 Read ports from a Mininet switch.
2046
2047 Returns a json structure containing information about the
2048 ports of the given switch.
2049 """
2050 response = self.getInterfaces( nodeName )
2051 # TODO: Sanity check on response. log if no such switch exists
2052 ports = []
2053 for line in response.split( "\n" ):
2054 if not line.startswith( "name=" ):
2055 continue
2056 portVars = {}
2057 for var in line.split( "," ):
2058 key, value = var.split( "=" )
2059 portVars[ key ] = value
2060 isUp = portVars.pop( 'enabled', "True" )
2061 isUp = "True" in isUp
2062 if verbose:
2063 main.log.info( "Reading switch port %s(%s)" %
2064 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2065 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002066 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002067 mac = None
2068 ips = []
2069 ip = portVars[ 'ip' ]
2070 if ip == 'None':
2071 ip = None
2072 ips.append( ip )
2073 name = portVars[ 'name' ]
2074 if name == 'None':
2075 name = None
2076 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2077 if name == 'lo':
2078 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2079 else:
2080 portNo = re.search( portRe, name ).group( 'port' )
2081 ports.append( { 'of_port': portNo,
2082 'mac': str( mac ).replace( '\'', '' ),
2083 'name': name,
2084 'ips': ips,
2085 'enabled': isUp } )
2086 return ports
2087
Jon Halld80cc142015-07-06 13:36:05 -07002088 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002089 """
2090 Read switches from Mininet.
2091
2092 Returns a dictionary whose keys are the switch names and the value is
2093 a dictionary containing information about the switch.
2094 """
Jon Halla22481b2015-07-28 17:46:01 -07002095 # NOTE: To support new Mininet switch classes, just append the new
2096 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002097
Jon Halla22481b2015-07-28 17:46:01 -07002098 # Regex patterns to parse 'dump' output
2099 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002100 # <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 -07002101 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002102 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2103 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2104 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2105 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2106 swRE = r"<(?P<class>" + switchClasses + r")" +\
2107 r"(?P<options>\{.*\})?\s" +\
2108 r"(?P<name>[^:]+)\:\s" +\
2109 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2110 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002111 # Update mn port info
2112 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002113 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002114 dump = self.dump().split( "\n" )
2115 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002116 result = re.search( swRE, line, re.I )
2117 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002118 name = result.group( 'name' )
2119 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002120 pid = result.group( 'pid' )
2121 swClass = result.group( 'class' )
2122 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002123 if verbose:
2124 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2125 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002126 output[ name ] = { "dpid": dpid,
2127 "ports": ports,
2128 "swClass": swClass,
2129 "pid": pid,
2130 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002131 return output
2132
Jon Halld80cc142015-07-06 13:36:05 -07002133 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002134 """
2135 Read hosts from Mininet.
2136
2137 Returns a dictionary whose keys are the host names and the value is
2138 a dictionary containing information about the host.
2139 """
2140 # Regex patterns to parse dump output
2141 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002142 # <Host h1: pid=12725>
2143 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2144 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2145 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002146 # NOTE: Does not correctly match hosts with multi-links
2147 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2148 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002149 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002150 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002151 # update mn port info
2152 self.update()
2153 # Get mininet dump
2154 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002155 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002156 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002157 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002158 result = re.search( hostRE, line )
2159 name = result.group( 'name' )
2160 interfaces = []
2161 response = self.getInterfaces( name )
2162 # Populate interface info
2163 for line in response.split( "\n" ):
2164 if line.startswith( "name=" ):
2165 portVars = {}
2166 for var in line.split( "," ):
2167 key, value = var.split( "=" )
2168 portVars[ key ] = value
2169 isUp = portVars.pop( 'enabled', "True" )
2170 isUp = "True" in isUp
2171 if verbose:
2172 main.log.info( "Reading host port %s(%s)" %
2173 ( portVars[ 'name' ],
2174 portVars[ 'mac' ] ) )
2175 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002176 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002177 mac = None
2178 ips = []
2179 ip = portVars[ 'ip' ]
2180 if ip == 'None':
2181 ip = None
2182 ips.append( ip )
2183 intfName = portVars[ 'name' ]
2184 if name == 'None':
2185 name = None
2186 interfaces.append( {
2187 "name": intfName,
2188 "ips": ips,
2189 "mac": str( mac ),
2190 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002191 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002192 return hosts
2193
2194 def getLinks( self ):
2195 """
2196 Gathers information about current Mininet links. These links may not
2197 be up if one of the ports is down.
2198
2199 Returns a list of dictionaries with link endpoints.
2200
2201 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002202 { 'node1': str( node1 name )
2203 'node2': str( node2 name )
2204 'port1': str( port1 of_port )
2205 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002206 Note: The port number returned is the eth#, not necessarily the of_port
2207 number. In Mininet, for OVS switch, these should be the same. For
2208 hosts, this is just the eth#.
2209 """
2210 self.update()
2211 response = self.links().split( '\n' )
2212
2213 # Examples:
2214 # s1-eth3<->s2-eth1 (OK OK)
2215 # s13-eth3<->h27-eth0 (OK OK)
2216 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2217 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2218 links = []
2219 for line in response:
2220 match = re.search( linkRE, line )
2221 if match:
2222 node1 = match.group( 'node1' )
2223 node2 = match.group( 'node2' )
2224 port1 = match.group( 'port1' )
2225 port2 = match.group( 'port2' )
2226 links.append( { 'node1': node1,
2227 'node2': node2,
2228 'port1': port1,
2229 'port2': port2 } )
2230 return links
2231
2232 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002233 """
2234 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002235 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002236
Jon Hallafa8a472015-06-12 14:02:42 -07002237 Dependencies:
2238 1. numpy - "sudo pip install numpy"
2239 """
2240 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002241 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002242 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002243 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002244 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002245 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002246 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002247 main.log.error(
2248 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002249 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002250 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002251 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002252 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002253 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002254 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002255 onosDPIDs.append(
2256 switch[ 'id' ].replace(
2257 ":",
2258 '' ).replace(
2259 "of",
2260 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002261 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002262
Jon Hall7eb38402015-01-08 17:19:54 -08002263 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002264 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002265 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002266 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002267 main.log.error( str( list1 ) )
2268 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002269 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002270 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002271 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002272 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002273 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002274
Jon Hall7eb38402015-01-08 17:19:54 -08002275 # FIXME: this does not look for extra ports in ONOS, only checks that
2276 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002277 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002278
Jon Hall7eb38402015-01-08 17:19:54 -08002279 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002280 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002281 mnPorts = []
2282 onosPorts = []
2283 switchResult = main.TRUE
2284 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002285 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002286 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002287 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002288 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002289 if onosSwitch[ 'device' ][ 'id' ].replace(
2290 ':',
2291 '' ).replace(
2292 "of",
2293 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002294 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002295 if port[ 'isEnabled' ]:
2296 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002297 # onosPorts.append( 'local' )
2298 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002299 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002300 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002301 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002302 mnPorts.sort( key=float )
2303 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002304
kelvin-onlabd3b64892015-01-20 13:26:24 -08002305 mnPortsLog = mnPorts
2306 onosPortsLog = onosPorts
2307 mnPorts = [ x for x in mnPorts ]
2308 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002309
Jon Hall7eb38402015-01-08 17:19:54 -08002310 # TODO: handle other reserved port numbers besides LOCAL
2311 # NOTE: Reserved ports
2312 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2313 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002314 for mnPort in mnPortsLog:
2315 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002316 # don't set results to true here as this is just one of
2317 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002318 mnPorts.remove( mnPort )
2319 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002320
Jon Hall7eb38402015-01-08 17:19:54 -08002321 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002322 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002323 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002324 if 65534 in mnPorts:
2325 mnPorts.remove( 65534 )
2326 if long( uint64( -2 ) ) in onosPorts:
2327 onosPorts.remove( long( uint64( -2 ) ) )
2328 if len( mnPorts ): # the ports of this switch don't match
2329 switchResult = main.FALSE
2330 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2331 if len( onosPorts ): # the ports of this switch don't match
2332 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002333 main.log.warn(
2334 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002335 str( onosPorts ) )
2336 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002337 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002338 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002339 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002340 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2341 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2342 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002343 finalResults = finalResults and portsResults
2344 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002345
Jon Hallafa8a472015-06-12 14:02:42 -07002346 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002347 """
2348 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002349 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002350
Jon Hallafa8a472015-06-12 14:02:42 -07002351 """
Jon Hall7eb38402015-01-08 17:19:54 -08002352 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002353 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002354 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002355
Jon Halld80cc142015-07-06 13:36:05 -07002356 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002357 for l in links:
2358 try:
2359 node1 = switches[ l[ 'node1' ] ]
2360 node2 = switches[ l[ 'node2' ] ]
2361 enabled = True
2362 for port in node1[ 'ports' ]:
2363 if port[ 'of_port' ] == l[ 'port1' ]:
2364 enabled = enabled and port[ 'enabled' ]
2365 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002366 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002367 enabled = enabled and port[ 'enabled' ]
2368 if enabled:
2369 mnLinks.append( l )
2370 except KeyError:
2371 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002372 if 2 * len( mnLinks ) == len( onos ):
2373 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002374 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002375 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002376 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002377 "Mininet has " + str( len( mnLinks ) ) +
2378 " bidirectional links and ONOS has " +
2379 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002380
Jon Hall7eb38402015-01-08 17:19:54 -08002381 # iterate through MN links and check if an ONOS link exists in
2382 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002383 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002384 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002385 node1 = None
2386 port1 = None
2387 node2 = None
2388 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002389 firstDir = main.FALSE
2390 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002391 for swName, switch in switches.iteritems():
2392 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002393 node1 = switch[ 'dpid' ]
2394 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002395 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002396 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002397 if node1 is not None and node2 is not None:
2398 break
Jon Hallafa8a472015-06-12 14:02:42 -07002399 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002400 node2 = switch[ 'dpid' ]
2401 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002402 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002403 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002404 if node1 is not None and node2 is not None:
2405 break
2406
kelvin-onlabd3b64892015-01-20 13:26:24 -08002407 for onosLink in onos:
2408 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002409 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002410 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002411 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002412 onosPort1 = onosLink[ 'src' ][ 'port' ]
2413 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002414
Jon Hall72cf1dc2014-10-20 21:04:50 -04002415 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002416 if str( onosNode1 ) == str( node1 ) and str(
2417 onosNode2 ) == str( node2 ):
2418 if int( onosPort1 ) == int( port1 ) and int(
2419 onosPort2 ) == int( port2 ):
2420 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002421 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002422 main.log.warn(
2423 'The port numbers do not match for ' +
2424 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002425 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002426 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002427 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002428 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002429 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002430
2431 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002432 elif ( str( onosNode1 ) == str( node2 ) and
2433 str( onosNode2 ) == str( node1 ) ):
2434 if ( int( onosPort1 ) == int( port2 )
2435 and int( onosPort2 ) == int( port1 ) ):
2436 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002437 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002438 main.log.warn(
2439 'The port numbers do not match for ' +
2440 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002441 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002442 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002443 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002444 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002445 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002446 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002447 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002448 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002449 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002450 'ONOS does not have the link %s/%s -> %s/%s' %
2451 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002452 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002453 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002454 'ONOS does not have the link %s/%s -> %s/%s' %
2455 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002456 linkResults = linkResults and firstDir and secondDir
2457 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002458
Jon Hallafa8a472015-06-12 14:02:42 -07002459 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002460 """
Jon Hallafa8a472015-06-12 14:02:42 -07002461 Compare mn and onos Hosts.
2462 Since Mininet hosts are quiet, ONOS will only know of them when they
2463 speak. For this reason, we will only check that the hosts in ONOS
2464 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002465
Jon Hallafa8a472015-06-12 14:02:42 -07002466 Arguments:
2467 hostsJson: parsed json object from the onos hosts api
2468 Returns:
2469 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002470 import json
2471 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002472 for onosHost in hostsJson:
2473 onosMAC = onosHost[ 'mac' ].lower()
2474 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002475 for mnHost, info in hosts.iteritems():
2476 for mnIntf in info[ 'interfaces' ]:
2477 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002478 match = True
2479 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002480 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002481 pass # all is well
2482 else:
2483 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002484 main.log.error( "ONOS host " +
2485 onosHost[ 'id' ] +
2486 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002487 str( onosHost[ 'ipAddresses' ] ) +
2488 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002489 str( ip ) +
2490 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002491 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002492 onosHost,
2493 sort_keys=True,
2494 indent=4,
2495 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002496 main.log.info( output )
2497 hostResults = main.FALSE
2498 if not match:
2499 hostResults = main.FALSE
2500 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2501 "corresponding Mininet host." )
2502 output = json.dumps( onosHost,
2503 sort_keys=True,
2504 indent=4,
2505 separators=( ',', ': ' ) )
2506 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002507 return hostResults
2508
Jon Hallafa8a472015-06-12 14:02:42 -07002509 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002510 """
2511 Returns a list of all hosts
2512 Don't ask questions just use it"""
2513 self.handle.sendline( "" )
2514 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002515
Jon Hall7eb38402015-01-08 17:19:54 -08002516 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2517 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002518
kelvin-onlabd3b64892015-01-20 13:26:24 -08002519 handlePy = self.handle.before
2520 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2521 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002522
Jon Hall7eb38402015-01-08 17:19:54 -08002523 self.handle.sendline( "" )
2524 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002525
kelvin-onlabd3b64892015-01-20 13:26:24 -08002526 hostStr = handlePy.replace( "]", "" )
2527 hostStr = hostStr.replace( "'", "" )
2528 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002529 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002530 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002531
kelvin-onlabd3b64892015-01-20 13:26:24 -08002532 return hostList
adminbae64d82013-08-01 10:50:15 -07002533
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002534 def getSwitch( self ):
2535 """
2536 Returns a list of all switches
2537 Again, don't ask question just use it...
2538 """
2539 # get host list...
2540 hostList = self.getHosts()
2541 # Make host set
2542 hostSet = set( hostList )
2543
2544 # Getting all the nodes in mininet
2545 self.handle.sendline( "" )
2546 self.handle.expect( "mininet>" )
2547
2548 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2549 self.handle.expect( "mininet>" )
2550
2551 handlePy = self.handle.before
2552 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2553 handlePy = handlePy.rstrip()
2554
2555 self.handle.sendline( "" )
2556 self.handle.expect( "mininet>" )
2557
2558 nodesStr = handlePy.replace( "]", "" )
2559 nodesStr = nodesStr.replace( "'", "" )
2560 nodesStr = nodesStr.replace( "[", "" )
2561 nodesStr = nodesStr.replace( " ", "" )
2562 nodesList = nodesStr.split( "," )
2563
2564 nodesSet = set( nodesList )
2565 # discarding default controller(s) node
2566 nodesSet.discard( 'c0' )
2567 nodesSet.discard( 'c1' )
2568 nodesSet.discard( 'c2' )
2569
2570 switchSet = nodesSet - hostSet
2571 switchList = list( switchSet )
2572
2573 return switchList
2574
Jon Hall7eb38402015-01-08 17:19:54 -08002575 def update( self ):
2576 """
2577 updates the port address and status information for
2578 each port in mn"""
2579 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002580 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002581 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002582 self.handle.sendline( "" )
2583 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002584
Jon Hall7eb38402015-01-08 17:19:54 -08002585 self.handle.sendline( "update" )
2586 self.handle.expect( "update" )
2587 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002588
Jon Hall7eb38402015-01-08 17:19:54 -08002589 self.handle.sendline( "" )
2590 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002591
Jon Hallb1290e82014-11-18 16:17:48 -05002592 return main.TRUE
2593 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002594 main.log.error( self.name + ": EOF exception found" )
2595 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002596 main.cleanup()
2597 main.exit()
2598
Jon Halld80cc142015-07-06 13:36:05 -07002599 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002600 """
2601 Add vlan tag to a host.
2602 Dependencies:
2603 This class depends on the "vlan" package
2604 $ sudo apt-get install vlan
2605 Configuration:
2606 Load the 8021q module into the kernel
2607 $sudo modprobe 8021q
2608
2609 To make this setup permanent:
2610 $ sudo su -c 'echo "8021q" >> /etc/modules'
2611 """
2612 if self.handle:
2613 try:
Jon Halld80cc142015-07-06 13:36:05 -07002614 # get the ip address of the host
2615 main.log.info( "Get the ip address of the host" )
2616 ipaddr = self.getIPAddress( host )
2617 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002618
Jon Halld80cc142015-07-06 13:36:05 -07002619 # remove IP from interface intf
2620 # Ex: h1 ifconfig h1-eth0 inet 0
2621 main.log.info( "Remove IP from interface " )
2622 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2623 self.handle.sendline( cmd2 )
2624 self.handle.expect( "mininet>" )
2625 response = self.handle.before
2626 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002627
Jon Halld80cc142015-07-06 13:36:05 -07002628 # create VLAN interface
2629 # Ex: h1 vconfig add h1-eth0 100
2630 main.log.info( "Create Vlan" )
2631 cmd3 = host + " vconfig add " + intf + " " + vlan
2632 self.handle.sendline( cmd3 )
2633 self.handle.expect( "mininet>" )
2634 response = self.handle.before
2635 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002636
Jon Halld80cc142015-07-06 13:36:05 -07002637 # assign the host's IP to the VLAN interface
2638 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2639 main.log.info( "Assign the host IP to the vlan interface" )
2640 vintf = intf + "." + vlan
2641 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2642 self.handle.sendline( cmd4 )
2643 self.handle.expect( "mininet>" )
2644 response = self.handle.before
2645 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002646
2647 return main.TRUE
2648 except pexpect.EOF:
2649 main.log.error( self.name + ": EOF exception found" )
2650 main.log.error( self.name + ": " + self.handle.before )
2651 return main.FALSE
2652
adminbae64d82013-08-01 10:50:15 -07002653if __name__ != "__main__":
2654 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002655 sys.modules[ __name__ ] = MininetCliDriver()