blob: b38e257a72d33d0ec2d2d9e0c770b82ae088a919 [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 )
You Wang083ae982016-05-25 09:31:09 -07002324 if flows == None:
2325 return main.ERROR
GlennRC956ea742015-11-05 16:14:15 -08002326
2327 if debug: print "flow ids:\n{}\n\n".format(flowId)
2328
2329 # Check flowId is a list or a string
2330 if type( flowId ) is str:
2331 result = False
2332 for f in flows:
2333 if flowId in f.get( 'cookie' ):
2334 result = True
2335 break
2336 # flowId is a list
2337 else:
2338 result = True
2339 # Get flow IDs from Mininet
2340 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2341 # Save the IDs that are not in Mininet
2342 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2343
2344 if debug: print "mn flow ids:\n{}\n\n".format(mnFlowIds)
2345
2346 # Print out the IDs that are not in Mininet
2347 if absentIds:
2348 main.log.warn( "Absent ids: {}".format( absentIds ) )
2349 result = False
2350
2351 return main.TRUE if result else main.FALSE
2352
2353 except Exception:
2354 main.log.exception( self.name + ": Uncaught exception!" )
2355 main.cleanup()
2356 main.exit()
2357
2358
Charles Chan029be652015-08-24 01:46:10 +08002359 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002360 """
Jon Hallefbd9792015-03-05 16:11:36 -08002361 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002362 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002363 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002364 self.handle.sendline( "" )
2365 self.handle.expect( "mininet>" )
2366 self.handle.sendline(
2367 "sh sudo tcpdump -n -i " +
2368 intf +
2369 " " +
2370 port +
2371 " -w " +
2372 filename.strip() +
2373 " &" )
2374 self.handle.sendline( "" )
2375 i = self.handle.expect( [ 'No\ssuch\device',
2376 'listening\son',
2377 pexpect.TIMEOUT,
2378 "mininet>" ],
2379 timeout=10 )
2380 main.log.warn( self.handle.before + self.handle.after )
2381 self.handle.sendline( "" )
2382 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002383 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002384 main.log.error(
2385 self.name +
2386 ": tcpdump - No such device exists. " +
2387 "tcpdump attempted on: " +
2388 intf )
admin2a9548d2014-06-17 14:08:07 -07002389 return main.FALSE
2390 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002391 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002392 return main.TRUE
2393 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002394 main.log.error(
2395 self.name +
2396 ": tcpdump command timed out! Check interface name," +
2397 " given interface was: " +
2398 intf )
admin2a9548d2014-06-17 14:08:07 -07002399 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002400 elif i == 3:
2401 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002402 return main.TRUE
2403 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002404 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002405 return main.FALSE
2406 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002407 main.log.error( self.name + ": EOF exception found" )
2408 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002409 main.cleanup()
2410 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002411 except Exception:
2412 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002413 main.cleanup()
2414 main.exit()
2415
kelvin-onlabd3b64892015-01-20 13:26:24 -08002416 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002417 """
2418 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002419 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002420 self.handle.sendline( "sh sudo pkill tcpdump" )
2421 self.handle.expect( "mininet>" )
2422 self.handle.sendline( "" )
2423 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002424 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002425 main.log.error( self.name + ": EOF exception found" )
2426 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002427 main.cleanup()
2428 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002429 except Exception:
2430 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002431 main.cleanup()
2432 main.exit()
2433
Jon Halld80cc142015-07-06 13:36:05 -07002434 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002435 """
2436 Read ports from a Mininet switch.
2437
2438 Returns a json structure containing information about the
2439 ports of the given switch.
2440 """
2441 response = self.getInterfaces( nodeName )
2442 # TODO: Sanity check on response. log if no such switch exists
2443 ports = []
2444 for line in response.split( "\n" ):
2445 if not line.startswith( "name=" ):
2446 continue
2447 portVars = {}
2448 for var in line.split( "," ):
2449 key, value = var.split( "=" )
2450 portVars[ key ] = value
2451 isUp = portVars.pop( 'enabled', "True" )
2452 isUp = "True" in isUp
2453 if verbose:
2454 main.log.info( "Reading switch port %s(%s)" %
2455 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2456 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002457 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002458 mac = None
2459 ips = []
2460 ip = portVars[ 'ip' ]
2461 if ip == 'None':
2462 ip = None
2463 ips.append( ip )
2464 name = portVars[ 'name' ]
2465 if name == 'None':
2466 name = None
2467 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2468 if name == 'lo':
2469 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2470 else:
2471 portNo = re.search( portRe, name ).group( 'port' )
2472 ports.append( { 'of_port': portNo,
2473 'mac': str( mac ).replace( '\'', '' ),
2474 'name': name,
2475 'ips': ips,
2476 'enabled': isUp } )
2477 return ports
2478
Jon Halld80cc142015-07-06 13:36:05 -07002479 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002480 """
2481 Read switches from Mininet.
2482
2483 Returns a dictionary whose keys are the switch names and the value is
2484 a dictionary containing information about the switch.
2485 """
Jon Halla22481b2015-07-28 17:46:01 -07002486 # NOTE: To support new Mininet switch classes, just append the new
2487 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002488
Jon Halla22481b2015-07-28 17:46:01 -07002489 # Regex patterns to parse 'dump' output
2490 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002491 # <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 -07002492 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002493 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2494 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2495 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2496 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2497 swRE = r"<(?P<class>" + switchClasses + r")" +\
2498 r"(?P<options>\{.*\})?\s" +\
2499 r"(?P<name>[^:]+)\:\s" +\
2500 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2501 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002502 # Update mn port info
2503 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002504 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002505 dump = self.dump().split( "\n" )
2506 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002507 result = re.search( swRE, line, re.I )
2508 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002509 name = result.group( 'name' )
2510 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002511 pid = result.group( 'pid' )
2512 swClass = result.group( 'class' )
2513 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002514 if verbose:
2515 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2516 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002517 output[ name ] = { "dpid": dpid,
2518 "ports": ports,
2519 "swClass": swClass,
2520 "pid": pid,
2521 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002522 return output
2523
Jon Halld80cc142015-07-06 13:36:05 -07002524 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002525 """
2526 Read hosts from Mininet.
2527
2528 Returns a dictionary whose keys are the host names and the value is
2529 a dictionary containing information about the host.
2530 """
2531 # Regex patterns to parse dump output
2532 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002533 # <Host h1: pid=12725>
2534 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2535 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2536 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002537 # NOTE: Does not correctly match hosts with multi-links
2538 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2539 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002540 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002541 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002542 # update mn port info
2543 self.update()
2544 # Get mininet dump
2545 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002546 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002547 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002548 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002549 result = re.search( hostRE, line )
2550 name = result.group( 'name' )
2551 interfaces = []
2552 response = self.getInterfaces( name )
2553 # Populate interface info
2554 for line in response.split( "\n" ):
2555 if line.startswith( "name=" ):
2556 portVars = {}
2557 for var in line.split( "," ):
2558 key, value = var.split( "=" )
2559 portVars[ key ] = value
2560 isUp = portVars.pop( 'enabled', "True" )
2561 isUp = "True" in isUp
2562 if verbose:
2563 main.log.info( "Reading host port %s(%s)" %
2564 ( portVars[ 'name' ],
2565 portVars[ 'mac' ] ) )
2566 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002567 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002568 mac = None
2569 ips = []
2570 ip = portVars[ 'ip' ]
2571 if ip == 'None':
2572 ip = None
2573 ips.append( ip )
2574 intfName = portVars[ 'name' ]
2575 if name == 'None':
2576 name = None
2577 interfaces.append( {
2578 "name": intfName,
2579 "ips": ips,
2580 "mac": str( mac ),
2581 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002582 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002583 return hosts
2584
YPZhang81a7d4e2016-04-18 13:10:17 -07002585 def getLinks( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002586 """
2587 Gathers information about current Mininet links. These links may not
2588 be up if one of the ports is down.
2589
2590 Returns a list of dictionaries with link endpoints.
2591
2592 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002593 { 'node1': str( node1 name )
2594 'node2': str( node2 name )
2595 'port1': str( port1 of_port )
2596 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002597 Note: The port number returned is the eth#, not necessarily the of_port
2598 number. In Mininet, for OVS switch, these should be the same. For
2599 hosts, this is just the eth#.
2600 """
2601 self.update()
YPZhang81a7d4e2016-04-18 13:10:17 -07002602 response = self.links(timeout=timeout).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002603
2604 # Examples:
2605 # s1-eth3<->s2-eth1 (OK OK)
2606 # s13-eth3<->h27-eth0 (OK OK)
2607 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2608 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2609 links = []
2610 for line in response:
2611 match = re.search( linkRE, line )
2612 if match:
2613 node1 = match.group( 'node1' )
2614 node2 = match.group( 'node2' )
2615 port1 = match.group( 'port1' )
2616 port2 = match.group( 'port2' )
2617 links.append( { 'node1': node1,
2618 'node2': node2,
2619 'port1': port1,
2620 'port2': port2 } )
2621 return links
2622
2623 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002624 """
2625 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002626 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002627
Jon Hallafa8a472015-06-12 14:02:42 -07002628 Dependencies:
2629 1. numpy - "sudo pip install numpy"
2630 """
2631 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002632 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002633 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002634 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002635 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002636 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002637 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002638 main.log.error(
2639 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002640 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002641 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002642 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002643 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002644 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002645 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002646 onosDPIDs.append(
2647 switch[ 'id' ].replace(
2648 ":",
2649 '' ).replace(
2650 "of",
2651 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002652 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002653
Jon Hall7eb38402015-01-08 17:19:54 -08002654 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002655 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002656 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002657 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002658 main.log.error( str( list1 ) )
2659 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002660 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002661 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002662 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002663 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002664 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002665
Jon Hall7eb38402015-01-08 17:19:54 -08002666 # FIXME: this does not look for extra ports in ONOS, only checks that
2667 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002668 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002669
Jon Hall7eb38402015-01-08 17:19:54 -08002670 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002671 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002672 mnPorts = []
2673 onosPorts = []
2674 switchResult = main.TRUE
2675 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002676 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002677 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002678 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002679 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002680 if onosSwitch[ 'device' ][ 'id' ].replace(
2681 ':',
2682 '' ).replace(
2683 "of",
2684 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002685 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002686 if port[ 'isEnabled' ]:
2687 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002688 # onosPorts.append( 'local' )
2689 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002690 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002691 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002692 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002693 mnPorts.sort( key=float )
2694 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002695
kelvin-onlabd3b64892015-01-20 13:26:24 -08002696 mnPortsLog = mnPorts
2697 onosPortsLog = onosPorts
2698 mnPorts = [ x for x in mnPorts ]
2699 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002700
Jon Hall7eb38402015-01-08 17:19:54 -08002701 # TODO: handle other reserved port numbers besides LOCAL
2702 # NOTE: Reserved ports
2703 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2704 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002705 for mnPort in mnPortsLog:
2706 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002707 # don't set results to true here as this is just one of
2708 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002709 mnPorts.remove( mnPort )
2710 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002711
Jon Hall7eb38402015-01-08 17:19:54 -08002712 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002713 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002714 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002715 if 65534 in mnPorts:
2716 mnPorts.remove( 65534 )
2717 if long( uint64( -2 ) ) in onosPorts:
2718 onosPorts.remove( long( uint64( -2 ) ) )
2719 if len( mnPorts ): # the ports of this switch don't match
2720 switchResult = main.FALSE
2721 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2722 if len( onosPorts ): # the ports of this switch don't match
2723 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002724 main.log.warn(
2725 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002726 str( onosPorts ) )
2727 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002728 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002729 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002730 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002731 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2732 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2733 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002734 finalResults = finalResults and portsResults
2735 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002736
Jon Hallafa8a472015-06-12 14:02:42 -07002737 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002738 """
2739 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002740 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002741
Jon Hallafa8a472015-06-12 14:02:42 -07002742 """
Jon Hall7eb38402015-01-08 17:19:54 -08002743 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002744 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002745 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002746
Jon Halld80cc142015-07-06 13:36:05 -07002747 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002748 for l in links:
2749 try:
2750 node1 = switches[ l[ 'node1' ] ]
2751 node2 = switches[ l[ 'node2' ] ]
2752 enabled = True
2753 for port in node1[ 'ports' ]:
2754 if port[ 'of_port' ] == l[ 'port1' ]:
2755 enabled = enabled and port[ 'enabled' ]
2756 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002757 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002758 enabled = enabled and port[ 'enabled' ]
2759 if enabled:
2760 mnLinks.append( l )
2761 except KeyError:
2762 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002763 if 2 * len( mnLinks ) == len( onos ):
2764 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002765 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002766 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002767 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002768 "Mininet has " + str( len( mnLinks ) ) +
2769 " bidirectional links and ONOS has " +
2770 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002771
Jon Hall7eb38402015-01-08 17:19:54 -08002772 # iterate through MN links and check if an ONOS link exists in
2773 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002774 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002775 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002776 node1 = None
2777 port1 = None
2778 node2 = None
2779 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002780 firstDir = main.FALSE
2781 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002782 for swName, switch in switches.iteritems():
2783 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002784 node1 = switch[ 'dpid' ]
2785 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002786 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002787 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002788 if node1 is not None and node2 is not None:
2789 break
Jon Hallafa8a472015-06-12 14:02:42 -07002790 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002791 node2 = switch[ 'dpid' ]
2792 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002793 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002794 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002795 if node1 is not None and node2 is not None:
2796 break
2797
kelvin-onlabd3b64892015-01-20 13:26:24 -08002798 for onosLink in onos:
2799 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002800 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002801 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002802 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002803 onosPort1 = onosLink[ 'src' ][ 'port' ]
2804 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002805
Jon Hall72cf1dc2014-10-20 21:04:50 -04002806 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002807 if str( onosNode1 ) == str( node1 ) and str(
2808 onosNode2 ) == str( node2 ):
2809 if int( onosPort1 ) == int( port1 ) and int(
2810 onosPort2 ) == int( port2 ):
2811 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002812 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002813 main.log.warn(
2814 'The port numbers do not match for ' +
2815 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002816 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002817 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002818 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002819 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002820 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002821
2822 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002823 elif ( str( onosNode1 ) == str( node2 ) and
2824 str( onosNode2 ) == str( node1 ) ):
2825 if ( int( onosPort1 ) == int( port2 )
2826 and int( onosPort2 ) == int( port1 ) ):
2827 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002828 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002829 main.log.warn(
2830 'The port numbers do not match for ' +
2831 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002832 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002833 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002834 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002835 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002836 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002837 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002838 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002839 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002840 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002841 'ONOS does not have the link %s/%s -> %s/%s' %
2842 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002843 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002844 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002845 'ONOS does not have the link %s/%s -> %s/%s' %
2846 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002847 linkResults = linkResults and firstDir and secondDir
2848 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002849
Jon Hallafa8a472015-06-12 14:02:42 -07002850 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002851 """
Jon Hallafa8a472015-06-12 14:02:42 -07002852 Compare mn and onos Hosts.
2853 Since Mininet hosts are quiet, ONOS will only know of them when they
2854 speak. For this reason, we will only check that the hosts in ONOS
2855 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002856
Jon Hallafa8a472015-06-12 14:02:42 -07002857 Arguments:
2858 hostsJson: parsed json object from the onos hosts api
2859 Returns:
2860 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002861 import json
2862 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002863 for onosHost in hostsJson:
2864 onosMAC = onosHost[ 'mac' ].lower()
2865 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002866 for mnHost, info in hosts.iteritems():
2867 for mnIntf in info[ 'interfaces' ]:
2868 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002869 match = True
2870 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002871 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002872 pass # all is well
2873 else:
2874 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002875 main.log.error( "ONOS host " +
2876 onosHost[ 'id' ] +
2877 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002878 str( onosHost[ 'ipAddresses' ] ) +
2879 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002880 str( ip ) +
2881 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002882 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002883 onosHost,
2884 sort_keys=True,
2885 indent=4,
2886 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002887 main.log.info( output )
2888 hostResults = main.FALSE
2889 if not match:
2890 hostResults = main.FALSE
2891 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2892 "corresponding Mininet host." )
2893 output = json.dumps( onosHost,
2894 sort_keys=True,
2895 indent=4,
2896 separators=( ',', ': ' ) )
2897 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002898 return hostResults
2899
Jon Hallafa8a472015-06-12 14:02:42 -07002900 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002901 """
2902 Returns a list of all hosts
2903 Don't ask questions just use it"""
2904 self.handle.sendline( "" )
2905 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002906
Jon Hall7eb38402015-01-08 17:19:54 -08002907 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2908 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002909
kelvin-onlabd3b64892015-01-20 13:26:24 -08002910 handlePy = self.handle.before
2911 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2912 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002913
Jon Hall7eb38402015-01-08 17:19:54 -08002914 self.handle.sendline( "" )
2915 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002916
kelvin-onlabd3b64892015-01-20 13:26:24 -08002917 hostStr = handlePy.replace( "]", "" )
2918 hostStr = hostStr.replace( "'", "" )
2919 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002920 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002921 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002922
kelvin-onlabd3b64892015-01-20 13:26:24 -08002923 return hostList
adminbae64d82013-08-01 10:50:15 -07002924
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002925 def getSwitch( self ):
2926 """
2927 Returns a list of all switches
2928 Again, don't ask question just use it...
2929 """
2930 # get host list...
2931 hostList = self.getHosts()
2932 # Make host set
2933 hostSet = set( hostList )
2934
2935 # Getting all the nodes in mininet
2936 self.handle.sendline( "" )
2937 self.handle.expect( "mininet>" )
2938
2939 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2940 self.handle.expect( "mininet>" )
2941
2942 handlePy = self.handle.before
2943 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2944 handlePy = handlePy.rstrip()
2945
2946 self.handle.sendline( "" )
2947 self.handle.expect( "mininet>" )
2948
2949 nodesStr = handlePy.replace( "]", "" )
2950 nodesStr = nodesStr.replace( "'", "" )
2951 nodesStr = nodesStr.replace( "[", "" )
2952 nodesStr = nodesStr.replace( " ", "" )
2953 nodesList = nodesStr.split( "," )
2954
2955 nodesSet = set( nodesList )
2956 # discarding default controller(s) node
2957 nodesSet.discard( 'c0' )
2958 nodesSet.discard( 'c1' )
2959 nodesSet.discard( 'c2' )
2960
2961 switchSet = nodesSet - hostSet
2962 switchList = list( switchSet )
2963
2964 return switchList
2965
Jon Hall7eb38402015-01-08 17:19:54 -08002966 def update( self ):
2967 """
2968 updates the port address and status information for
2969 each port in mn"""
2970 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002971 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002972 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002973 self.handle.sendline( "" )
2974 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002975
Jon Hall7eb38402015-01-08 17:19:54 -08002976 self.handle.sendline( "update" )
2977 self.handle.expect( "update" )
2978 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002979
Jon Hall7eb38402015-01-08 17:19:54 -08002980 self.handle.sendline( "" )
2981 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002982
Jon Hallb1290e82014-11-18 16:17:48 -05002983 return main.TRUE
2984 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002985 main.log.error( self.name + ": EOF exception found" )
2986 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002987 main.cleanup()
2988 main.exit()
2989
Jon Halld80cc142015-07-06 13:36:05 -07002990 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002991 """
2992 Add vlan tag to a host.
2993 Dependencies:
2994 This class depends on the "vlan" package
2995 $ sudo apt-get install vlan
2996 Configuration:
2997 Load the 8021q module into the kernel
2998 $sudo modprobe 8021q
2999
3000 To make this setup permanent:
3001 $ sudo su -c 'echo "8021q" >> /etc/modules'
3002 """
3003 if self.handle:
3004 try:
Jon Halld80cc142015-07-06 13:36:05 -07003005 # get the ip address of the host
3006 main.log.info( "Get the ip address of the host" )
3007 ipaddr = self.getIPAddress( host )
3008 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07003009
Jon Halld80cc142015-07-06 13:36:05 -07003010 # remove IP from interface intf
3011 # Ex: h1 ifconfig h1-eth0 inet 0
3012 main.log.info( "Remove IP from interface " )
3013 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
3014 self.handle.sendline( cmd2 )
3015 self.handle.expect( "mininet>" )
3016 response = self.handle.before
3017 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003018
Jon Halld80cc142015-07-06 13:36:05 -07003019 # create VLAN interface
3020 # Ex: h1 vconfig add h1-eth0 100
3021 main.log.info( "Create Vlan" )
3022 cmd3 = host + " vconfig add " + intf + " " + vlan
3023 self.handle.sendline( cmd3 )
3024 self.handle.expect( "mininet>" )
3025 response = self.handle.before
3026 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003027
Jon Halld80cc142015-07-06 13:36:05 -07003028 # assign the host's IP to the VLAN interface
3029 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3030 main.log.info( "Assign the host IP to the vlan interface" )
3031 vintf = intf + "." + vlan
3032 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3033 self.handle.sendline( cmd4 )
3034 self.handle.expect( "mininet>" )
3035 response = self.handle.before
3036 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003037
3038 return main.TRUE
3039 except pexpect.EOF:
3040 main.log.error( self.name + ": EOF exception found" )
3041 main.log.error( self.name + ": " + self.handle.before )
3042 return main.FALSE
3043
Jon Hall892818c2015-10-20 17:58:34 -07003044 def createHostComponent( self, name ):
3045 """
3046 Creates a new mininet cli component with the same parameters as self.
3047 This new component is intended to be used to login to the hosts created
3048 by mininet.
3049
3050 Arguments:
3051 name - The string of the name of this component. The new component
3052 will be assigned to main.<name> .
3053 In addition, main.<name>.name = str( name )
3054 """
3055 try:
3056 # look to see if this component already exists
3057 getattr( main, name )
3058 except AttributeError:
3059 # namespace is clear, creating component
3060 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
3061 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
3062 main.componentInit( name )
3063 except Exception:
3064 main.log.exception( self.name + ": Uncaught exception!" )
3065 main.cleanup()
3066 main.exit()
3067 else:
3068 # namespace is not clear!
3069 main.log.error( name + " component already exists!" )
3070 # FIXME: Should we exit here?
3071 main.cleanup()
3072 main.exit()
3073
3074 def removeHostComponent( self, name ):
3075 """
3076 Remove host component
3077 Arguments:
3078 name - The string of the name of the component to delete.
3079 """
3080 try:
3081 # Get host component
3082 component = getattr( main, name )
3083 except AttributeError:
3084 main.log.error( "Component " + name + " does not exist." )
3085 return
3086 try:
3087 # Disconnect from component
3088 component.disconnect()
3089 # Delete component
3090 delattr( main, name )
3091 # Delete component from ComponentDictionary
3092 del( main.componentDictionary[name] )
3093 except Exception:
3094 main.log.exception( self.name + ": Uncaught exception!" )
3095 main.cleanup()
3096 main.exit()
3097
3098 def startHostCli( self, host=None ):
3099 """
3100 Use the mininet m utility to connect to the host's cli
3101 """
3102 # These are fields that can be used by scapy packets. Initialized to None
3103 self.hostIp = None
3104 self.hostMac = None
3105 try:
3106 if not host:
3107 host = self.name
3108 self.handle.sendline( self.home + "/util/m " + host )
3109 self.handle.expect( self.hostPrompt )
3110 return main.TRUE
3111 except pexpect.TIMEOUT:
3112 main.log.exception( self.name + ": Command timed out" )
3113 return main.FALSE
3114 except pexpect.EOF:
3115 main.log.exception( self.name + ": connection closed." )
3116 main.cleanup()
3117 main.exit()
3118 except Exception:
3119 main.log.exception( self.name + ": Uncaught exception!" )
3120 main.cleanup()
3121 main.exit()
3122
Jon Hall892818c2015-10-20 17:58:34 -07003123
adminbae64d82013-08-01 10:50:15 -07003124if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003125 sys.modules[ __name__ ] = MininetCliDriver()