blob: b6fbded3d2708cbf91951402d2f9a8c0a73fb3dd [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 Hall41d39f12016-04-11 22:54:35 -07002132 returnValue = main.TRUE
GlennRC68467eb2015-11-16 18:01:01 -08002133 if len(flowTable1) != len(flowTable2):
2134 main.log.warn( "Flow table lengths do not match" )
Jon Hall41d39f12016-04-11 22:54:35 -07002135 returnValue = main.FALSE
GlennRCfa65fce2015-12-16 13:16:08 -08002136 dFields = ["n_bytes", "cookie", "n_packets", "duration"]
2137 for flow1, flow2 in zip(flowTable1, flowTable2):
Jon Hallacd1b182015-12-17 11:43:20 -08002138 for field in dFields:
2139 try:
2140 flow1.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002141 except KeyError:
2142 pass
Jon Hallacd1b182015-12-17 11:43:20 -08002143 try:
2144 flow2.pop( field )
Jon Hall41d39f12016-04-11 22:54:35 -07002145 except KeyError:
2146 pass
GlennRC68467eb2015-11-16 18:01:01 -08002147 for i in range( len(flowTable1) ):
GlennRC17bbcf52015-12-14 17:31:50 -08002148 if flowTable1[i] not in flowTable2:
2149 main.log.warn( "Flow tables do not match:" )
2150 main.log.warn( "Old flow:\n{}\n not in new flow table".format( flowTable1[i] ) )
Jon Hall41d39f12016-04-11 22:54:35 -07002151 returnValue = main.FALSE
2152 break
2153 return returnValue
GlennRC68467eb2015-11-16 18:01:01 -08002154 except Exception:
2155 main.log.exception( "Uncaught exception!" )
2156 main.cleanup()
2157 main.exit()
Jon Hall9043c902015-07-30 14:23:44 -07002158
GlennRC528ad292015-11-12 10:38:18 -08002159 def parseFlowTable( self, flowTable, version="", debug=True ):
GlennRC956ea742015-11-05 16:14:15 -08002160 '''
2161 Discription: Parses flows into json format.
2162 NOTE: this can parse any string thats separated with commas
2163 Arguments:
2164 Required:
2165 flows: a list of strings that represnt flows
2166 Optional:
2167 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2168 debug: prints out the final result
2169 returns: A list of flows in json format
2170 '''
GlennRC528ad292015-11-12 10:38:18 -08002171 jsonFlowTable = []
2172 for flow in flowTable:
GlennRC956ea742015-11-05 16:14:15 -08002173 jsonFlow = {}
GlennRC528ad292015-11-12 10:38:18 -08002174 # split up the fields of the flow
2175 parsedFlow = flow.split(", ")
2176 # get rid of any spaces in front of the field
2177 for i in range( len(parsedFlow) ):
2178 item = parsedFlow[i]
2179 if item[0] == " ":
2180 parsedFlow[i] = item[1:]
2181 # grab the selector and treatment from the parsed flow
2182 # the last element is the selector and the treatment
2183 temp = parsedFlow.pop(-1)
2184 # split up the selector and the treatment
2185 temp = temp.split(" ")
2186 index = 0
2187 # parse the flags
2188 # NOTE: This only parses one flag
2189 flag = {}
2190 if version == "1.3":
2191 flag = {"flag":[temp[index]]}
2192 index += 1
2193 # the first element is the selector and split it up
2194 sel = temp[index]
2195 index += 1
2196 sel = sel.split(",")
2197 # the priority is stuck in the selecter so put it back
2198 # in the flow
2199 parsedFlow.append(sel.pop(0))
2200 # parse selector
2201 criteria = []
2202 for item in sel:
2203 # this is the type of the packet e.g. "arp"
2204 if "=" not in item:
2205 criteria.append( {"type":item} )
2206 else:
2207 field = item.split("=")
2208 criteria.append( {field[0]:field[1]} )
GlennRC68467eb2015-11-16 18:01:01 -08002209 selector = {"selector": {"criteria":sorted(criteria)} }
GlennRC528ad292015-11-12 10:38:18 -08002210 treat = temp[index]
2211 # get rid of the action part e.g. "action=output:2"
2212 # we will add it back later
2213 treat = treat.split("=")
2214 treat.pop(0)
2215 # parse treatment
2216 action = []
2217 for item in treat:
2218 field = item.split(":")
2219 action.append( {field[0]:field[1]} )
2220 # create the treatment field and add the actions
GlennRC68467eb2015-11-16 18:01:01 -08002221 treatment = {"treatment": {"action":sorted(action)} }
GlennRC528ad292015-11-12 10:38:18 -08002222 # parse the rest of the flow
2223 for item in parsedFlow:
2224 field = item.split("=")
2225 jsonFlow.update( {field[0]:field[1]} )
2226 # add the treatment and the selector to the json flow
2227 jsonFlow.update( selector )
2228 jsonFlow.update( treatment )
2229 jsonFlow.update( flag )
GlennRC956ea742015-11-05 16:14:15 -08002230
GlennRC528ad292015-11-12 10:38:18 -08002231 if debug: main.log.debug( "\033[94mJson flow:\033[0m\n{}\n".format(jsonFlow) )
GlennRC956ea742015-11-05 16:14:15 -08002232
GlennRC528ad292015-11-12 10:38:18 -08002233 # add the json flow to the json flow table
2234 jsonFlowTable.append( jsonFlow )
GlennRC956ea742015-11-05 16:14:15 -08002235
GlennRC528ad292015-11-12 10:38:18 -08002236 return jsonFlowTable
2237
Jon Hall0a543792015-12-14 11:00:26 -08002238 def getFlowTable( self, sw, version="", debug=False):
GlennRC956ea742015-11-05 16:14:15 -08002239 '''
2240 Discription: Returns the flow table(s) on a switch or switches in a list.
2241 Each element is a flow.
2242 Arguments:
2243 Required:
2244 sw: The switch name ("s1") to retrive the flow table. Can also be
2245 a list of switches.
2246 Optional:
2247 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2248 debug: prints out the final result
2249 '''
2250 try:
2251 switches = []
2252 if type(sw) is list:
Jon Hallca7ac292015-11-11 09:28:12 -08002253 switches.extend(sw)
GlennRC956ea742015-11-05 16:14:15 -08002254 else: switches.append(sw)
2255
2256 flows = []
2257 for s in switches:
2258 cmd = "sh ovs-ofctl dump-flows " + s
2259
GlennRC528ad292015-11-12 10:38:18 -08002260 if "1.0" == version:
2261 cmd += " -F OpenFlow10-table_id"
2262 elif "1.3" == version:
GlennRC956ea742015-11-05 16:14:15 -08002263 cmd += " -O OpenFlow13"
GlennRC956ea742015-11-05 16:14:15 -08002264
2265 main.log.info( "Sending: " + cmd )
2266 self.handle.sendline( cmd )
2267 self.handle.expect( "mininet>" )
2268 response = self.handle.before
2269 response = response.split( "\r\n" )
2270 # dump the first two elements and the last
2271 # the first element is the command that was sent
2272 # the second is the table header
2273 # the last element is empty
2274 response = response[2:-1]
2275 flows.extend( response )
2276
2277 if debug: print "Flows:\n{}\n\n".format(flows)
2278
GlennRC528ad292015-11-12 10:38:18 -08002279 return self.parseFlowTable( flows, version, debug )
GlennRC956ea742015-11-05 16:14:15 -08002280
2281 except pexpect.TIMEOUT:
2282 main.log.exception( self.name + ": Command timed out" )
2283 return None
2284 except pexpect.EOF:
2285 main.log.exception( self.name + ": connection closed." )
2286 main.cleanup()
2287 main.exit()
2288 except Exception:
2289 main.log.exception( self.name + ": Uncaught exception!" )
2290 main.cleanup()
2291 main.exit()
2292
2293 def checkFlowId( self, sw, flowId, version="1.3", debug=True ):
2294 '''
2295 Discription: Checks whether the ID provided matches a flow ID in Mininet
2296 Arguments:
2297 Required:
2298 sw: The switch name ("s1") to retrive the flow table. Can also be
2299 a list of switches.
2300 flowId: the flow ID in hex format. Can also be a list of IDs
2301 Optional:
2302 version: The version of OpenFlow. Currently, 1.3 and 1.0 are supported.
2303 debug: prints out the final result
2304 returns: main.TRUE if all IDs are present, otherwise returns main.FALSE
2305 NOTE: prints out IDs that are not present
2306 '''
2307 try:
2308 main.log.info( "Getting flows from Mininet" )
2309 flows = self.getFlowTable( sw, version, debug )
2310
2311 if debug: print "flow ids:\n{}\n\n".format(flowId)
2312
2313 # Check flowId is a list or a string
2314 if type( flowId ) is str:
2315 result = False
2316 for f in flows:
2317 if flowId in f.get( 'cookie' ):
2318 result = True
2319 break
2320 # flowId is a list
2321 else:
2322 result = True
2323 # Get flow IDs from Mininet
2324 mnFlowIds = [ f.get( 'cookie' ) for f in flows ]
2325 # Save the IDs that are not in Mininet
2326 absentIds = [ x for x in flowId if x not in mnFlowIds ]
2327
2328 if debug: print "mn flow ids:\n{}\n\n".format(mnFlowIds)
2329
2330 # Print out the IDs that are not in Mininet
2331 if absentIds:
2332 main.log.warn( "Absent ids: {}".format( absentIds ) )
2333 result = False
2334
2335 return main.TRUE if result else main.FALSE
2336
2337 except Exception:
2338 main.log.exception( self.name + ": Uncaught exception!" )
2339 main.cleanup()
2340 main.exit()
2341
2342
Charles Chan029be652015-08-24 01:46:10 +08002343 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08002344 """
Jon Hallefbd9792015-03-05 16:11:36 -08002345 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08002346 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07002347 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002348 self.handle.sendline( "" )
2349 self.handle.expect( "mininet>" )
2350 self.handle.sendline(
2351 "sh sudo tcpdump -n -i " +
2352 intf +
2353 " " +
2354 port +
2355 " -w " +
2356 filename.strip() +
2357 " &" )
2358 self.handle.sendline( "" )
2359 i = self.handle.expect( [ 'No\ssuch\device',
2360 'listening\son',
2361 pexpect.TIMEOUT,
2362 "mininet>" ],
2363 timeout=10 )
2364 main.log.warn( self.handle.before + self.handle.after )
2365 self.handle.sendline( "" )
2366 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002367 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08002368 main.log.error(
2369 self.name +
2370 ": tcpdump - No such device exists. " +
2371 "tcpdump attempted on: " +
2372 intf )
admin2a9548d2014-06-17 14:08:07 -07002373 return main.FALSE
2374 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08002375 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07002376 return main.TRUE
2377 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08002378 main.log.error(
2379 self.name +
2380 ": tcpdump command timed out! Check interface name," +
2381 " given interface was: " +
2382 intf )
admin2a9548d2014-06-17 14:08:07 -07002383 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002384 elif i == 3:
2385 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002386 return main.TRUE
2387 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002388 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002389 return main.FALSE
2390 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002391 main.log.error( self.name + ": EOF exception found" )
2392 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002393 main.cleanup()
2394 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002395 except Exception:
2396 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002397 main.cleanup()
2398 main.exit()
2399
kelvin-onlabd3b64892015-01-20 13:26:24 -08002400 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002401 """
2402 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002403 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002404 self.handle.sendline( "sh sudo pkill tcpdump" )
2405 self.handle.expect( "mininet>" )
2406 self.handle.sendline( "" )
2407 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002408 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002409 main.log.error( self.name + ": EOF exception found" )
2410 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002411 main.cleanup()
2412 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002413 except Exception:
2414 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002415 main.cleanup()
2416 main.exit()
2417
Jon Halld80cc142015-07-06 13:36:05 -07002418 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002419 """
2420 Read ports from a Mininet switch.
2421
2422 Returns a json structure containing information about the
2423 ports of the given switch.
2424 """
2425 response = self.getInterfaces( nodeName )
2426 # TODO: Sanity check on response. log if no such switch exists
2427 ports = []
2428 for line in response.split( "\n" ):
2429 if not line.startswith( "name=" ):
2430 continue
2431 portVars = {}
2432 for var in line.split( "," ):
2433 key, value = var.split( "=" )
2434 portVars[ key ] = value
2435 isUp = portVars.pop( 'enabled', "True" )
2436 isUp = "True" in isUp
2437 if verbose:
2438 main.log.info( "Reading switch port %s(%s)" %
2439 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2440 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002441 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002442 mac = None
2443 ips = []
2444 ip = portVars[ 'ip' ]
2445 if ip == 'None':
2446 ip = None
2447 ips.append( ip )
2448 name = portVars[ 'name' ]
2449 if name == 'None':
2450 name = None
2451 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2452 if name == 'lo':
2453 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2454 else:
2455 portNo = re.search( portRe, name ).group( 'port' )
2456 ports.append( { 'of_port': portNo,
2457 'mac': str( mac ).replace( '\'', '' ),
2458 'name': name,
2459 'ips': ips,
2460 'enabled': isUp } )
2461 return ports
2462
Jon Halld80cc142015-07-06 13:36:05 -07002463 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002464 """
2465 Read switches from Mininet.
2466
2467 Returns a dictionary whose keys are the switch names and the value is
2468 a dictionary containing information about the switch.
2469 """
Jon Halla22481b2015-07-28 17:46:01 -07002470 # NOTE: To support new Mininet switch classes, just append the new
2471 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002472
Jon Halla22481b2015-07-28 17:46:01 -07002473 # Regex patterns to parse 'dump' output
2474 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002475 # <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 -07002476 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002477 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2478 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2479 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2480 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2481 swRE = r"<(?P<class>" + switchClasses + r")" +\
2482 r"(?P<options>\{.*\})?\s" +\
2483 r"(?P<name>[^:]+)\:\s" +\
2484 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2485 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002486 # Update mn port info
2487 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002488 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002489 dump = self.dump().split( "\n" )
2490 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002491 result = re.search( swRE, line, re.I )
2492 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002493 name = result.group( 'name' )
2494 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002495 pid = result.group( 'pid' )
2496 swClass = result.group( 'class' )
2497 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002498 if verbose:
2499 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2500 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002501 output[ name ] = { "dpid": dpid,
2502 "ports": ports,
2503 "swClass": swClass,
2504 "pid": pid,
2505 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002506 return output
2507
Jon Halld80cc142015-07-06 13:36:05 -07002508 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002509 """
2510 Read hosts from Mininet.
2511
2512 Returns a dictionary whose keys are the host names and the value is
2513 a dictionary containing information about the host.
2514 """
2515 # Regex patterns to parse dump output
2516 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002517 # <Host h1: pid=12725>
2518 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2519 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2520 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002521 # NOTE: Does not correctly match hosts with multi-links
2522 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2523 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002524 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002525 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002526 # update mn port info
2527 self.update()
2528 # Get mininet dump
2529 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002530 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002531 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002532 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002533 result = re.search( hostRE, line )
2534 name = result.group( 'name' )
2535 interfaces = []
2536 response = self.getInterfaces( name )
2537 # Populate interface info
2538 for line in response.split( "\n" ):
2539 if line.startswith( "name=" ):
2540 portVars = {}
2541 for var in line.split( "," ):
2542 key, value = var.split( "=" )
2543 portVars[ key ] = value
2544 isUp = portVars.pop( 'enabled', "True" )
2545 isUp = "True" in isUp
2546 if verbose:
2547 main.log.info( "Reading host port %s(%s)" %
2548 ( portVars[ 'name' ],
2549 portVars[ 'mac' ] ) )
2550 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002551 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002552 mac = None
2553 ips = []
2554 ip = portVars[ 'ip' ]
2555 if ip == 'None':
2556 ip = None
2557 ips.append( ip )
2558 intfName = portVars[ 'name' ]
2559 if name == 'None':
2560 name = None
2561 interfaces.append( {
2562 "name": intfName,
2563 "ips": ips,
2564 "mac": str( mac ),
2565 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002566 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002567 return hosts
2568
YPZhang81a7d4e2016-04-18 13:10:17 -07002569 def getLinks( self, timeout=20 ):
Jon Hallafa8a472015-06-12 14:02:42 -07002570 """
2571 Gathers information about current Mininet links. These links may not
2572 be up if one of the ports is down.
2573
2574 Returns a list of dictionaries with link endpoints.
2575
2576 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002577 { 'node1': str( node1 name )
2578 'node2': str( node2 name )
2579 'port1': str( port1 of_port )
2580 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002581 Note: The port number returned is the eth#, not necessarily the of_port
2582 number. In Mininet, for OVS switch, these should be the same. For
2583 hosts, this is just the eth#.
2584 """
2585 self.update()
YPZhang81a7d4e2016-04-18 13:10:17 -07002586 response = self.links(timeout=timeout).split( '\n' )
Jon Hallafa8a472015-06-12 14:02:42 -07002587
2588 # Examples:
2589 # s1-eth3<->s2-eth1 (OK OK)
2590 # s13-eth3<->h27-eth0 (OK OK)
2591 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2592 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2593 links = []
2594 for line in response:
2595 match = re.search( linkRE, line )
2596 if match:
2597 node1 = match.group( 'node1' )
2598 node2 = match.group( 'node2' )
2599 port1 = match.group( 'port1' )
2600 port2 = match.group( 'port2' )
2601 links.append( { 'node1': node1,
2602 'node2': node2,
2603 'port1': port1,
2604 'port2': port2 } )
2605 return links
2606
2607 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002608 """
2609 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002610 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002611
Jon Hallafa8a472015-06-12 14:02:42 -07002612 Dependencies:
2613 1. numpy - "sudo pip install numpy"
2614 """
2615 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002616 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002617 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002618 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002619 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002620 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002621 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002622 main.log.error(
2623 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002624 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002625 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002626 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002627 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002628 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002629 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002630 onosDPIDs.append(
2631 switch[ 'id' ].replace(
2632 ":",
2633 '' ).replace(
2634 "of",
2635 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002636 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002637
Jon Hall7eb38402015-01-08 17:19:54 -08002638 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002639 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002640 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002641 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002642 main.log.error( str( list1 ) )
2643 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002644 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002645 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002646 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002647 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002648 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002649
Jon Hall7eb38402015-01-08 17:19:54 -08002650 # FIXME: this does not look for extra ports in ONOS, only checks that
2651 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002652 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002653
Jon Hall7eb38402015-01-08 17:19:54 -08002654 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002655 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002656 mnPorts = []
2657 onosPorts = []
2658 switchResult = main.TRUE
2659 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002660 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002661 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002662 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002663 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002664 if onosSwitch[ 'device' ][ 'id' ].replace(
2665 ':',
2666 '' ).replace(
2667 "of",
2668 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002669 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002670 if port[ 'isEnabled' ]:
2671 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002672 # onosPorts.append( 'local' )
2673 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002674 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002675 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002676 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002677 mnPorts.sort( key=float )
2678 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002679
kelvin-onlabd3b64892015-01-20 13:26:24 -08002680 mnPortsLog = mnPorts
2681 onosPortsLog = onosPorts
2682 mnPorts = [ x for x in mnPorts ]
2683 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002684
Jon Hall7eb38402015-01-08 17:19:54 -08002685 # TODO: handle other reserved port numbers besides LOCAL
2686 # NOTE: Reserved ports
2687 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2688 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002689 for mnPort in mnPortsLog:
2690 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002691 # don't set results to true here as this is just one of
2692 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002693 mnPorts.remove( mnPort )
2694 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002695
Jon Hall7eb38402015-01-08 17:19:54 -08002696 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002697 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002698 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002699 if 65534 in mnPorts:
2700 mnPorts.remove( 65534 )
2701 if long( uint64( -2 ) ) in onosPorts:
2702 onosPorts.remove( long( uint64( -2 ) ) )
2703 if len( mnPorts ): # the ports of this switch don't match
2704 switchResult = main.FALSE
2705 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2706 if len( onosPorts ): # the ports of this switch don't match
2707 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002708 main.log.warn(
2709 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002710 str( onosPorts ) )
2711 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002712 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002713 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002714 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002715 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2716 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2717 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002718 finalResults = finalResults and portsResults
2719 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002720
Jon Hallafa8a472015-06-12 14:02:42 -07002721 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002722 """
2723 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002724 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002725
Jon Hallafa8a472015-06-12 14:02:42 -07002726 """
Jon Hall7eb38402015-01-08 17:19:54 -08002727 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002728 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002729 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002730
Jon Halld80cc142015-07-06 13:36:05 -07002731 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002732 for l in links:
2733 try:
2734 node1 = switches[ l[ 'node1' ] ]
2735 node2 = switches[ l[ 'node2' ] ]
2736 enabled = True
2737 for port in node1[ 'ports' ]:
2738 if port[ 'of_port' ] == l[ 'port1' ]:
2739 enabled = enabled and port[ 'enabled' ]
2740 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002741 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002742 enabled = enabled and port[ 'enabled' ]
2743 if enabled:
2744 mnLinks.append( l )
2745 except KeyError:
2746 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002747 if 2 * len( mnLinks ) == len( onos ):
2748 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002749 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002750 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002751 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002752 "Mininet has " + str( len( mnLinks ) ) +
2753 " bidirectional links and ONOS has " +
2754 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002755
Jon Hall7eb38402015-01-08 17:19:54 -08002756 # iterate through MN links and check if an ONOS link exists in
2757 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002758 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002759 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002760 node1 = None
2761 port1 = None
2762 node2 = None
2763 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002764 firstDir = main.FALSE
2765 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002766 for swName, switch in switches.iteritems():
2767 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002768 node1 = switch[ 'dpid' ]
2769 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002770 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002771 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002772 if node1 is not None and node2 is not None:
2773 break
Jon Hallafa8a472015-06-12 14:02:42 -07002774 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002775 node2 = switch[ 'dpid' ]
2776 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002777 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002778 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002779 if node1 is not None and node2 is not None:
2780 break
2781
kelvin-onlabd3b64892015-01-20 13:26:24 -08002782 for onosLink in onos:
2783 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002784 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002785 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002786 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002787 onosPort1 = onosLink[ 'src' ][ 'port' ]
2788 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002789
Jon Hall72cf1dc2014-10-20 21:04:50 -04002790 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002791 if str( onosNode1 ) == str( node1 ) and str(
2792 onosNode2 ) == str( node2 ):
2793 if int( onosPort1 ) == int( port1 ) and int(
2794 onosPort2 ) == int( port2 ):
2795 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002796 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002797 main.log.warn(
2798 'The port numbers do not match for ' +
2799 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002800 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002801 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002802 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002803 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002804 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002805
2806 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002807 elif ( str( onosNode1 ) == str( node2 ) and
2808 str( onosNode2 ) == str( node1 ) ):
2809 if ( int( onosPort1 ) == int( port2 )
2810 and int( onosPort2 ) == int( port1 ) ):
2811 secondDir = 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 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002821 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002822 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002823 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002824 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002825 'ONOS does not have the link %s/%s -> %s/%s' %
2826 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002827 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002828 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002829 'ONOS does not have the link %s/%s -> %s/%s' %
2830 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002831 linkResults = linkResults and firstDir and secondDir
2832 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002833
Jon Hallafa8a472015-06-12 14:02:42 -07002834 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002835 """
Jon Hallafa8a472015-06-12 14:02:42 -07002836 Compare mn and onos Hosts.
2837 Since Mininet hosts are quiet, ONOS will only know of them when they
2838 speak. For this reason, we will only check that the hosts in ONOS
2839 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002840
Jon Hallafa8a472015-06-12 14:02:42 -07002841 Arguments:
2842 hostsJson: parsed json object from the onos hosts api
2843 Returns:
2844 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002845 import json
2846 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002847 for onosHost in hostsJson:
2848 onosMAC = onosHost[ 'mac' ].lower()
2849 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002850 for mnHost, info in hosts.iteritems():
2851 for mnIntf in info[ 'interfaces' ]:
2852 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002853 match = True
2854 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002855 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002856 pass # all is well
2857 else:
2858 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002859 main.log.error( "ONOS host " +
2860 onosHost[ 'id' ] +
2861 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002862 str( onosHost[ 'ipAddresses' ] ) +
2863 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002864 str( ip ) +
2865 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002866 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002867 onosHost,
2868 sort_keys=True,
2869 indent=4,
2870 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002871 main.log.info( output )
2872 hostResults = main.FALSE
2873 if not match:
2874 hostResults = main.FALSE
2875 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2876 "corresponding Mininet host." )
2877 output = json.dumps( onosHost,
2878 sort_keys=True,
2879 indent=4,
2880 separators=( ',', ': ' ) )
2881 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002882 return hostResults
2883
Jon Hallafa8a472015-06-12 14:02:42 -07002884 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002885 """
2886 Returns a list of all hosts
2887 Don't ask questions just use it"""
2888 self.handle.sendline( "" )
2889 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002890
Jon Hall7eb38402015-01-08 17:19:54 -08002891 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2892 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002893
kelvin-onlabd3b64892015-01-20 13:26:24 -08002894 handlePy = self.handle.before
2895 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2896 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002897
Jon Hall7eb38402015-01-08 17:19:54 -08002898 self.handle.sendline( "" )
2899 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002900
kelvin-onlabd3b64892015-01-20 13:26:24 -08002901 hostStr = handlePy.replace( "]", "" )
2902 hostStr = hostStr.replace( "'", "" )
2903 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002904 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002905 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002906
kelvin-onlabd3b64892015-01-20 13:26:24 -08002907 return hostList
adminbae64d82013-08-01 10:50:15 -07002908
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002909 def getSwitch( self ):
2910 """
2911 Returns a list of all switches
2912 Again, don't ask question just use it...
2913 """
2914 # get host list...
2915 hostList = self.getHosts()
2916 # Make host set
2917 hostSet = set( hostList )
2918
2919 # Getting all the nodes in mininet
2920 self.handle.sendline( "" )
2921 self.handle.expect( "mininet>" )
2922
2923 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2924 self.handle.expect( "mininet>" )
2925
2926 handlePy = self.handle.before
2927 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2928 handlePy = handlePy.rstrip()
2929
2930 self.handle.sendline( "" )
2931 self.handle.expect( "mininet>" )
2932
2933 nodesStr = handlePy.replace( "]", "" )
2934 nodesStr = nodesStr.replace( "'", "" )
2935 nodesStr = nodesStr.replace( "[", "" )
2936 nodesStr = nodesStr.replace( " ", "" )
2937 nodesList = nodesStr.split( "," )
2938
2939 nodesSet = set( nodesList )
2940 # discarding default controller(s) node
2941 nodesSet.discard( 'c0' )
2942 nodesSet.discard( 'c1' )
2943 nodesSet.discard( 'c2' )
2944
2945 switchSet = nodesSet - hostSet
2946 switchList = list( switchSet )
2947
2948 return switchList
2949
Jon Hall7eb38402015-01-08 17:19:54 -08002950 def update( self ):
2951 """
2952 updates the port address and status information for
2953 each port in mn"""
2954 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002955 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002956 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002957 self.handle.sendline( "" )
2958 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002959
Jon Hall7eb38402015-01-08 17:19:54 -08002960 self.handle.sendline( "update" )
2961 self.handle.expect( "update" )
2962 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002963
Jon Hall7eb38402015-01-08 17:19:54 -08002964 self.handle.sendline( "" )
2965 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002966
Jon Hallb1290e82014-11-18 16:17:48 -05002967 return main.TRUE
2968 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002969 main.log.error( self.name + ": EOF exception found" )
2970 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002971 main.cleanup()
2972 main.exit()
2973
Jon Halld80cc142015-07-06 13:36:05 -07002974 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002975 """
2976 Add vlan tag to a host.
2977 Dependencies:
2978 This class depends on the "vlan" package
2979 $ sudo apt-get install vlan
2980 Configuration:
2981 Load the 8021q module into the kernel
2982 $sudo modprobe 8021q
2983
2984 To make this setup permanent:
2985 $ sudo su -c 'echo "8021q" >> /etc/modules'
2986 """
2987 if self.handle:
2988 try:
Jon Halld80cc142015-07-06 13:36:05 -07002989 # get the ip address of the host
2990 main.log.info( "Get the ip address of the host" )
2991 ipaddr = self.getIPAddress( host )
2992 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002993
Jon Halld80cc142015-07-06 13:36:05 -07002994 # remove IP from interface intf
2995 # Ex: h1 ifconfig h1-eth0 inet 0
2996 main.log.info( "Remove IP from interface " )
2997 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2998 self.handle.sendline( cmd2 )
2999 self.handle.expect( "mininet>" )
3000 response = self.handle.before
3001 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003002
Jon Halld80cc142015-07-06 13:36:05 -07003003 # create VLAN interface
3004 # Ex: h1 vconfig add h1-eth0 100
3005 main.log.info( "Create Vlan" )
3006 cmd3 = host + " vconfig add " + intf + " " + vlan
3007 self.handle.sendline( cmd3 )
3008 self.handle.expect( "mininet>" )
3009 response = self.handle.before
3010 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003011
Jon Halld80cc142015-07-06 13:36:05 -07003012 # assign the host's IP to the VLAN interface
3013 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
3014 main.log.info( "Assign the host IP to the vlan interface" )
3015 vintf = intf + "." + vlan
3016 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
3017 self.handle.sendline( cmd4 )
3018 self.handle.expect( "mininet>" )
3019 response = self.handle.before
3020 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07003021
3022 return main.TRUE
3023 except pexpect.EOF:
3024 main.log.error( self.name + ": EOF exception found" )
3025 main.log.error( self.name + ": " + self.handle.before )
3026 return main.FALSE
3027
Jon Hall892818c2015-10-20 17:58:34 -07003028 def createHostComponent( self, name ):
3029 """
3030 Creates a new mininet cli component with the same parameters as self.
3031 This new component is intended to be used to login to the hosts created
3032 by mininet.
3033
3034 Arguments:
3035 name - The string of the name of this component. The new component
3036 will be assigned to main.<name> .
3037 In addition, main.<name>.name = str( name )
3038 """
3039 try:
3040 # look to see if this component already exists
3041 getattr( main, name )
3042 except AttributeError:
3043 # namespace is clear, creating component
3044 main.componentDictionary[name] = main.componentDictionary[self.name].copy()
3045 main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
3046 main.componentInit( name )
3047 except Exception:
3048 main.log.exception( self.name + ": Uncaught exception!" )
3049 main.cleanup()
3050 main.exit()
3051 else:
3052 # namespace is not clear!
3053 main.log.error( name + " component already exists!" )
3054 # FIXME: Should we exit here?
3055 main.cleanup()
3056 main.exit()
3057
3058 def removeHostComponent( self, name ):
3059 """
3060 Remove host component
3061 Arguments:
3062 name - The string of the name of the component to delete.
3063 """
3064 try:
3065 # Get host component
3066 component = getattr( main, name )
3067 except AttributeError:
3068 main.log.error( "Component " + name + " does not exist." )
3069 return
3070 try:
3071 # Disconnect from component
3072 component.disconnect()
3073 # Delete component
3074 delattr( main, name )
3075 # Delete component from ComponentDictionary
3076 del( main.componentDictionary[name] )
3077 except Exception:
3078 main.log.exception( self.name + ": Uncaught exception!" )
3079 main.cleanup()
3080 main.exit()
3081
3082 def startHostCli( self, host=None ):
3083 """
3084 Use the mininet m utility to connect to the host's cli
3085 """
3086 # These are fields that can be used by scapy packets. Initialized to None
3087 self.hostIp = None
3088 self.hostMac = None
3089 try:
3090 if not host:
3091 host = self.name
3092 self.handle.sendline( self.home + "/util/m " + host )
3093 self.handle.expect( self.hostPrompt )
3094 return main.TRUE
3095 except pexpect.TIMEOUT:
3096 main.log.exception( self.name + ": Command timed out" )
3097 return main.FALSE
3098 except pexpect.EOF:
3099 main.log.exception( self.name + ": connection closed." )
3100 main.cleanup()
3101 main.exit()
3102 except Exception:
3103 main.log.exception( self.name + ": Uncaught exception!" )
3104 main.cleanup()
3105 main.exit()
3106
Jon Hall892818c2015-10-20 17:58:34 -07003107
adminbae64d82013-08-01 10:50:15 -07003108if __name__ != "__main__":
kelvin-onlab50907142015-04-01 13:37:45 -07003109 sys.modules[ __name__ ] = MininetCliDriver()