blob: 3eb5577504511af83a85f0785d60bad847570e7e [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
Jon Hall892818c2015-10-20 17:58:34 -070055 # TODO: Refactor driver to use these everywhere
56 self.mnPrompt = "mininet>"
57 self.hostPrompt = "~#"
58 self.bashPrompt = "\$"
59 self.scapyPrompt = ">>>"
adminbae64d82013-08-01 10:50:15 -070060
Jon Hall7eb38402015-01-08 17:19:54 -080061 def connect( self, **connectargs ):
62 """
63 Here the main is the TestON instance after creating
64 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080065 try:
66 for key in connectargs:
67 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070068 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080069 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070070 for key in self.options:
71 if key == "home":
72 self.home = self.options[ 'home' ]
73 break
74 if self.home is None or self.home == "":
75 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070076
77 try:
Jon Hall892818c2015-10-20 17:58:34 -070078 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070079 self.ip_address = os.getenv( str( self.ip_address ) )
80 else:
81 main.log.info( self.name +
82 ": Trying to connect to " +
83 self.ip_address )
84
85 except KeyError:
86 main.log.info( "Invalid host name," +
87 " connecting to local host instead" )
88 self.ip_address = 'localhost'
89 except Exception as inst:
90 main.log.error( "Uncaught exception: " + str( inst ) )
91
kelvin-onlaba1484582015-02-02 15:46:20 -080092 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070093 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080094 self ).connect(
95 user_name=self.user_name,
96 ip_address=self.ip_address,
97 port=None,
98 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080099
kelvin-onlaba1484582015-02-02 15:46:20 -0800100 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -0800101 main.log.info( "Connection successful to the host " +
102 self.user_name +
103 "@" +
104 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800105 return main.TRUE
106 else:
107 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800108 self.user_name +
109 "@" +
110 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800111 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800112 return main.FALSE
113 except pexpect.EOF:
114 main.log.error( self.name + ": EOF exception found" )
115 main.log.error( self.name + ": " + self.handle.before )
116 main.cleanup()
117 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800118 except Exception:
119 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800120 main.cleanup()
121 main.exit()
122
kelvin-onlab10e8d392015-06-03 13:53:45 -0700123 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800124 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700125 Description:
126 Starts Mininet accepts a topology(.py) file and/or an optional
127 argument, to start the mininet, as a parameter.
128 Can also send regular mininet command to load up desired topology.
129 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
130 Options:
131 topoFile = file path for topology file (.py)
132 args = extra option added when starting the topology from the file
133 mnCmd = Mininet command use to start topology
134 Returns:
135 main.TRUE if the mininet starts successfully, main.FALSE
136 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800137 """
Jon Hall7eb38402015-01-08 17:19:54 -0800138 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700139 # make sure old networks are cleaned up
140 main.log.info( self.name +
141 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800142 self.handle.sendline( "sudo mn -c" )
143 i = self.handle.expect( [ 'password\sfor\s',
144 'Cleanup\scomplete',
145 pexpect.EOF,
146 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800147 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800148 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700149 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800150 main.log.info( self.name + ": Sending sudo password" )
151 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800152 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800153 '\$',
154 pexpect.EOF,
155 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800156 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800157 if i == 1:
158 main.log.info( self.name + ": Clean" )
159 elif i == 2:
160 main.log.error( self.name + ": Connection terminated" )
161 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700162 main.log.error( self.name + ": Something while cleaning " +
163 "Mininet took too long... " )
164 # Craft the string to start mininet
165 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700166 if not mnCmd:
167 if topoFile is None or topoFile == '': # If no file is given
168 main.log.info( self.name + ": building fresh Mininet" )
169 cmdString += "mn "
170 if args is None or args == '':
171 # If no args given, use args from .topo file
172 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700173 " " + self.options[ 'arg2' ] +\
174 " --mac --controller " +\
175 self.options[ 'controller' ] + " " +\
176 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700177 else: # else only use given args
178 pass
179 # TODO: allow use of topo args and method args?
180 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700181 main.log.info(
182 "Starting Mininet from topo file " +
183 topoFile )
Flavio Castrocc38a542016-03-03 13:15:46 -0800184 cmdString += "-E python " + topoFile + " "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700185 if args is None:
186 args = ''
187 # TODO: allow use of args from .topo file?
188 cmdString += args
189 else:
190 main.log.info( "Starting Mininet topology using '" + mnCmd +
191 "' command" )
192 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700193 # Send the command and check if network started
194 self.handle.sendline( "" )
195 self.handle.expect( '\$' )
196 main.log.info( "Sending '" + cmdString + "' to " + self.name )
197 self.handle.sendline( cmdString )
198 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800199 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700200 'Exception',
201 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800202 pexpect.EOF,
203 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700204 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800205 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700206 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800207 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800208 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700209 response = str( self.handle.before +
210 self.handle.after )
211 self.handle.expect( '\$' )
212 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700213 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700214 main.log.error(
215 self.name +
216 ": Launching Mininet failed: " + response )
217 return main.FALSE
218 elif i == 2:
219 self.handle.expect( [ "\n",
220 pexpect.EOF,
221 pexpect.TIMEOUT ],
222 timeout )
223 main.log.info( self.handle.before )
224 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800225 main.log.error( self.name + ": Connection timeout" )
226 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700227 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800228 main.log.error(
229 self.name +
230 ": Something took too long... " )
231 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700232 # Why did we hit this part?
233 main.log.error( "startNet did not return correctly" )
234 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800235 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700236 main.log.error( self.name + ": Connection failed to the host " +
237 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800238 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700239 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800240
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800241 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400242 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800243 # In tree topology, if fanout arg is not given, by default it is 2
244 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400245 fanout = 2
246 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500247 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800248 while( k <= depth - 1 ):
249 count = count + pow( fanout, k )
250 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800251 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800252 while( k <= depth - 2 ):
253 # depth-2 gives you only core links and not considering
254 # edge links as seen by ONOS. If all the links including
255 # edge links are required, do depth-1
256 count = count + pow( fanout, k )
257 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800258 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800259 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800260 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800261
Jon Hall7eb38402015-01-08 17:19:54 -0800262 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800263 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800264 # by default it is 1
265 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400266 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800267 numSwitches = depth
268 numHostsPerSw = fanout
269 totalNumHosts = numSwitches * numHostsPerSw
270 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800271 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800272 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800273 topoDict = { "num_switches": int( numSwitches ),
274 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400275 return topoDict
276
kelvin-onlabd3b64892015-01-20 13:26:24 -0800277 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700278 """
279 Calculate the number of switches and links in a topo."""
280 # TODO: combine this function and numSwitchesNlinks
281 argList = self.options[ 'arg1' ].split( "," )
282 topoArgList = argList[ 0 ].split( " " )
283 argList = map( int, argList[ 1: ] )
284 topoArgList = topoArgList[ 1: ] + argList
285
286 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400287 return topoDict
288
GlennRCf07c44a2015-09-18 13:33:46 -0700289 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800290 """
291 Verifies the reachability of the hosts using pingall command.
292 Optional parameter timeout allows you to specify how long to
293 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700294 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700295 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700296 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700297 ping
298 acceptableFailed - Set the number of acceptable failed pings for the
299 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800300 Returns:
301 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700302 otherwise main.FALSE
303 """
304 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700305 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700306 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700307 if self.handle:
308 main.log.info(
309 self.name +
310 ": Checking reachabilty to the hosts using pingall" )
311 response = ""
312 failedPings = 0
313 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700314 cmd = "pingall"
315 if protocol == "IPv6":
316 cmd = "py net.pingAll6()"
317 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700318 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700319 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700320 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700321 pexpect.EOF,
322 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700323 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700324 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700325 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700326 response += self.handle.before
327 break
328 elif i == 1:
329 response += self.handle.before + self.handle.after
330 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700331 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700332 returnValue = main.FALSE
333 if shortCircuit:
334 main.log.error( self.name +
335 ": Aborting pingall - "
336 + str( failedPings ) +
337 " pings failed" )
338 break
Jon Hall390696c2015-05-05 17:13:41 -0700339 if ( time.time() - startTime ) > timeout:
340 returnValue = main.FALSE
341 main.log.error( self.name +
342 ": Aborting pingall - " +
343 "Function took too long " )
344 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700345 elif i == 2:
346 main.log.error( self.name +
347 ": EOF exception found" )
348 main.log.error( self.name + ": " +
349 self.handle.before )
350 main.cleanup()
351 main.exit()
352 elif i == 3:
353 response += self.handle.before
354 main.log.error( self.name +
355 ": TIMEOUT exception found" )
356 main.log.error( self.name +
357 ": " +
358 str( response ) )
359 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800360 self.handle.send( "\x03" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 self.handle.expect( "Interrupt" )
362 self.handle.expect( "mininet>" )
363 break
364 pattern = "Results\:"
365 main.log.info( "Pingall output: " + str( response ) )
366 if re.search( pattern, response ):
367 main.log.info( self.name + ": Pingall finished with "
368 + str( failedPings ) + " failed pings" )
369 return returnValue
370 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700371 # NOTE: Send ctrl-c to make sure pingall is done
You Wangaf684312016-01-27 14:44:38 -0800372 self.handle.send( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700373 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700374 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700375 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700376 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700377 main.log.error( self.name + ": Connection failed to the host" )
378 main.cleanup()
379 main.exit()
380 except pexpect.TIMEOUT:
381 if response:
382 main.log.info( "Pingall output: " + str( response ) )
383 main.log.error( self.name + ": pexpect.TIMEOUT found" )
384 return main.FALSE
385 except pexpect.EOF:
386 main.log.error( self.name + ": EOF exception found" )
387 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500388 main.cleanup()
389 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700390
Jon Hall7eb38402015-01-08 17:19:54 -0800391 def fpingHost( self, **pingParams ):
392 """
393 Uses the fping package for faster pinging...
394 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800395 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800396 command = args[ "SRC" ] + \
397 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
398 self.handle.sendline( command )
399 self.handle.expect(
400 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
401 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
402 response = self.handle.before
403 if re.search( ":\s-", response ):
404 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700405 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800406 elif re.search( ":\s\d{1,2}\.\d\d", response ):
407 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700408 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800409 main.log.info( self.name + ": Install fping on mininet machine... " )
410 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700411 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800412
Jon Hall3b489db2015-10-05 14:38:37 -0700413 def pingallHosts( self, hostList, wait=1 ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400414 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700415 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700416
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400417 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700418 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700419
420 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400421 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700422
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400423 Returns main.FALSE if one or more of hosts specified
424 cannot reach each other"""
Jon Hall3b489db2015-10-05 14:38:37 -0700425 wait = int( wait )
426 cmd = " ping -c 1 -i 1 -W " + str( wait ) + " "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400427
428 try:
429 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700430
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400431 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700432 pingResponse = "IPv4 ping across specified hosts\n"
433 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400434 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700435 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400436 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700437 pingList = hostList[ :listIndex ] + \
438 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700439
440 pingResponse += str(str(host) + " -> ")
441
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400442 for temp in pingList:
443 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700444 pingCmd = str( host ) + cmd + str( temp )
Jon Hall934576d2015-10-09 10:12:22 -0700445 self.handle.sendline( pingCmd )
446 self.handle.expect( "mininet>", timeout=wait + 1 )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400447 response = self.handle.before
448 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRCd10d3cc2015-09-24 12:47:16 -0700449 pingResponse += str(" h" + str( temp[1:] ))
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400450 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700451 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400452 # One of the host to host pair is unreachable
453 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700454 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700455 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700456 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700457 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700458 except pexpect.TIMEOUT:
459 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700460 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400461 except pexpect.EOF:
462 main.log.error( self.name + ": EOF exception found" )
463 main.log.error( self.name + ": " + self.handle.before )
464 main.cleanup()
465 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700466 except Exception:
467 main.log.exception( self.name + ": Uncaught exception!" )
468 main.cleanup()
469 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400470
Jon Hall3b489db2015-10-05 14:38:37 -0700471 def pingIpv6Hosts( self, hostList, prefix='1000::', wait=1 ):
Hari Krishna9592fc82015-07-31 15:11:15 -0700472 """
Jon Hall3b489db2015-10-05 14:38:37 -0700473 IPv6 ping all hosts in hostList. If no prefix passed this will use
474 default prefix of 1000::
Hari Krishna9592fc82015-07-31 15:11:15 -0700475
Jon Hall3b489db2015-10-05 14:38:37 -0700476 Returns main.TRUE if all hosts specified can reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700477
Jon Hall3b489db2015-10-05 14:38:37 -0700478 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700479 """
480 try:
481 main.log.info( "Testing reachability between specified IPv6 hosts" )
482 isReachable = main.TRUE
Jon Hall3b489db2015-10-05 14:38:37 -0700483 wait = int( wait )
484 cmd = " ping6 -c 1 -i 1 -W " + str( wait ) + " "
GlennRC6d506272015-09-25 11:36:07 -0700485 pingResponse = "IPv6 Pingall output:\n"
486 failedPings = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700487 for host in hostList:
488 listIndex = hostList.index( host )
489 # List of hosts to ping other than itself
490 pingList = hostList[ :listIndex ] + \
491 hostList[ ( listIndex + 1 ): ]
492
GlennRC2cf7d952015-09-11 16:32:13 -0700493 pingResponse += str(str(host) + " -> ")
494
Hari Krishna9592fc82015-07-31 15:11:15 -0700495 for temp in pingList:
496 # Current host pings all other hosts specified
Jon Hall439c8912016-04-15 02:22:03 -0700497 pingCmd = str( host ) + cmd + str( self.getIPAddress(temp,proto='IPv6') )
Jon Hall934576d2015-10-09 10:12:22 -0700498 self.handle.sendline( pingCmd )
499 self.handle.expect( "mininet>", timeout=wait + 1 )
Hari Krishna9592fc82015-07-31 15:11:15 -0700500 response = self.handle.before
501 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700502 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700503 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700504 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700505 # One of the host to host pair is unreachable
506 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700507 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700508 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700509 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700510 return isReachable
511
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700512 except pexpect.TIMEOUT:
513 main.log.exception( self.name + ": TIMEOUT exception" )
514 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700515 except pexpect.EOF:
516 main.log.error( self.name + ": EOF exception found" )
517 main.log.error( self.name + ": " + self.handle.before )
518 main.cleanup()
519 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700520 except Exception:
521 main.log.exception( self.name + ": Uncaught exception!" )
522 main.cleanup()
523 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700524
Jon Hall7eb38402015-01-08 17:19:54 -0800525 def pingHost( self, **pingParams ):
526 """
Jon Hall3b489db2015-10-05 14:38:37 -0700527 Ping from one mininet host to another
528 Currently the only supported Params: SRC, TARGET, and WAIT
529 """
530 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
531 wait = args['WAIT']
532 wait = int( wait if wait else 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800533 command = args[ "SRC" ] + " ping " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700534 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Jon Hall6094a362014-04-11 14:46:56 -0700535 try:
Jon Hall61282e32015-03-19 11:34:11 -0700536 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800537 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700538 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
539 timeout=wait + 1 )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700540 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800541 main.log.error(
542 self.name +
543 ": timeout when waiting for response from mininet" )
544 main.log.error( "response: " + str( self.handle.before ) )
545 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700546 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800547 main.log.error(
548 self.name +
549 ": timeout when waiting for response from mininet" )
550 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700551 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700552 if re.search( ',\s0\%\spacket\sloss', response ):
553 main.log.info( self.name + ": no packets lost, host is reachable" )
554 return main.TRUE
555 else:
556 main.log.error(
557 self.name +
558 ": PACKET LOST, HOST IS NOT REACHABLE" )
559 return main.FALSE
560
Jon Hallfbc828e2015-01-06 17:30:19 -0800561 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800562 main.log.error( self.name + ": EOF exception found" )
563 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700564 main.cleanup()
565 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700566 except Exception:
567 main.log.exception( self.name + ": Uncaught exception!" )
568 main.cleanup()
569 main.exit()
570
571 def ping6pair( self, **pingParams ):
572 """
GlennRC2cf7d952015-09-11 16:32:13 -0700573 IPv6 Ping between a pair of mininet hosts
Jon Hall3b489db2015-10-05 14:38:37 -0700574 Currently the only supported Params are: SRC, TARGET, and WAIT
Hari Krishna012a1c12015-08-25 14:23:58 -0700575 FLOWLABEL and -I (src interface) will be added later after running some tests.
576 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
577 """
Jon Hall3b489db2015-10-05 14:38:37 -0700578 args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
579 wait = args['WAIT']
580 wait = int( wait if wait else 1 )
Subhash Kumar Singhbcc1c792015-11-07 04:52:11 +0530581 command = args[ "SRC" ] + " ping6 " + \
Jon Hall3b489db2015-10-05 14:38:37 -0700582 args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
Hari Krishna012a1c12015-08-25 14:23:58 -0700583 try:
584 main.log.info( "Sending: " + command )
585 self.handle.sendline( command )
Jon Hall3b489db2015-10-05 14:38:37 -0700586 i = self.handle.expect( [ command, pexpect.TIMEOUT ],
587 timeout=wait + 1 )
Hari Krishna012a1c12015-08-25 14:23:58 -0700588 if i == 1:
589 main.log.error(
590 self.name +
591 ": timeout when waiting for response from mininet" )
592 main.log.error( "response: " + str( self.handle.before ) )
593 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
594 if i == 1:
595 main.log.error(
596 self.name +
597 ": timeout when waiting for response from mininet" )
598 main.log.error( "response: " + str( self.handle.before ) )
599 response = self.handle.before
600 main.log.info( self.name + ": Ping Response: " + response )
601 if re.search( ',\s0\%\spacket\sloss', response ):
602 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700603 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700604 else:
605 main.log.error(
606 self.name +
607 ": PACKET LOST, HOST IS NOT REACHABLE" )
608 return main.FALSE
609
610 except pexpect.EOF:
611 main.log.error( self.name + ": EOF exception found" )
612 main.log.error( self.name + ": " + self.handle.before )
613 main.cleanup()
614 main.exit()
615 except Exception:
616 main.log.exception( self.name + ": Uncaught exception!" )
617 main.cleanup()
618 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800619
You Wangdb927a52016-02-26 11:03:28 -0800620 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
621 """
622 Description:
623 Ping a set of destination host from host CLI.
624 Logging into a Mininet host CLI is required before calling this funtion.
625 Params:
626 dstIPList is a list of destination ip addresses
627 Returns:
628 main.TRUE if the destination host is reachable
629 main.FALSE otherwise
630 """
631 isReachable = main.TRUE
632 wait = int( wait )
633 cmd = "ping"
634 if IPv6:
635 cmd = cmd + "6"
636 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
637 try:
638 for dstIP in dstIPList:
639 pingCmd = cmd + " " + dstIP
640 self.handle.sendline( pingCmd )
641 i = self.handle.expect( [ self.hostPrompt,
642 '\*\*\* Unknown command: ' + pingCmd,
643 pexpect.TIMEOUT ],
644 timeout=wait + 1 )
645 if i == 0:
646 response = self.handle.before
647 if not re.search( ',\s0\%\spacket\sloss', response ):
648 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
649 isReachable = main.FALSE
650 elif i == 1:
651 main.log.error( self.name + ": function should be called from host CLI instead of Mininet CLI" )
652 main.cleanup()
653 main.exit()
654 elif i == 2:
655 main.log.error( self.name + ": timeout when waiting for response" )
656 isReachable = main.FALSE
657 else:
658 main.log.error( self.name + ": unknown response: " + self.handle.before )
659 isReachable = main.FALSE
660 except pexpect.TIMEOUT:
661 main.log.exception( self.name + ": TIMEOUT exception" )
662 isReachable = main.FALSE
663 except pexpect.EOF:
664 main.log.error( self.name + ": EOF exception found" )
665 main.log.error( self.name + ": " + self.handle.before )
666 main.cleanup()
667 main.exit()
668 except Exception:
669 main.log.exception( self.name + ": Uncaught exception!" )
670 main.cleanup()
671 main.exit()
672 return isReachable
673
Jon Hall7eb38402015-01-08 17:19:54 -0800674 def checkIP( self, host ):
675 """
676 Verifies the host's ip configured or not."""
677 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700678 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800679 response = self.execute(
680 cmd=host +
681 " ifconfig",
682 prompt="mininet>",
683 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800684 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800685 main.log.error( self.name + ": EOF exception found" )
686 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700687 main.cleanup()
688 main.exit()
adminbae64d82013-08-01 10:50:15 -0700689
Jon Hall7eb38402015-01-08 17:19:54 -0800690 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800691 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
692 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
693 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
694 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
695 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800696 # pattern = "inet addr:10.0.0.6"
697 if re.search( pattern, response ):
698 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700699 return main.TRUE
700 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800701 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700702 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800703 else:
704 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800705
Jon Hall7eb38402015-01-08 17:19:54 -0800706 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800707 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700708 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800709 response = self.execute(
710 cmd="h1 /usr/sbin/sshd -D&",
711 prompt="mininet>",
712 timeout=10 )
713 response = self.execute(
714 cmd="h4 /usr/sbin/sshd -D&",
715 prompt="mininet>",
716 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700717 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800718 vars( self )[ key ] = connectargs[ key ]
719 response = self.execute(
720 cmd="xterm h1 h4 ",
721 prompt="mininet>",
722 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800723 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800724 main.log.error( self.name + ": EOF exception found" )
725 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700726 main.cleanup()
727 main.exit()
adminbae64d82013-08-01 10:50:15 -0700728 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800729 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700730 if self.flag == 0:
731 self.flag = 1
732 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800733 else:
adminbae64d82013-08-01 10:50:15 -0700734 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800735
Jon Hall53c5e662016-04-13 16:06:56 -0700736 def moveHost( self, host, oldSw, newSw, ):
737 """
738 Moves a host from one switch to another on the fly
739 Note: The intf between host and oldSw when detached
740 using detach(), will still show up in the 'net'
741 cmd, because switch.detach() doesn't affect switch.intfs[]
742 ( which is correct behavior since the interfaces
743 haven't moved ).
744 """
745 if self.handle:
746 try:
747 # Bring link between oldSw-host down
748 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
749 "'," + "'down')"
750 print "cmd1= ", cmd
751 response = self.execute( cmd=cmd,
752 prompt="mininet>",
753 timeout=10 )
754
755 # Determine hostintf and Oldswitchintf
756 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
757 ")[0]"
758 print "cmd2= ", cmd
759 self.handle.sendline( cmd )
760 self.handle.expect( "mininet>" )
761
762 # Determine ip and mac address of the host-oldSw interface
763 cmd = "px ipaddr = hintf.IP()"
764 print "cmd3= ", cmd
765 self.handle.sendline( cmd )
766 self.handle.expect( "mininet>" )
767
768 cmd = "px macaddr = hintf.MAC()"
769 print "cmd3= ", cmd
770 self.handle.sendline( cmd )
771 self.handle.expect( "mininet>" )
772
773 # Detach interface between oldSw-host
774 cmd = "px " + oldSw + ".detach( sintf )"
775 print "cmd4= ", cmd
776 self.handle.sendline( cmd )
777 self.handle.expect( "mininet>" )
778
779 # Add link between host-newSw
780 cmd = "py net.addLink(" + host + "," + newSw + ")"
781 print "cmd5= ", cmd
782 self.handle.sendline( cmd )
783 self.handle.expect( "mininet>" )
784
785 # Determine hostintf and Newswitchintf
786 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
787 ")[0]"
788 print "cmd6= ", cmd
789 self.handle.sendline( cmd )
790 self.handle.expect( "mininet>" )
791
792 # Attach interface between newSw-host
793 cmd = "px " + newSw + ".attach( sintf )"
794 print "cmd3= ", cmd
795 self.handle.sendline( cmd )
796 self.handle.expect( "mininet>" )
797
798 # Set ipaddress of the host-newSw interface
799 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
800 print "cmd7 = ", cmd
801 self.handle.sendline( cmd )
802 self.handle.expect( "mininet>" )
803
804 # Set macaddress of the host-newSw interface
805 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
806 print "cmd8 = ", cmd
807 self.handle.sendline( cmd )
808 self.handle.expect( "mininet>" )
809
810 cmd = "net"
811 print "cmd9 = ", cmd
812 self.handle.sendline( cmd )
813 self.handle.expect( "mininet>" )
814 print "output = ", self.handle.before
815
816 # Determine ipaddress of the host-newSw interface
817 cmd = host + " ifconfig"
818 print "cmd10= ", cmd
819 self.handle.sendline( cmd )
820 self.handle.expect( "mininet>" )
821 print "ifconfig o/p = ", self.handle.before
822
823 return main.TRUE
824 except pexpect.EOF:
825 main.log.error( self.name + ": EOF exception found" )
826 main.log.error( self.name + ": " + self.handle.before )
827 return main.FALSE
828
Jon Hall439c8912016-04-15 02:22:03 -0700829 def moveHostv6( self, host, oldSw, newSw, ):
kelvin-onlaba1484582015-02-02 15:46:20 -0800830 """
831 Moves a host from one switch to another on the fly
832 Note: The intf between host and oldSw when detached
833 using detach(), will still show up in the 'net'
834 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700835 ( which is correct behavior since the interfaces
836 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800837 """
838 if self.handle:
839 try:
Jon Hall439c8912016-04-15 02:22:03 -0700840 IP = str( self.getIPAddress( host, proto='IPV6' ) ) + "/64"
kelvin-onlaba1484582015-02-02 15:46:20 -0800841 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700842 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800843 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800844 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800845 response = self.execute( cmd=cmd,
846 prompt="mininet>",
847 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700848
kelvin-onlaba1484582015-02-02 15:46:20 -0800849 # Determine hostintf and Oldswitchintf
850 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800851 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800852 print "cmd2= ", cmd
853 self.handle.sendline( cmd )
854 self.handle.expect( "mininet>" )
855
shahshreya73537862015-02-11 15:15:24 -0800856 # Determine ip and mac address of the host-oldSw interface
Jon Hall439c8912016-04-15 02:22:03 -0700857 cmd = "px ipaddr = " + str(IP)
kelvin-onlaba1484582015-02-02 15:46:20 -0800858 print "cmd3= ", cmd
859 self.handle.sendline( cmd )
860 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800861
862 cmd = "px macaddr = hintf.MAC()"
863 print "cmd3= ", cmd
864 self.handle.sendline( cmd )
865 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700866
kelvin-onlaba1484582015-02-02 15:46:20 -0800867 # Detach interface between oldSw-host
868 cmd = "px " + oldSw + ".detach( sintf )"
869 print "cmd4= ", cmd
870 self.handle.sendline( cmd )
871 self.handle.expect( "mininet>" )
872
873 # Add link between host-newSw
874 cmd = "py net.addLink(" + host + "," + newSw + ")"
875 print "cmd5= ", cmd
876 self.handle.sendline( cmd )
877 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700878
kelvin-onlaba1484582015-02-02 15:46:20 -0800879 # Determine hostintf and Newswitchintf
880 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800881 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800882 print "cmd6= ", cmd
883 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700884 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800885
886 # Attach interface between newSw-host
887 cmd = "px " + newSw + ".attach( sintf )"
Jon Hall439c8912016-04-15 02:22:03 -0700888 print "cmd6= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800889 self.handle.sendline( cmd )
890 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800891
892 # Set macaddress of the host-newSw interface
893 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
Jon Hall439c8912016-04-15 02:22:03 -0700894 print "cmd7 = ", cmd
895 self.handle.sendline( cmd )
896 self.handle.expect( "mininet>" )
897
898 # Set ipaddress of the host-newSw interface
899 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
shahshreya73537862015-02-11 15:15:24 -0800900 print "cmd8 = ", cmd
901 self.handle.sendline( cmd )
902 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700903
Jon Hall439c8912016-04-15 02:22:03 -0700904 cmd = host + " ifconfig"
905 print "cmd9 =",cmd
906 response = self.execute( cmd = cmd, prompt="mininet>" ,timeout=10 )
907 print response
908 pattern = "h\d-eth([\w])"
Jeremyd9e4eb12016-04-13 12:09:06 -0700909 ipAddressSearch = re.search( pattern, response )
Jon Hall439c8912016-04-15 02:22:03 -0700910 print ipAddressSearch.group(1)
911 intf= host + "-eth" + str(ipAddressSearch.group(1))
912 cmd = host + " ip -6 addr add %s dev %s" % ( IP, intf )
913 print "cmd10 = ", cmd
914 self.handle.sendline( cmd )
915 self.handle.expect( "mininet>" )
916
kelvin-onlaba1484582015-02-02 15:46:20 -0800917 cmd = "net"
Jon Hall439c8912016-04-15 02:22:03 -0700918 print "cmd11 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800919 self.handle.sendline( cmd )
920 self.handle.expect( "mininet>" )
921 print "output = ", self.handle.before
922
923 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800924 cmd = host + " ifconfig"
Jon Hall439c8912016-04-15 02:22:03 -0700925 print "cmd12= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800926 self.handle.sendline( cmd )
927 self.handle.expect( "mininet>" )
928 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700929
kelvin-onlaba1484582015-02-02 15:46:20 -0800930 return main.TRUE
931 except pexpect.EOF:
932 main.log.error( self.name + ": EOF exception found" )
933 main.log.error( self.name + ": " + self.handle.before )
934 return main.FALSE
935
Jon Hall7eb38402015-01-08 17:19:54 -0800936 def changeIP( self, host, intf, newIP, newNetmask ):
937 """
938 Changes the ip address of a host on the fly
939 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800940 if self.handle:
941 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800942 cmd = host + " ifconfig " + intf + " " + \
943 newIP + " " + 'netmask' + " " + newNetmask
944 self.handle.sendline( cmd )
945 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800946 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800947 main.log.info( "response = " + response )
948 main.log.info(
949 "Ip of host " +
950 host +
951 " changed to new IP " +
952 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800953 return main.TRUE
954 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800955 main.log.error( self.name + ": EOF exception found" )
956 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800957 return main.FALSE
958
Jon Hall7eb38402015-01-08 17:19:54 -0800959 def changeDefaultGateway( self, host, newGW ):
960 """
961 Changes the default gateway of a host
962 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800963 if self.handle:
964 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800965 cmd = host + " route add default gw " + newGW
966 self.handle.sendline( cmd )
967 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800968 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800969 main.log.info( "response = " + response )
970 main.log.info(
971 "Default gateway of host " +
972 host +
973 " changed to " +
974 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800975 return main.TRUE
976 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800977 main.log.error( self.name + ": EOF exception found" )
978 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800979 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800980
Jon Hall7eb38402015-01-08 17:19:54 -0800981 def addStaticMACAddress( self, host, GW, macaddr ):
982 """
Jon Hallefbd9792015-03-05 16:11:36 -0800983 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800984 if self.handle:
985 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800986 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
987 cmd = host + " arp -s " + GW + " " + macaddr
988 self.handle.sendline( cmd )
989 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800990 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800991 main.log.info( "response = " + response )
992 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800993 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800994 GW +
995 " changed to " +
996 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800997 return main.TRUE
998 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 )
shahshreyad0c80432014-12-04 16:56:05 -08001001 return main.FALSE
1002
Jon Hall7eb38402015-01-08 17:19:54 -08001003 def verifyStaticGWandMAC( self, host ):
1004 """
1005 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -08001006 if self.handle:
1007 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001008 # h1 arp -an
1009 cmd = host + " arp -an "
1010 self.handle.sendline( cmd )
1011 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -08001012 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -08001013 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -08001014 return main.TRUE
1015 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001016 main.log.error( self.name + ": EOF exception found" )
1017 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -08001018 return main.FALSE
1019
Jon Hall7eb38402015-01-08 17:19:54 -08001020 def getMacAddress( self, host ):
1021 """
1022 Verifies the host's ip configured or not."""
1023 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001024 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001025 response = self.execute(
1026 cmd=host +
1027 " ifconfig",
1028 prompt="mininet>",
1029 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001030 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001031 main.log.error( self.name + ": EOF exception found" )
1032 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001033 main.cleanup()
1034 main.exit()
adminbae64d82013-08-01 10:50:15 -07001035
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -07001036 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001037 macAddressSearch = re.search( pattern, response, re.I )
1038 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001039 main.log.info(
1040 self.name +
1041 ": Mac-Address of Host " +
1042 host +
1043 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001044 macAddress )
1045 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001046 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001047 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001048
Jon Hall7eb38402015-01-08 17:19:54 -08001049 def getInterfaceMACAddress( self, host, interface ):
1050 """
1051 Return the IP address of the interface on the given host"""
1052 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001053 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001054 response = self.execute( cmd=host + " ifconfig " + interface,
1055 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001056 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001057 main.log.error( self.name + ": EOF exception found" )
1058 main.log.error( self.name + ": " + self.handle.before )
1059 main.cleanup()
1060 main.exit()
1061
1062 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001063 macAddressSearch = re.search( pattern, response, re.I )
1064 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001065 main.log.info( "No mac address found in %s" % response )
1066 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001067 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -08001068 main.log.info(
1069 "Mac-Address of " +
1070 host +
1071 ":" +
1072 interface +
1073 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001074 macAddress )
1075 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -08001076 else:
1077 main.log.error( "Connection failed to the host" )
1078
sathishmad953462015-12-03 17:42:07 +05301079 def getIPAddress( self, host , proto='IPV4'):
Jon Hall7eb38402015-01-08 17:19:54 -08001080 """
1081 Verifies the host's ip configured or not."""
1082 if self.handle:
1083 try:
1084 response = self.execute(
1085 cmd=host +
1086 " ifconfig",
1087 prompt="mininet>",
1088 timeout=10 )
1089 except pexpect.EOF:
1090 main.log.error( self.name + ": EOF exception found" )
1091 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001092 main.cleanup()
1093 main.exit()
adminbae64d82013-08-01 10:50:15 -07001094
sathishmad953462015-12-03 17:42:07 +05301095 pattern = ''
1096 if proto == 'IPV4':
1097 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
1098 else:
Jon Hall439c8912016-04-15 02:22:03 -07001099 pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001100 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -08001101 main.log.info(
1102 self.name +
1103 ": IP-Address of Host " +
1104 host +
1105 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001106 ipAddressSearch.group( 1 ) )
1107 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -08001108 else:
1109 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001110
Jon Hall7eb38402015-01-08 17:19:54 -08001111 def getSwitchDPID( self, switch ):
1112 """
1113 return the datapath ID of the switch"""
1114 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001115 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -07001116 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001117 response = self.execute(
1118 cmd=cmd,
1119 prompt="mininet>",
1120 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001121 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001122 main.log.error( self.name + ": EOF exception found" )
1123 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001124 main.cleanup()
1125 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -08001126 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -08001127 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001128 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001129 main.log.info(
1130 "Couldn't find DPID for switch %s, found: %s" %
1131 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001132 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001133 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001134 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001135 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001136
Jon Hall7eb38402015-01-08 17:19:54 -08001137 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -07001138 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -08001139 self.handle.sendline( "" )
1140 self.expect( "mininet>" )
1141 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -07001142 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001143 response = self.execute(
1144 cmd=cmd,
1145 prompt="mininet>",
1146 timeout=10 )
1147 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -07001148 response = self.handle.before
1149 return response
1150 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001151 main.log.error( self.name + ": EOF exception found" )
1152 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -07001153 main.cleanup()
1154 main.exit()
1155
Jon Hall7eb38402015-01-08 17:19:54 -08001156 def getInterfaces( self, node ):
1157 """
1158 return information dict about interfaces connected to the node"""
1159 if self.handle:
1160 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -08001161 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001162 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -07001163 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001164 response = self.execute(
1165 cmd=cmd,
1166 prompt="mininet>",
1167 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001168 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001169 main.log.error( self.name + ": EOF exception found" )
1170 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001171 main.cleanup()
1172 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001173 return response
1174 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001175 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -07001176
Jon Hall7eb38402015-01-08 17:19:54 -08001177 def dump( self ):
1178 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001179 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 response = self.execute(
1181 cmd='dump',
1182 prompt='mininet>',
1183 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001184 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001185 main.log.error( self.name + ": EOF exception found" )
1186 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001187 main.cleanup()
1188 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001189 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001190
Jon Hall7eb38402015-01-08 17:19:54 -08001191 def intfs( self ):
1192 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001193 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001194 response = self.execute(
1195 cmd='intfs',
1196 prompt='mininet>',
1197 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001198 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001199 main.log.error( self.name + ": EOF exception found" )
1200 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001201 main.cleanup()
1202 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001203 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001204
Jon Hall7eb38402015-01-08 17:19:54 -08001205 def net( self ):
1206 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001207 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001208 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001209 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001210 main.log.error( self.name + ": EOF exception found" )
1211 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001212 main.cleanup()
1213 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001214 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001215
YPZhang81a7d4e2016-04-18 13:10:17 -07001216 def links( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07001217 main.log.info( self.name + ": List network links" )
1218 try:
1219 response = self.execute( cmd='links', prompt='mininet>',
YPZhang81a7d4e2016-04-18 13:10:17 -07001220 timeout=timeout )
Jon Hallafa8a472015-06-12 14:02:42 -07001221 except pexpect.EOF:
1222 main.log.error( self.name + ": EOF exception found" )
1223 main.log.error( self.name + ": " + self.handle.before )
1224 main.cleanup()
1225 main.exit()
1226 return response
1227
GlennRC61321f22015-07-16 13:36:54 -07001228 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001229 '''
1230 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001231
kelvin-onlab7cce9382015-07-17 10:21:03 -07001232 @parm:
1233 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1234 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1235 '''
1236 for host1 in hosts:
1237 for host2 in hosts:
1238 if host1 != host2:
1239 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1240 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001241
1242 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001243 '''
1244 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1245 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001246
kelvin-onlab7cce9382015-07-17 10:21:03 -07001247 @parm:
1248 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1249 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1250 '''
1251 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1252 try:
1253 # Setup the mininet command
1254 cmd1 = 'iperf ' + host1 + " " + host2
1255 self.handle.sendline( cmd1 )
1256 outcome = self.handle.expect( "mininet>", timeout )
1257 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001258
kelvin-onlab7cce9382015-07-17 10:21:03 -07001259 # checks if there are results in the mininet response
1260 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001261 main.log.report(self.name + ": iperf test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001262 # parse the mn results
1263 response = response.split("\r\n")
1264 response = response[len(response)-2]
1265 response = response.split(": ")
1266 response = response[len(response)-1]
1267 response = response.replace("[", "")
1268 response = response.replace("]", "")
1269 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001270
kelvin-onlab7cce9382015-07-17 10:21:03 -07001271 # this is the bandwith two and from the two hosts
1272 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001273
kelvin-onlab7cce9382015-07-17 10:21:03 -07001274 # there should be two elements in the bandwidth list
1275 # ['host1 to host2', 'host2 to host1"]
1276 if len(bandwidth) == 2:
1277 main.log.report(self.name + ": iperf test successful")
1278 return main.TRUE
1279 else:
1280 main.log.error(self.name + ": invalid iperf results")
1281 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001282 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001283 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001284 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001285 except pexpect.TIMEOUT:
Jon Hall3b489db2015-10-05 14:38:37 -07001286 main.log.error( self.name + ": TIMEOUT exception found" )
1287 main.log.error( self.name + " response: " +
Jon Hall892818c2015-10-20 17:58:34 -07001288 repr( self.handle.before ) )
Jon Hall3b489db2015-10-05 14:38:37 -07001289 # NOTE: Send ctrl-c to make sure iperf is done
1290 self.handle.sendline( "\x03" )
1291 self.handle.expect( "Interrupt" )
1292 self.handle.expect( "mininet>" )
GlennRC61321f22015-07-16 13:36:54 -07001293 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001294 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001295 main.log.error( self.name + ": EOF exception found" )
1296 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001297 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001298 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001299
Jon Hall439c8912016-04-15 02:22:03 -07001300 def iperftcpipv6(self, host1="h1", host2="h2", timeout=50):
1301 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1302 try:
1303 IP1 = self.getIPAddress( host1, proto='IPV6' )
1304 cmd1 = host1 +' iperf -V -sD -B '+ str(IP1)
1305 self.handle.sendline( cmd1 )
1306 outcome1 = self.handle.expect( "mininet>")
1307 cmd2 = host2 +' iperf -V -c '+ str(IP1) +' -t 5'
1308 self.handle.sendline( cmd2 )
1309 outcome2 = self.handle.expect( "mininet>")
1310 response1 = self.handle.before
1311 response2 = self.handle.after
1312 print response1,response2
1313 pattern = "connected with "+ str(IP1)
1314 if pattern in response1:
1315 main.log.report(self.name + ": iperf test completed")
1316 return main.TRUE
1317 else:
1318 main.log.error( self.name + ": iperf test failed" )
1319 return main.FALSE
1320 except pexpect.TIMEOUT:
1321 main.log.error( self.name + ": TIMEOUT exception found" )
1322 main.log.error( self.name + " response: " + repr( self.handle.before ) )
1323 self.handle.sendline( "\x03" )
1324 self.handle.expect( "Interrupt" )
1325 self.handle.expect( "mininet>" )
1326 return main.FALSE
1327 except pexpect.EOF:
1328 main.log.error( self.name + ": EOF exception found" )
1329 main.log.error( self.name + ": " + self.handle.before )
1330 main.cleanup()
1331 main.exit()
1332
GlennRC61321f22015-07-16 13:36:54 -07001333 def iperfudpAll(self, hosts, bandwidth="10M"):
1334 '''
1335 Runs the iperfudp function with a given set of hosts and specified
1336 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001337
GlennRC61321f22015-07-16 13:36:54 -07001338 @param:
1339 bandwidth: the targeted bandwidth, in megabits ('M')
1340 '''
1341 for host1 in hosts:
1342 for host2 in hosts:
1343 if host1 != host2:
1344 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1345 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1346
1347 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1348
kelvin-onlab7cce9382015-07-17 10:21:03 -07001349 '''
1350 Creates an iperf UDP test with a specific bandwidth.
1351 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001352
kelvin-onlab7cce9382015-07-17 10:21:03 -07001353 @param:
1354 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1355 '''
1356 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1357 try:
1358 # setup the mininet command
1359 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1360 self.handle.sendline(cmd)
1361 self.handle.expect("mininet>")
1362 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001363
kelvin-onlab7cce9382015-07-17 10:21:03 -07001364 # check if there are in results in the mininet response
1365 if "Results:" in response:
Jon Hall892818c2015-10-20 17:58:34 -07001366 main.log.report(self.name + ": iperfudp test completed")
kelvin-onlab7cce9382015-07-17 10:21:03 -07001367 # parse the results
1368 response = response.split("\r\n")
1369 response = response[len(response)-2]
1370 response = response.split(": ")
1371 response = response[len(response)-1]
1372 response = response.replace("[", "")
1373 response = response.replace("]", "")
1374 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001375
kelvin-onlab7cce9382015-07-17 10:21:03 -07001376 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001377
kelvin-onlab7cce9382015-07-17 10:21:03 -07001378 # check to see if there are at least three entries
1379 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1380 if len(mnBandwidth) == 3:
1381 # if one entry is blank then something is wrong
1382 for item in mnBandwidth:
1383 if item == "":
1384 main.log.error(self.name + ": Could not parse iperf output")
1385 main.log.error(self.name + ": invalid iperfudp results")
1386 return main.FALSE
1387 # otherwise results are vaild
1388 main.log.report(self.name + ": iperfudp test successful")
1389 return main.TRUE
1390 else:
1391 main.log.error(self.name + ": invalid iperfudp results")
1392 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001393
kelvin-onlab7cce9382015-07-17 10:21:03 -07001394 except pexpect.EOF:
1395 main.log.error( self.name + ": EOF exception found" )
1396 main.log.error( self.name + ": " + self.handle.before )
1397 main.cleanup()
1398 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001399
Jon Hall7eb38402015-01-08 17:19:54 -08001400 def nodes( self ):
1401 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001402 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001403 response = self.execute(
1404 cmd='nodes',
1405 prompt='mininet>',
1406 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001407 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001408 main.log.error( self.name + ": EOF exception found" )
1409 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001410 main.cleanup()
1411 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001412 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001413
Jon Hall7eb38402015-01-08 17:19:54 -08001414 def pingpair( self ):
1415 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001416 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001417 response = self.execute(
1418 cmd='pingpair',
1419 prompt='mininet>',
1420 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001421 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001422 main.log.error( self.name + ": EOF exception found" )
1423 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001424 main.cleanup()
1425 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001426
Jon Hall7eb38402015-01-08 17:19:54 -08001427 if re.search( ',\s0\%\spacket\sloss', response ):
1428 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001429 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001430 else:
1431 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001432 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001433
Jon Hall7eb38402015-01-08 17:19:54 -08001434 def link( self, **linkargs ):
1435 """
GlennRCed771242016-01-13 17:02:47 -08001436 Bring link( s ) between two nodes up or down
1437 """
Jon Hall6094a362014-04-11 14:46:56 -07001438 try:
GlennRCed771242016-01-13 17:02:47 -08001439 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
1440 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1441 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1442 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1443
1444 main.log.info( "Bring link between " + str( end1 ) + " and " + str( end2 ) + " " + str( option ) )
1445 cmd = "link {} {} {}".format( end1, end2, option )
1446 self.handle.sendline( cmd )
Jon Hall7eb38402015-01-08 17:19:54 -08001447 self.handle.expect( "mininet>" )
GlennRCed771242016-01-13 17:02:47 -08001448 response = self.handle.before
1449 main.log.info( response )
1450
1451 return main.TRUE
1452 except pexpect.TIMEOUT:
1453 main.log.exception( self.name + ": Command timed out" )
1454 return None
Jon Hallfbc828e2015-01-06 17:30:19 -08001455 except pexpect.EOF:
GlennRCed771242016-01-13 17:02:47 -08001456 main.log.exception( self.name + ": connection closed." )
Jon Hall6094a362014-04-11 14:46:56 -07001457 main.cleanup()
1458 main.exit()
GlennRCed771242016-01-13 17:02:47 -08001459 except Exception:
1460 main.log.exception( self.name + ": Uncaught exception!" )
1461 main.cleanup()
1462 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001463
pingping-lin8244a3b2015-09-16 13:36:56 -07001464 def switch( self, **switchargs ):
1465 """
1466 start/stop a switch
1467 """
1468 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1469 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1470 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1471 command = "switch " + str( sw ) + " " + str( option )
1472 main.log.info( command )
1473 try:
1474 self.handle.sendline( command )
1475 self.handle.expect( "mininet>" )
1476 except pexpect.TIMEOUT:
1477 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1478 main.cleanup()
1479 main.exit()
1480 except pexpect.EOF:
1481 main.log.error( self.name + ": EOF exception found" )
1482 main.log.error( self.name + ": " + self.handle.before )
1483 main.cleanup()
1484 main.exit()
1485 return main.TRUE
1486
pingping-lin5bb663b2015-09-24 11:47:50 -07001487 def node( self, nodeName, commandStr ):
1488 """
1489 Carry out a command line on a given node
1490 @parm:
1491 nodeName: the node name in Mininet testbed
1492 commandStr: the command line will be carried out on the node
1493 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1494 """
1495 command = str( nodeName ) + " " + str( commandStr )
1496 main.log.info( command )
1497
1498 try:
1499 response = self.execute( cmd = command, prompt = "mininet>" )
1500 if re.search( "Unknown command", response ):
1501 main.log.warn( response )
1502 return main.FALSE
Jon Hall9ed8f372016-02-24 17:34:07 -08001503 if re.search( "Permission denied", response ):
1504 main.log.warn( response )
1505 return main.FALSE
pingping-lin5bb663b2015-09-24 11:47:50 -07001506 except pexpect.TIMEOUT:
1507 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1508 main.cleanup()
1509 main.exit()
1510 except pexpect.EOF:
1511 main.log.error( self.name + ": EOF exception found" )
1512 main.log.error( self.name + ": " + self.handle.before )
1513 main.cleanup()
1514 main.exit()
1515 main.log.info( " response is :" )
1516 main.log.info( response )
1517 return response
1518
Jon Hall7eb38402015-01-08 17:19:54 -08001519 def yank( self, **yankargs ):
1520 """
1521 yank a mininet switch interface to a host"""
1522 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001523 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001524 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1525 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1526 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001527 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001528 response = self.execute(
1529 cmd=command,
1530 prompt="mininet>",
1531 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001532 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001533 main.log.error( self.name + ": EOF exception found" )
1534 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001535 main.cleanup()
1536 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001537 return main.TRUE
1538
Jon Hall7eb38402015-01-08 17:19:54 -08001539 def plug( self, **plugargs ):
1540 """
1541 plug the yanked mininet switch interface to a switch"""
1542 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001543 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001544 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1545 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1546 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001547 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001548 response = self.execute(
1549 cmd=command,
1550 prompt="mininet>",
1551 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001552 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001553 main.log.error( self.name + ": EOF exception found" )
1554 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001555 main.cleanup()
1556 main.exit()
adminbae64d82013-08-01 10:50:15 -07001557 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001558
Jon Hall7eb38402015-01-08 17:19:54 -08001559 def dpctl( self, **dpctlargs ):
1560 """
1561 Run dpctl command on all switches."""
1562 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001563 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001564 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1565 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1566 command = "dpctl " + cmd + " " + str( cmdargs )
1567 try:
1568 response = self.execute(
1569 cmd=command,
1570 prompt="mininet>",
1571 timeout=10 )
1572 except pexpect.EOF:
1573 main.log.error( self.name + ": EOF exception found" )
1574 main.log.error( self.name + ": " + self.handle.before )
1575 main.cleanup()
1576 main.exit()
1577 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001578
kelvin-onlabd3b64892015-01-20 13:26:24 -08001579 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001580 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001581 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001582 fileInput = path + '/lib/Mininet/INSTALL'
1583 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001584 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001585 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001586 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001587 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001588 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001589 return version
adminbae64d82013-08-01 10:50:15 -07001590
kelvin-onlabd3b64892015-01-20 13:26:24 -08001591 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001592 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001593 Parameters:
1594 sw: The name of an OVS switch. Example "s1"
1595 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001596 The output of the command from the mininet cli
1597 or main.FALSE on timeout"""
1598 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001599 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001600 response = self.execute(
1601 cmd=command,
1602 prompt="mininet>",
1603 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001604 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001605 return response
admin2a9548d2014-06-17 14:08:07 -07001606 else:
1607 return main.FALSE
1608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 main.log.error( self.name + ": EOF exception found" )
1610 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001611 main.cleanup()
1612 main.exit()
adminbae64d82013-08-01 10:50:15 -07001613
Charles Chan029be652015-08-24 01:46:10 +08001614 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001615 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001616 Description:
1617 Assign switches to the controllers ( for ovs use only )
1618 Required:
1619 sw - Name of the switch. This can be a list or a string.
1620 ip - Ip addresses of controllers. This can be a list or a string.
1621 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001622 port - ONOS use port 6653, if no list of ports is passed, then
1623 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001624 ptcp - ptcp number, This can be a string or a list that has
1625 the same length as switch. This is optional and not required
1626 when using ovs switches.
1627 NOTE: If switches and ptcp are given in a list type they should have the
1628 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1629 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001630
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001631 Return:
1632 Returns main.TRUE if mininet correctly assigned switches to
1633 controllers, otherwise it will return main.FALSE or an appropriate
1634 exception(s)
1635 """
1636 assignResult = main.TRUE
1637 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001638 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001639 command = "sh ovs-vsctl set-controller "
1640 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001641 try:
1642 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001643 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001644 if isinstance( port, types.StringType ) or \
1645 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001646 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001647 elif isinstance( port, types.ListType ):
1648 main.log.error( self.name + ": Only one controller " +
1649 "assigned and a list of ports has" +
1650 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001651 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001652 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001653 main.log.error( self.name + ": Invalid controller port " +
1654 "number. Please specify correct " +
1655 "controller port" )
1656 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001657
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001658 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001659 if isinstance( port, types.StringType ) or \
1660 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001661 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001662 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1663 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001664 elif isinstance( port, types.ListType ):
1665 if ( len( ip ) != len( port ) ):
1666 main.log.error( self.name + ": Port list = " +
1667 str( len( port ) ) +
1668 "should be the same as controller" +
1669 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001670 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001671 else:
1672 onosIp = ""
1673 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001674 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1675 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001676 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001677 main.log.error( self.name + ": Invalid controller port " +
1678 "number. Please specify correct " +
1679 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001680 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001681 else:
1682 main.log.error( self.name + ": Invalid ip address" )
1683 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001684
1685 if isinstance( sw, types.StringType ):
1686 command += sw + " "
1687 if ptcp:
1688 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001689 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001690 elif isinstance( ptcp, types.ListType ):
1691 main.log.error( self.name + ": Only one switch is " +
1692 "being set and multiple PTCP is " +
1693 "being passed " )
1694 else:
1695 main.log.error( self.name + ": Invalid PTCP" )
1696 ptcp = ""
1697 command += onosIp
1698 commandList.append( command )
1699
1700 elif isinstance( sw, types.ListType ):
1701 if ptcp:
1702 if isinstance( ptcp, types.ListType ):
1703 if len( ptcp ) != len( sw ):
1704 main.log.error( self.name + ": PTCP length = " +
1705 str( len( ptcp ) ) +
1706 " is not the same as switch" +
1707 " length = " +
1708 str( len( sw ) ) )
1709 return main.FALSE
1710 else:
1711 for switch, ptcpNum in zip( sw, ptcp ):
1712 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001713 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001714 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001715 tempCmd += onosIp
1716 commandList.append( tempCmd )
1717 else:
1718 main.log.error( self.name + ": Invalid PTCP" )
1719 return main.FALSE
1720 else:
1721 for switch in sw:
1722 tempCmd = "sh ovs-vsctl set-controller "
1723 tempCmd += switch + " " + onosIp
1724 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001725 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001726 main.log.error( self.name + ": Invalid switch type " )
1727 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001728
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001729 for cmd in commandList:
1730 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001731 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001732 except pexpect.TIMEOUT:
1733 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1734 return main.FALSE
1735 except pexpect.EOF:
1736 main.log.error( self.name + ": EOF exception found" )
1737 main.log.error( self.name + ": " + self.handle.before )
1738 main.cleanup()
1739 main.exit()
1740 return main.TRUE
1741 except Exception:
1742 main.log.exception( self.name + ": Uncaught exception!" )
1743 main.cleanup()
1744 main.exit()
adminbae64d82013-08-01 10:50:15 -07001745
kelvin-onlabd3b64892015-01-20 13:26:24 -08001746 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001747 """
1748 Removes the controller target from sw"""
1749 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001750 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001751 response = self.execute(
1752 cmd=command,
1753 prompt="mininet>",
1754 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001755 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001756 main.log.error( self.name + ": EOF exception found" )
1757 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001758 main.cleanup()
1759 main.exit()
1760 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001761 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001762
kelvin-onlabd3b64892015-01-20 13:26:24 -08001763 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001764 """
Jon Hallb1290e82014-11-18 16:17:48 -05001765 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001766 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001767 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001768 NOTE: cannot currently specify what type of switch
1769 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001770 sw = name of the new switch as a string
1771 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001772 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001773 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001774 """
1775 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001776 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001777 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001778 response = self.execute(
1779 cmd=command,
1780 prompt="mininet>",
1781 timeout=10 )
1782 if re.search( "already exists!", response ):
1783 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001784 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001785 elif re.search( "Error", response ):
1786 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001787 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001788 elif re.search( "usage:", response ):
1789 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001790 return main.FALSE
1791 else:
1792 return main.TRUE
1793 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001794 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001795 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001796 main.cleanup()
1797 main.exit()
1798
kelvin-onlabd3b64892015-01-20 13:26:24 -08001799 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001800 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001801 delete a switch from the mininet topology
1802 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001803 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001804 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001805 sw = name of the switch as a string
1806 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001807 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001808 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001809 response = self.execute(
1810 cmd=command,
1811 prompt="mininet>",
1812 timeout=10 )
1813 if re.search( "no switch named", response ):
1814 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001815 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001816 elif re.search( "Error", response ):
1817 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001818 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001819 elif re.search( "usage:", response ):
1820 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001821 return main.FALSE
1822 else:
1823 return main.TRUE
1824 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001825 main.log.error( self.name + ": EOF exception found" )
1826 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001827 main.cleanup()
1828 main.exit()
1829
kelvin-onlabd3b64892015-01-20 13:26:24 -08001830 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001831 """
1832 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001833 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001834 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001835 NOTE: cannot currently specify what type of link
1836 required params:
1837 node1 = the string node name of the first endpoint of the link
1838 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001839 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001840 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001841 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001842 response = self.execute(
1843 cmd=command,
1844 prompt="mininet>",
1845 timeout=10 )
1846 if re.search( "doesnt exist!", response ):
1847 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001848 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001849 elif re.search( "Error", response ):
1850 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001851 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001852 elif re.search( "usage:", response ):
1853 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001854 return main.FALSE
1855 else:
1856 return main.TRUE
1857 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001858 main.log.error( self.name + ": EOF exception found" )
1859 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001860 main.cleanup()
1861 main.exit()
1862
kelvin-onlabd3b64892015-01-20 13:26:24 -08001863 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001864 """
1865 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001866 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001867 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001868 required params:
1869 node1 = the string node name of the first endpoint of the link
1870 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001871 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001872 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001873 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001874 response = self.execute(
1875 cmd=command,
1876 prompt="mininet>",
1877 timeout=10 )
1878 if re.search( "no node named", response ):
1879 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001880 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001881 elif re.search( "Error", response ):
1882 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001883 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001884 elif re.search( "usage:", response ):
1885 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001886 return main.FALSE
1887 else:
1888 return main.TRUE
1889 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001890 main.log.error( self.name + ": EOF exception found" )
1891 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001892 main.cleanup()
1893 main.exit()
1894
kelvin-onlabd3b64892015-01-20 13:26:24 -08001895 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001896 """
Jon Hallb1290e82014-11-18 16:17:48 -05001897 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001898 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001899 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001900 NOTE: cannot currently specify what type of host
1901 required params:
1902 hostname = the string hostname
1903 optional key-value params
1904 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001905 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001906 """
1907 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001908 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001909 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001910 response = self.execute(
1911 cmd=command,
1912 prompt="mininet>",
1913 timeout=10 )
1914 if re.search( "already exists!", response ):
1915 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001916 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001917 elif re.search( "doesnt exists!", response ):
1918 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001919 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001920 elif re.search( "Error", response ):
1921 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001922 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001923 elif re.search( "usage:", response ):
1924 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001925 return main.FALSE
1926 else:
1927 return main.TRUE
1928 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001929 main.log.error( self.name + ": EOF exception found" )
1930 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001931 main.cleanup()
1932 main.exit()
1933
kelvin-onlabd3b64892015-01-20 13:26:24 -08001934 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001935 """
1936 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001937 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001938 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001939 NOTE: this uses a custom mn function
1940 required params:
1941 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001942 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001943 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001944 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001945 response = self.execute(
1946 cmd=command,
1947 prompt="mininet>",
1948 timeout=10 )
1949 if re.search( "no host named", response ):
1950 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001951 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001952 elif re.search( "Error", response ):
1953 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001954 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001955 elif re.search( "usage:", response ):
1956 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001957 return main.FALSE
1958 else:
1959 return main.TRUE
1960 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001961 main.log.error( self.name + ": EOF exception found" )
1962 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001963 main.cleanup()
1964 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001965
Jon Hall7eb38402015-01-08 17:19:54 -08001966 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001967 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001968 Called at the end of the test to stop the mininet and
1969 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001970 """
Jon Halld80cc142015-07-06 13:36:05 -07001971 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001972 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001973 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001974 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001975 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001976 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001977 elif i == 1:
1978 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001979 # print "Disconnecting Mininet"
1980 if self.handle:
1981 self.handle.sendline( "exit" )
1982 self.handle.expect( "exit" )
1983 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001984 else:
1985 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001986 return response
1987
Jon Halld80cc142015-07-06 13:36:05 -07001988 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001989 """
Jon Hall21270ac2015-02-16 17:59:55 -08001990 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001991 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001992 main.FALSE if the pexpect handle does not exist.
1993
Jon Halld61331b2015-02-17 16:35:47 -08001994 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001995 """
Jon Halld61331b2015-02-17 16:35:47 -08001996 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001997 response = ''
1998 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001999 try:
Jon Halld80cc142015-07-06 13:36:05 -07002000 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08002001 i = self.handle.expect( [ 'mininet>',
2002 '\$',
2003 pexpect.EOF,
2004 pexpect.TIMEOUT ],
2005 timeout )
2006 if i == 0:
2007 main.log.info( "Exiting mininet..." )
Jeremyd9e4eb12016-04-13 12:09:06 -07002008 response = self.execute( cmd="exit",
2009 prompt="(.*)",
2010 timeout=120 )
2011 main.log.info( self.name + ": Stopped" )
2012 self.handle.sendline( "sudo mn -c" )
2013 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002014
Jeremyd9e4eb12016-04-13 12:09:06 -07002015 elif i == 1:
kelvin-onlab56a3f462015-02-06 14:04:43 -08002016 main.log.info( " Mininet trying to exit while not " +
2017 "in the mininet prompt" )
Jeremy9cdb1132016-04-19 10:50:40 -07002018 response = main.TRUE
kelvin-onlab56a3f462015-02-06 14:04:43 -08002019 elif i == 2:
2020 main.log.error( "Something went wrong exiting mininet" )
2021 elif i == 3: # timeout
2022 main.log.error( "Something went wrong exiting mininet " +
2023 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07002024
Hari Krishnab35c6d02015-03-18 11:13:51 -07002025 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07002026 self.handle.sendline( "" )
2027 self.handle.expect( '\$' )
2028 self.handle.sendline(
2029 "sudo kill -9 \`ps -ef | grep \"" +
2030 fileName +
2031 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002032 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002033 main.log.error( self.name + ": EOF exception found" )
2034 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07002035 main.cleanup()
2036 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08002037 else:
2038 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07002039 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08002040 return response
2041
YPZhang26a139e2016-04-25 14:01:55 -07002042 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="", output=True, noResult=False ):
kelvin-onlab65782a82015-05-07 14:12:13 -07002043 """
2044 Description:
2045 Sends arp message from mininet host for hosts discovery
2046 Required:
2047 host - hosts name
2048 Optional:
2049 ip - ip address that does not exist in the network so there would
2050 be no reply.
2051 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07002052 if ethDevice:
2053 ethDevice = '-I ' + ethDevice + ' '
YPZhang26a139e2016-04-25 14:01:55 -07002054 cmd = srcHost + " arping -c1 "
2055 if noResult:
2056 cmd += "-w10 " # If we don't want the actural arping result, set -w10, arping will exit after 10 ms.
2057 cmd += ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08002058 try:
YPZhang81a7d4e2016-04-18 13:10:17 -07002059 if output:
2060 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07002061 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07002062 i = self.handle.expect( [ "mininet>", "arping: " ] )
2063 if i == 0:
2064 return main.TRUE
2065 elif i == 1:
2066 response = self.handle.before + self.handle.after
2067 self.handle.expect( "mininet>" )
2068 response += self.handle.before + self.handle.after
2069 main.log.warn( "Error sending arping, output was: " +
2070 response )
2071 return main.FALSE
2072 except pexpect.TIMEOUT:
2073 main.log.error( self.name + ": TIMEOUT exception found" )
2074 main.log.warn( self.handle.before )
2075 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07002076 except pexpect.EOF:
2077 main.log.error( self.name + ": EOF exception found" )
2078 main.log.error( self.name + ": " + self.handle.before )
2079 main.cleanup()
2080 main.exit()
admin07529932013-11-22 14:58:28 -08002081
Jon Hall7eb38402015-01-08 17:19:54 -08002082 def decToHex( self, num ):
2083 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08002084
Jon Hall7eb38402015-01-08 17:19:54 -08002085 def getSwitchFlowCount( self, switch ):
2086 """
2087 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07002088 if self.handle:
2089 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
2090 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002091 response = self.execute(
2092 cmd=cmd,
2093 prompt="mininet>",
2094 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07002095 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002096 main.log.error( self.name + ": EOF exception found" )
2097 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002098 main.cleanup()
2099 main.exit()
2100 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08002101 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07002102 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08002103 main.log.info(
2104 "Couldn't find flows on switch %s, found: %s" %
2105 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07002106 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002107 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07002108 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002109 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08002110
Jon Hall9ed8f372016-02-24 17:34:07 -08002111 def checkFlows( self, sw, dumpFormat=None ):
2112 if dumpFormat:
2113 command = "sh ovs-ofctl -F " + \
2114 dumpFormat + " dump-flows " + str( sw )
2115 else:
2116 command = "sh ovs-ofctl dump-flows " + str( sw )
2117 try:
2118 response = self.execute(
2119 cmd=command,
2120 prompt="mininet>",
2121 timeout=10 )
2122 return response
2123 except pexpect.EOF:
2124 main.log.error( self.name + ": EOF exception found" )
2125 main.log.error( self.name + ": " + self.handle.before )
2126 main.cleanup()
2127 main.exit()
2128
GlennRC68467eb2015-11-16 18:01:01 -08002129 def flowTableComp( self, flowTable1, flowTable2 ):
2130 # This function compares the selctors and treatments of each flow
2131 try:
Jon Hall3c512f72016-05-06 10:44:45 -07002132 assert flowTable1, "flowTable1 is empty or None"
2133 assert flowTable2, "flowTable2 is empty or None"
Jon Hall41d39f12016-04-11 22:54:35 -07002134 returnValue = main.TRUE
GlennRC68467eb2015-11-16 18:01:01 -08002135 if len(flowTable1) != len(flowTable2):
2136 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002137 returnValue = main.FALSE
GlennRCfa65fce2015-12-16 13:16:08 -08002138 dFields = ["n_bytes", "cookie", "n_packets", "duration"]
2139 for flow1, flow2 in zip(flowTable1, flowTable2):
Jon Hallacd1b182015-12-17 11:43:20 -08002140 for field in dFields:
2141 try:
2142 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002143 except KeyError:
2144 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002145 try:
2146 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002147 except KeyError:
2148 pass
GlennRC68467eb2015-11-16 18:01:01 -08002149 for i in range( len(flowTable1) ):
GlennRC17bbcf52015-12-14 17:31:50 -08002150 if flowTable1[i] not in flowTable2:
2151 main.log.warn( "Flow tables do not match:" )
2152 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[i] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002153 returnValue = main.FALSE
2154 break
2155 return returnValue
Jon Hall3c512f72016-05-06 10:44:45 -07002156 except AssertionError:
2157 main.log.exception( "Nothing to compare" )
2158 return main.FALSE
GlennRC68467eb2015-11-16 18:01:01 -08002159 except Exception:
2160 main.log.exception( "Uncaught exception!" )
2161 main.cleanup()
2162 main.exit()
Jon Hall9043c902015-07-30 14:23:44 -07002163
GlennRC528ad292015-11-12 10:38:18 -08002164 def parseFlowTable( self, flowTable, version="", debug=True ):
GlennRC956ea742015-11-05 16:14:15 -08002165 '''
2166 Discription: Parses flows into json format.
2167 NOTE: this can parse any string thats separated with commas
2168 Arguments:
2169 Required:
2170 flows: a list of strings that represnt flows
2171 Optional:
2172 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2173 debug: prints out the final result
2174 returns: A list of flows in json format
2175 '''
GlennRC528ad292015-11-12 10:38:18 -08002176 jsonFlowTable = []
You Wang91c37cf2016-05-23 09:39:42 -07002177 try:
2178 for flow in flowTable:
2179 jsonFlow = {}
2180 # split up the fields of the flow
2181 parsedFlow = flow.split(", ")
2182 # get rid of any spaces in front of the field
2183 for i in range( len(parsedFlow) ):
2184 item = parsedFlow[i]
2185 if item[0] == " ":
2186 parsedFlow[i] = item[1:]
2187 # grab the selector and treatment from the parsed flow
2188 # the last element is the selector and the treatment
2189 temp = parsedFlow.pop(-1)
2190 # split up the selector and the treatment
2191 temp = temp.split(" ")
2192 index = 0
2193 # parse the flags
2194 # NOTE: This only parses one flag
2195 flag = {}
2196 if version == "1.3":
2197 flag = {"flag":[temp[index]]}
2198 index += 1
2199 # the first element is the selector and split it up
2200 sel = temp[index]
GlennRC528ad292015-11-12 10:38:18 -08002201 index += 1
You Wang91c37cf2016-05-23 09:39:42 -07002202 sel = sel.split(",")
2203 # the priority is stuck in the selecter so put it back
2204 # in the flow
2205 parsedFlow.append(sel.pop(0))
2206 # parse selector
2207 criteria = []
2208 for item in sel:
2209 # this is the type of the packet e.g. "arp"
2210 if "=" not in item:
2211 criteria.append( {"type":item} )
2212 else:
2213 field = item.split("=")
2214 criteria.append( {field[0]:field[1]} )
2215 selector = {"selector": {"criteria":sorted(criteria)} }
2216 treat = temp[index]
2217 # get rid of the action part e.g. "action=output:2"
2218 # we will add it back later
2219 treat = treat.split("=")
2220 treat.pop(0)
2221 # parse treatment
2222 action = []
2223 for item in treat:
2224 field = item.split(":")
2225 action.append( {field[0]:field[1]} )
2226 # create the treatment field and add the actions
2227 treatment = {"treatment": {"action":sorted(action)} }
2228 # parse the rest of the flow
2229 for item in parsedFlow:
GlennRC528ad292015-11-12 10:38:18 -08002230 field = item.split("=")
You Wang91c37cf2016-05-23 09:39:42 -07002231 jsonFlow.update( {field[0]:field[1]} )
2232 # add the treatment and the selector to the json flow
2233 jsonFlow.update( selector )
2234 jsonFlow.update( treatment )
2235 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002236
You Wang91c37cf2016-05-23 09:39:42 -07002237 if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
GlennRC956ea742015-11-05 16:14:15 -08002238
You Wang91c37cf2016-05-23 09:39:42 -07002239 # add the json flow to the json flow table
2240 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002241
You Wang91c37cf2016-05-23 09:39:42 -07002242 return jsonFlowTable
2243
2244 except IndexError:
2245 main.log.exception( self.name + ": IndexError found" )
2246 return None
2247 except Exception:
2248 main.log.exception( self.name + ": Uncaught exception!" )
2249 main.cleanup()
2250 main.exit()
GlennRC528ad292015-11-12 10:38:18 -08002251
Jon Hall0a543792015-12-14 11:00:26 -08002252 def getFlowTable( self, sw, version="", debug=False):
GlennRC956ea742015-11-05 16:14:15 -08002253 '''
2254 Discription: Returns the flow table(s) on a switch or switches in a list.
2255 Each element is a flow.
2256 Arguments:
2257 Required:
2258 sw: The switch name ("s1") to retrive the flow table. Can also be
2259 a list of switches.
2260 Optional:
2261 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2262 debug: prints out the final result
2263 '''
2264 try:
2265 switches = []
2266 if type(sw) is list:
Jon Hallca7ac292015-11-11 09:28:12 -08002267 switches.extend(sw)
GlennRC956ea742015-11-05 16:14:15 -08002268 else: switches.append(sw)
2269
2270 flows = []
2271 for s in switches:
2272 cmd = "sh ovs-ofctl dump-flows " + s
2273
GlennRC528ad292015-11-12 10:38:18 -08002274 if "1.0" == version:
2275 cmd += " -F OpenFlow10-table_id"
2276 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002277 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002278
2279 main.log.info( "Sending: " + cmd )
2280 self.handle.sendline( cmd )
2281 self.handle.expect( "mininet>" )
2282 response = self.handle.before
2283 response = response.split( "\r\n" )
2284 # dump the first two elements and the last
2285 # the first element is the command that was sent
2286 # the second is the table header
2287 # the last element is empty
2288 response = response[2:-1]
2289 flows.extend( response )
2290
2291 if debug: print "Flows:\n{}\n\n".format(flows)
2292
GlennRC528ad292015-11-12 10:38:18 -08002293 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002294
2295 except pexpect.TIMEOUT:
2296 main.log.exception( self.name + ": Command timed out" )
2297 return None
2298 except pexpect.EOF:
2299 main.log.exception( self.name + ": connection closed." )
2300 main.cleanup()
2301 main.exit()
2302 except Exception:
2303 main.log.exception( self.name + ": Uncaught exception!" )
2304 main.cleanup()
2305 main.exit()
2306
2307 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
2308 '''
2309 Discription: Checks whether the ID provided matches a flow ID in Mininet
2310 Arguments:
2311 Required:
2312 sw: The switch name ("s1") to retrive the flow table. Can also be
2313 a list of switches.
2314 flowId: the flow ID in hex format. Can also be a list of IDs
2315 Optional:
2316 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2317 debug: prints out the final result
2318 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2319 NOTE: prints out IDs that are not present
2320 '''
2321 try:
2322 main.log.info( "Getting flows from Mininet" )
2323 flows = self.getFlowTable( sw, version, debug )
2324
2325 if debug: print "flow ids:\n{}\n\n".format(flowId)
2326
2327 # Check flowId is a list or a string
2328 if type( flowId ) is str:
2329 result = False
2330 for f in flows:
2331 if flowId in f.get( 'cookie' ):
2332 result = True
2333 break
2334 # flowId is a list
2335 else:
2336 result = True
2337 # Get flow IDs from Mininet
2338 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2339 # Save the IDs that are not in Mininet
2340 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2341
2342 if debug: print "mn flow ids:\n{}\n\n".format(mnFlowIds)
2343
2344 # Print out the IDs that are not in Mininet
2345 if absentIds:
2346 main.log.warn( "Absent ids: {}".format( absentIds ) )
2347 result = False
2348
2349 return main.TRUE if result else main.FALSE
2350
2351 except Exception:
2352 main.log.exception( self.name + ": Uncaught exception!" )
2353 main.cleanup()
2354 main.exit()
2355
2356
Charles Chan029be652015-08-24 01:46:10 +08002357 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002358 """
Jon Hallefbd9792015-03-05 16:11:36 -08002359 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002360 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002361 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002362 self.handle.sendline( "" )
2363 self.handle.expect( "mininet>" )
2364 self.handle.sendline(
2365 "sh sudo tcpdump -n -i " +
2366 intf +
2367 " " +
2368 port +
2369 " -w " +
2370 filename.strip() +
2371 " &" )
2372 self.handle.sendline( "" )
2373 i = self.handle.expect( [ 'No\ssuch\device',
2374 'listening\son',
2375 pexpect.TIMEOUT,
2376 "mininet>" ],
2377 timeout=10 )
2378 main.log.warn( self.handle.before + self.handle.after )
2379 self.handle.sendline( "" )
2380 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002381 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002382 main.log.error(
2383 self.name +
2384 ": tcpdump - No such device exists. " +
2385 "tcpdump attempted on: " +
2386 intf )
admin2a9548d2014-06-17 14:08:07 -07002387 return main.FALSE
2388 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002389 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002390 return main.TRUE
2391 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002392 main.log.error(
2393 self.name +
2394 ": tcpdump command timed out! Check interface name," +
2395 " given interface was: " +
2396 intf )
admin2a9548d2014-06-17 14:08:07 -07002397 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002398 elif i == 3:
2399 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002400 return main.TRUE
2401 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002402 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002403 return main.FALSE
2404 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002405 main.log.error( self.name + ": EOF exception found" )
2406 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002407 main.cleanup()
2408 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002409 except Exception:
2410 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002411 main.cleanup()
2412 main.exit()
2413
kelvin-onlabd3b64892015-01-20 13:26:24 -08002414 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002415 """
2416 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002417 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002418 self.handle.sendline( "sh sudo pkill tcpdump" )
2419 self.handle.expect( "mininet>" )
2420 self.handle.sendline( "" )
2421 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002422 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002423 main.log.error( self.name + ": EOF exception found" )
2424 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002425 main.cleanup()
2426 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002427 except Exception:
2428 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002429 main.cleanup()
2430 main.exit()
2431
Jon Halld80cc142015-07-06 13:36:05 -07002432 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002433 """
2434 Read ports from a Mininet switch.
2435
2436 Returns a json structure containing information about the
2437 ports of the given switch.
2438 """
2439 response = self.getInterfaces( nodeName )
2440 # TODO: Sanity check on response. log if no such switch exists
2441 ports = []
2442 for line in response.split( "\n" ):
2443 if not line.startswith( "name=" ):
2444 continue
2445 portVars = {}
2446 for var in line.split( "," ):
2447 key, value = var.split( "=" )
2448 portVars[ key ] = value
2449 isUp = portVars.pop( 'enabled', "True" )
2450 isUp = "True" in isUp
2451 if verbose:
2452 main.log.info( "Reading switch port %s(%s)" %
2453 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2454 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002455 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002456 mac = None
2457 ips = []
2458 ip = portVars[ 'ip' ]
2459 if ip == 'None':
2460 ip = None
2461 ips.append( ip )
2462 name = portVars[ 'name' ]
2463 if name == 'None':
2464 name = None
2465 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2466 if name == 'lo':
2467 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2468 else:
2469 portNo = re.search( portRe, name ).group( 'port' )
2470 ports.append( { 'of_port': portNo,
2471 'mac': str( mac ).replace( '\'', '' ),
2472 'name': name,
2473 'ips': ips,
2474 'enabled': isUp } )
2475 return ports
2476
Jon Halld80cc142015-07-06 13:36:05 -07002477 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002478 """
2479 Read switches from Mininet.
2480
2481 Returns a dictionary whose keys are the switch names and the value is
2482 a dictionary containing information about the switch.
2483 """
Jon Halla22481b2015-07-28 17:46:01 -07002484 # NOTE: To support new Mininet switch classes, just append the new
2485 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002486
Jon Halla22481b2015-07-28 17:46:01 -07002487 # Regex patterns to parse 'dump' output
2488 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002489 # <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 -07002490 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002491 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2492 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2493 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2494 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2495 swRE = r"<(?P<class>" + switchClasses + r")" +\
2496 r"(?P<options>\{.*\})?\s" +\
2497 r"(?P<name>[^:]+)\:\s" +\
2498 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2499 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002500 # Update mn port info
2501 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002502 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002503 dump = self.dump().split( "\n" )
2504 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002505 result = re.search( swRE, line, re.I )
2506 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002507 name = result.group( 'name' )
2508 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002509 pid = result.group( 'pid' )
2510 swClass = result.group( 'class' )
2511 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002512 if verbose:
2513 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2514 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002515 output[ name ] = { "dpid": dpid,
2516 "ports": ports,
2517 "swClass": swClass,
2518 "pid": pid,
2519 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002520 return output
2521
Jon Halld80cc142015-07-06 13:36:05 -07002522 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002523 """
2524 Read hosts from Mininet.
2525
2526 Returns a dictionary whose keys are the host names and the value is
2527 a dictionary containing information about the host.
2528 """
2529 # Regex patterns to parse dump output
2530 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002531 # <Host h1: pid=12725>
2532 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2533 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2534 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002535 # NOTE: Does not correctly match hosts with multi-links
2536 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2537 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002538 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002539 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002540 # update mn port info
2541 self.update()
2542 # Get mininet dump
2543 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002544 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002545 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002546 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002547 result = re.search( hostRE, line )
2548 name = result.group( 'name' )
2549 interfaces = []
2550 response = self.getInterfaces( name )
2551 # Populate interface info
2552 for line in response.split( "\n" ):
2553 if line.startswith( "name=" ):
2554 portVars = {}
2555 for var in line.split( "," ):
2556 key, value = var.split( "=" )
2557 portVars[ key ] = value
2558 isUp = portVars.pop( 'enabled', "True" )
2559 isUp = "True" in isUp
2560 if verbose:
2561 main.log.info( "Reading host port %s(%s)" %
2562 ( portVars[ 'name' ],
2563 portVars[ 'mac' ] ) )
2564 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002565 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002566 mac = None
2567 ips = []
2568 ip = portVars[ 'ip' ]
2569 if ip == 'None':
2570 ip = None
2571 ips.append( ip )
2572 intfName = portVars[ 'name' ]
2573 if name == 'None':
2574 name = None
2575 interfaces.append( {
2576 "name": intfName,
2577 "ips": ips,
2578 "mac": str( mac ),
2579 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002580 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002581 return hosts
2582
YPZhang81a7d4e2016-04-18 13:10:17 -07002583 def getLinks( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002584 """
2585 Gathers information about current Mininet links. These links may not
2586 be up if one of the ports is down.
2587
2588 Returns a list of dictionaries with link endpoints.
2589
2590 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002591 { 'node1': str( node1 name )
2592 'node2': str( node2 name )
2593 'port1': str( port1 of_port )
2594 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002595 Note: The port number returned is the eth#, not necessarily the of_port
2596 number. In Mininet, for OVS switch, these should be the same. For
2597 hosts, this is just the eth#.
2598 """
2599 self.update()
YPZhang81a7d4e2016-04-18 13:10:17 -07002600 response = self.links(timeout=timeout).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002601
2602 # Examples:
2603 # s1-eth3<->s2-eth1 (OK OK)
2604 # s13-eth3<->h27-eth0 (OK OK)
2605 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2606 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2607 links = []
2608 for line in response:
2609 match = re.search( linkRE, line )
2610 if match:
2611 node1 = match.group( 'node1' )
2612 node2 = match.group( 'node2' )
2613 port1 = match.group( 'port1' )
2614 port2 = match.group( 'port2' )
2615 links.append( { 'node1': node1,
2616 'node2': node2,
2617 'port1': port1,
2618 'port2': port2 } )
2619 return links
2620
2621 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002622 """
2623 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002624 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002625
Jon Hallafa8a472015-06-12 14:02:42 -07002626 Dependencies:
2627 1. numpy - "sudo pip install numpy"
2628 """
2629 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002630 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002631 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002632 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002633 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002634 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002635 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002636 main.log.error(
2637 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002638 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002639 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002640 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002641 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002642 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002643 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002644 onosDPIDs.append(
2645 switch[ 'id' ].replace(
2646 ":",
2647 '' ).replace(
2648 "of",
2649 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002650 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002651
Jon Hall7eb38402015-01-08 17:19:54 -08002652 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002653 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002654 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002655 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002656 main.log.error( str( list1 ) )
2657 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002658 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002659 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002660 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002661 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002662 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002663
Jon Hall7eb38402015-01-08 17:19:54 -08002664 # FIXME: this does not look for extra ports in ONOS, only checks that
2665 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002666 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002667
Jon Hall7eb38402015-01-08 17:19:54 -08002668 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002669 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002670 mnPorts = []
2671 onosPorts = []
2672 switchResult = main.TRUE
2673 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002674 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002675 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002676 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002677 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002678 if onosSwitch[ 'device' ][ 'id' ].replace(
2679 ':',
2680 '' ).replace(
2681 "of",
2682 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002683 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002684 if port[ 'isEnabled' ]:
2685 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002686 # onosPorts.append( 'local' )
2687 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002688 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002689 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002690 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002691 mnPorts.sort( key=float )
2692 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002693
kelvin-onlabd3b64892015-01-20 13:26:24 -08002694 mnPortsLog = mnPorts
2695 onosPortsLog = onosPorts
2696 mnPorts = [ x for x in mnPorts ]
2697 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002698
Jon Hall7eb38402015-01-08 17:19:54 -08002699 # TODO: handle other reserved port numbers besides LOCAL
2700 # NOTE: Reserved ports
2701 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2702 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002703 for mnPort in mnPortsLog:
2704 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002705 # don't set results to true here as this is just one of
2706 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002707 mnPorts.remove( mnPort )
2708 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002709
Jon Hall7eb38402015-01-08 17:19:54 -08002710 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002711 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002712 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002713 if 65534 in mnPorts:
2714 mnPorts.remove( 65534 )
2715 if long( uint64( -2 ) ) in onosPorts:
2716 onosPorts.remove( long( uint64( -2 ) ) )
2717 if len( mnPorts ): # the ports of this switch don't match
2718 switchResult = main.FALSE
2719 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2720 if len( onosPorts ): # the ports of this switch don't match
2721 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002722 main.log.warn(
2723 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002724 str( onosPorts ) )
2725 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002726 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002727 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002728 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002729 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2730 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2731 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002732 finalResults = finalResults and portsResults
2733 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002734
Jon Hallafa8a472015-06-12 14:02:42 -07002735 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002736 """
2737 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002738 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002739
Jon Hallafa8a472015-06-12 14:02:42 -07002740 """
Jon Hall7eb38402015-01-08 17:19:54 -08002741 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002742 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002743 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002744
Jon Halld80cc142015-07-06 13:36:05 -07002745 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002746 for l in links:
2747 try:
2748 node1 = switches[ l[ 'node1' ] ]
2749 node2 = switches[ l[ 'node2' ] ]
2750 enabled = True
2751 for port in node1[ 'ports' ]:
2752 if port[ 'of_port' ] == l[ 'port1' ]:
2753 enabled = enabled and port[ 'enabled' ]
2754 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002755 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002756 enabled = enabled and port[ 'enabled' ]
2757 if enabled:
2758 mnLinks.append( l )
2759 except KeyError:
2760 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002761 if 2 * len( mnLinks ) == len( onos ):
2762 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002763 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002764 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002765 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002766 "Mininet has " + str( len( mnLinks ) ) +
2767 " bidirectional links and ONOS has " +
2768 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002769
Jon Hall7eb38402015-01-08 17:19:54 -08002770 # iterate through MN links and check if an ONOS link exists in
2771 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002772 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002773 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002774 node1 = None
2775 port1 = None
2776 node2 = None
2777 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002778 firstDir = main.FALSE
2779 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002780 for swName, switch in switches.iteritems():
2781 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002782 node1 = switch[ 'dpid' ]
2783 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002784 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002785 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002786 if node1 is not None and node2 is not None:
2787 break
Jon Hallafa8a472015-06-12 14:02:42 -07002788 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002789 node2 = switch[ 'dpid' ]
2790 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002791 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002792 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002793 if node1 is not None and node2 is not None:
2794 break
2795
kelvin-onlabd3b64892015-01-20 13:26:24 -08002796 for onosLink in onos:
2797 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002798 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002799 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002800 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002801 onosPort1 = onosLink[ 'src' ][ 'port' ]
2802 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002803
Jon Hall72cf1dc2014-10-20 21:04:50 -04002804 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002805 if str( onosNode1 ) == str( node1 ) and str(
2806 onosNode2 ) == str( node2 ):
2807 if int( onosPort1 ) == int( port1 ) and int(
2808 onosPort2 ) == int( port2 ):
2809 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002810 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002811 main.log.warn(
2812 'The port numbers do not match for ' +
2813 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002814 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002815 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002816 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002817 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002818 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002819
2820 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002821 elif ( str( onosNode1 ) == str( node2 ) and
2822 str( onosNode2 ) == str( node1 ) ):
2823 if ( int( onosPort1 ) == int( port2 )
2824 and int( onosPort2 ) == int( port1 ) ):
2825 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002826 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002827 main.log.warn(
2828 'The port numbers do not match for ' +
2829 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002830 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002831 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002832 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002833 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002834 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002835 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002836 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002837 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002838 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002839 'ONOS does not have the link %s/%s -> %s/%s' %
2840 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002841 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002842 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002843 'ONOS does not have the link %s/%s -> %s/%s' %
2844 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002845 linkResults = linkResults and firstDir and secondDir
2846 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002847
Jon Hallafa8a472015-06-12 14:02:42 -07002848 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002849 """
Jon Hallafa8a472015-06-12 14:02:42 -07002850 Compare mn and onos Hosts.
2851 Since Mininet hosts are quiet, ONOS will only know of them when they
2852 speak. For this reason, we will only check that the hosts in ONOS
2853 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002854
Jon Hallafa8a472015-06-12 14:02:42 -07002855 Arguments:
2856 hostsJson: parsed json object from the onos hosts api
2857 Returns:
2858 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002859 import json
2860 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002861 for onosHost in hostsJson:
2862 onosMAC = onosHost[ 'mac' ].lower()
2863 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002864 for mnHost, info in hosts.iteritems():
2865 for mnIntf in info[ 'interfaces' ]:
2866 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002867 match = True
2868 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002869 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002870 pass # all is well
2871 else:
2872 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002873 main.log.error( "ONOS host " +
2874 onosHost[ 'id' ] +
2875 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002876 str( onosHost[ 'ipAddresses' ] ) +
2877 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002878 str( ip ) +
2879 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002880 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002881 onosHost,
2882 sort_keys=True,
2883 indent=4,
2884 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002885 main.log.info( output )
2886 hostResults = main.FALSE
2887 if not match:
2888 hostResults = main.FALSE
2889 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2890 "corresponding Mininet host." )
2891 output = json.dumps( onosHost,
2892 sort_keys=True,
2893 indent=4,
2894 separators=( ',', ': ' ) )
2895 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002896 return hostResults
2897
Jon Hallafa8a472015-06-12 14:02:42 -07002898 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002899 """
2900 Returns a list of all hosts
2901 Don't ask questions just use it"""
2902 self.handle.sendline( "" )
2903 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002904
Jon Hall7eb38402015-01-08 17:19:54 -08002905 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2906 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002907
kelvin-onlabd3b64892015-01-20 13:26:24 -08002908 handlePy = self.handle.before
2909 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2910 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002911
Jon Hall7eb38402015-01-08 17:19:54 -08002912 self.handle.sendline( "" )
2913 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002914
kelvin-onlabd3b64892015-01-20 13:26:24 -08002915 hostStr = handlePy.replace( "]", "" )
2916 hostStr = hostStr.replace( "'", "" )
2917 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002918 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002919 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002920
kelvin-onlabd3b64892015-01-20 13:26:24 -08002921 return hostList
adminbae64d82013-08-01 10:50:15 -07002922
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002923 def getSwitch( self ):
2924 """
2925 Returns a list of all switches
2926 Again, don't ask question just use it...
2927 """
2928 # get host list...
2929 hostList = self.getHosts()
2930 # Make host set
2931 hostSet = set( hostList )
2932
2933 # Getting all the nodes in mininet
2934 self.handle.sendline( "" )
2935 self.handle.expect( "mininet>" )
2936
2937 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2938 self.handle.expect( "mininet>" )
2939
2940 handlePy = self.handle.before
2941 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2942 handlePy = handlePy.rstrip()
2943
2944 self.handle.sendline( "" )
2945 self.handle.expect( "mininet>" )
2946
2947 nodesStr = handlePy.replace( "]", "" )
2948 nodesStr = nodesStr.replace( "'", "" )
2949 nodesStr = nodesStr.replace( "[", "" )
2950 nodesStr = nodesStr.replace( " ", "" )
2951 nodesList = nodesStr.split( "," )
2952
2953 nodesSet = set( nodesList )
2954 # discarding default controller(s) node
2955 nodesSet.discard( 'c0' )
2956 nodesSet.discard( 'c1' )
2957 nodesSet.discard( 'c2' )
2958
2959 switchSet = nodesSet - hostSet
2960 switchList = list( switchSet )
2961
2962 return switchList
2963
Jon Hall7eb38402015-01-08 17:19:54 -08002964 def update( self ):
2965 """
2966 updates the port address and status information for
2967 each port in mn"""
2968 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002969 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002970 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002971 self.handle.sendline( "" )
2972 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002973
Jon Hall7eb38402015-01-08 17:19:54 -08002974 self.handle.sendline( "update" )
2975 self.handle.expect( "update" )
2976 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002977
Jon Hall7eb38402015-01-08 17:19:54 -08002978 self.handle.sendline( "" )
2979 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002980
Jon Hallb1290e82014-11-18 16:17:48 -05002981 return main.TRUE
2982 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002983 main.log.error( self.name + ": EOF exception found" )
2984 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002985 main.cleanup()
2986 main.exit()
2987
Jon Halld80cc142015-07-06 13:36:05 -07002988 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002989 """
2990 Add vlan tag to a host.
2991 Dependencies:
2992 This class depends on the "vlan" package
2993 $ sudo apt-get install vlan
2994 Configuration:
2995 Load the 8021q module into the kernel
2996 $sudo modprobe 8021q
2997
2998 To make this setup permanent:
2999 $ sudo su -c 'echo "8021q" >> /etc/modules'
3000 """
3001 if self.handle:
3002 try:
Jon Halld80cc142015-07-06 13:36:05 -07003003 # get the ip address of the host
3004 main.log.info( "Get the ip address of the host" )
3005 ipaddr = self.getIPAddress( host )
3006 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003007
Jon Halld80cc142015-07-06 13:36:05 -07003008 # remove IP from interface intf
3009 # Ex: h1 ifconfig h1-eth0 inet 0
3010 main.log.info( "Remove IP from interface " )
3011 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3012 self.handle.sendline( cmd2 )
3013 self.handle.expect( "mininet>" )
3014 response = self.handle.before
3015 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003016
Jon Halld80cc142015-07-06 13:36:05 -07003017 # create VLAN interface
3018 # Ex: h1 vconfig add h1-eth0 100
3019 main.log.info( "Create Vlan" )
3020 cmd3 = host + " vconfig add " + intf + " " + vlan
3021 self.handle.sendline( cmd3 )
3022 self.handle.expect( "mininet>" )
3023 response = self.handle.before
3024 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003025
Jon Halld80cc142015-07-06 13:36:05 -07003026 # assign the host's IP to the VLAN interface
3027 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3028 main.log.info( "Assign the host IP to the vlan interface" )
3029 vintf = intf + "." + vlan
3030 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3031 self.handle.sendline( cmd4 )
3032 self.handle.expect( "mininet>" )
3033 response = self.handle.before
3034 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003035
3036 return main.TRUE
3037 except pexpect.EOF:
3038 main.log.error( self.name + ": EOF exception found" )
3039 main.log.error( self.name + ": " + self.handle.before )
3040 return main.FALSE
3041
Jon Hall892818c2015-10-20 17:58:34 -07003042 def createHostComponent( self, name ):
3043 """
3044 Creates a new mininet cli component with the same parameters as self.
3045 This new component is intended to be used to login to the hosts created
3046 by mininet.
3047
3048 Arguments:
3049 name - The string of the name of this component. The new component
3050 will be assigned to main.<name> .
3051 In addition, main.<name>.name = str( name )
3052 """
3053 try:
3054 # look to see if this component already exists
3055 getattr( main, name )
3056 except AttributeError:
3057 # namespace is clear, creating component
3058 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
3059 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
3060 main.componentInit( name )
3061 except Exception:
3062 main.log.exception( self.name + ": Uncaught exception!" )
3063 main.cleanup()
3064 main.exit()
3065 else:
3066 # namespace is not clear!
3067 main.log.error( name + " component already exists!" )
3068 # FIXME: Should we exit here?
3069 main.cleanup()
3070 main.exit()
3071
3072 def removeHostComponent( self, name ):
3073 """
3074 Remove host component
3075 Arguments:
3076 name - The string of the name of the component to delete.
3077 """
3078 try:
3079 # Get host component
3080 component = getattr( main, name )
3081 except AttributeError:
3082 main.log.error( "Component " + name + " does not exist." )
3083 return
3084 try:
3085 # Disconnect from component
3086 component.disconnect()
3087 # Delete component
3088 delattr( main, name )
3089 # Delete component from ComponentDictionary
3090 del( main.componentDictionary[name] )
3091 except Exception:
3092 main.log.exception( self.name + ": Uncaught exception!" )
3093 main.cleanup()
3094 main.exit()
3095
3096 def startHostCli( self, host=None ):
3097 """
3098 Use the mininet m utility to connect to the host's cli
3099 """
3100 # These are fields that can be used by scapy packets. Initialized to None
3101 self.hostIp = None
3102 self.hostMac = None
3103 try:
3104 if not host:
3105 host = self.name
3106 self.handle.sendline( self.home + "/util/m " + host )
3107 self.handle.expect( self.hostPrompt )
3108 return main.TRUE
3109 except pexpect.TIMEOUT:
3110 main.log.exception( self.name + ": Command timed out" )
3111 return main.FALSE
3112 except pexpect.EOF:
3113 main.log.exception( self.name + ": connection closed." )
3114 main.cleanup()
3115 main.exit()
3116 except Exception:
3117 main.log.exception( self.name + ": Uncaught exception!" )
3118 main.cleanup()
3119 main.exit()
3120
Jon Hall892818c2015-10-20 17:58:34 -07003121
adminbae64d82013-08-01 10:50:15 -07003122if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003123 sys.modules[ __name__ ] = MininetCliDriver()