blob: d726f2ebb5188edc7b85e45092300b2c92d3aa8d [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
Jon Hallbe6dfc42015-01-12 17:37:25 -08005author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
Jon Hall7eb38402015-01-08 17:19:54 -08008TestON is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 2 of the License, or
11( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
Jon Hall7eb38402015-01-08 17:19:54 -080013TestON is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070017
Jon Hall7eb38402015-01-08 17:19:54 -080018You should have received a copy of the GNU General Public License
19along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
Jon Hallbe6dfc42015-01-12 17:37:25 -080021MininetCliDriver is the basic driver which will handle the Mininet functions
22
23Some functions rely on a modified version of Mininet. These functions
24should all be noted in the comments. To get this MN version run these commands
25from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080026 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080027 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080028 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git pull
30
Jon Hall272a4db2015-01-12 17:43:48 -080031
32 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080033changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070034import pexpect
adminbae64d82013-08-01 10:50:15 -070035import re
36import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070037import types
kelvin-onlaba4074292015-07-09 15:19:49 -070038import os
Jon Hall1ccf82c2014-10-15 14:55:16 -040039from math import pow
adminbae64d82013-08-01 10:50:15 -070040from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070041
Jon Hall7eb38402015-01-08 17:19:54 -080042
kelvin-onlab50907142015-04-01 13:37:45 -070043class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080044
45 """
46 MininetCliDriver is the basic driver which will handle
47 the Mininet functions"""
48 def __init__( self ):
49 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070050 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080051 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070052 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080053 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070054 self.flag = 0
55
Jon Hall7eb38402015-01-08 17:19:54 -080056 def connect( self, **connectargs ):
57 """
58 Here the main is the TestON instance after creating
59 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080060 try:
61 for key in connectargs:
62 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070063 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080064 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070065 for key in self.options:
66 if key == "home":
67 self.home = self.options[ 'home' ]
68 break
69 if self.home is None or self.home == "":
70 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070071
72 try:
73 if os.getenv( str( self.ip_address ) ) != None:
74 self.ip_address = os.getenv( str( self.ip_address ) )
75 else:
76 main.log.info( self.name +
77 ": Trying to connect to " +
78 self.ip_address )
79
80 except KeyError:
81 main.log.info( "Invalid host name," +
82 " connecting to local host instead" )
83 self.ip_address = 'localhost'
84 except Exception as inst:
85 main.log.error( "Uncaught exception: " + str( inst ) )
86
kelvin-onlaba1484582015-02-02 15:46:20 -080087 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070088 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080089 self ).connect(
90 user_name=self.user_name,
91 ip_address=self.ip_address,
92 port=None,
93 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080094
kelvin-onlaba1484582015-02-02 15:46:20 -080095 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080096 main.log.info( "Connection successful to the host " +
97 self.user_name +
98 "@" +
99 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800100 return main.TRUE
101 else:
102 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800103 self.user_name +
104 "@" +
105 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800106 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800107 return main.FALSE
108 except pexpect.EOF:
109 main.log.error( self.name + ": EOF exception found" )
110 main.log.error( self.name + ": " + self.handle.before )
111 main.cleanup()
112 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800113 except Exception:
114 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800115 main.cleanup()
116 main.exit()
117
kelvin-onlab10e8d392015-06-03 13:53:45 -0700118 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800119 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700120 Description:
121 Starts Mininet accepts a topology(.py) file and/or an optional
122 argument, to start the mininet, as a parameter.
123 Can also send regular mininet command to load up desired topology.
124 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
125 Options:
126 topoFile = file path for topology file (.py)
127 args = extra option added when starting the topology from the file
128 mnCmd = Mininet command use to start topology
129 Returns:
130 main.TRUE if the mininet starts successfully, main.FALSE
131 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800132 """
Jon Hall7eb38402015-01-08 17:19:54 -0800133 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700134 # make sure old networks are cleaned up
135 main.log.info( self.name +
136 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800137 self.handle.sendline( "sudo mn -c" )
138 i = self.handle.expect( [ 'password\sfor\s',
139 'Cleanup\scomplete',
140 pexpect.EOF,
141 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800142 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800143 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700144 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800145 main.log.info( self.name + ": Sending sudo password" )
146 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800147 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800148 '\$',
149 pexpect.EOF,
150 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800151 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800152 if i == 1:
153 main.log.info( self.name + ": Clean" )
154 elif i == 2:
155 main.log.error( self.name + ": Connection terminated" )
156 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700157 main.log.error( self.name + ": Something while cleaning " +
158 "Mininet took too long... " )
159 # Craft the string to start mininet
160 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700161 if not mnCmd:
162 if topoFile is None or topoFile == '': # If no file is given
163 main.log.info( self.name + ": building fresh Mininet" )
164 cmdString += "mn "
165 if args is None or args == '':
166 # If no args given, use args from .topo file
167 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700168 " " + self.options[ 'arg2' ] +\
169 " --mac --controller " +\
170 self.options[ 'controller' ] + " " +\
171 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700172 else: # else only use given args
173 pass
174 # TODO: allow use of topo args and method args?
175 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700176 main.log.info(
177 "Starting Mininet from topo file " +
178 topoFile )
kelvin-onlab10e8d392015-06-03 13:53:45 -0700179 cmdString += topoFile + " "
180 if args is None:
181 args = ''
182 # TODO: allow use of args from .topo file?
183 cmdString += args
184 else:
185 main.log.info( "Starting Mininet topology using '" + mnCmd +
186 "' command" )
187 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700188 # Send the command and check if network started
189 self.handle.sendline( "" )
190 self.handle.expect( '\$' )
191 main.log.info( "Sending '" + cmdString + "' to " + self.name )
192 self.handle.sendline( cmdString )
193 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800194 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700195 'Exception',
196 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800197 pexpect.EOF,
198 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700199 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800200 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700201 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800202 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800203 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700204 response = str( self.handle.before +
205 self.handle.after )
206 self.handle.expect( '\$' )
207 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700208 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700209 main.log.error(
210 self.name +
211 ": Launching Mininet failed: " + response )
212 return main.FALSE
213 elif i == 2:
214 self.handle.expect( [ "\n",
215 pexpect.EOF,
216 pexpect.TIMEOUT ],
217 timeout )
218 main.log.info( self.handle.before )
219 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800220 main.log.error( self.name + ": Connection timeout" )
221 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700222 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800223 main.log.error(
224 self.name +
225 ": Something took too long... " )
226 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700227 # Why did we hit this part?
228 main.log.error( "startNet did not return correctly" )
229 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800230 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700231 main.log.error( self.name + ": Connection failed to the host " +
232 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800233 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700234 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800235
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800236 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400237 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800238 # In tree topology, if fanout arg is not given, by default it is 2
239 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400240 fanout = 2
241 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500242 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800243 while( k <= depth - 1 ):
244 count = count + pow( fanout, k )
245 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800246 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800247 while( k <= depth - 2 ):
248 # depth-2 gives you only core links and not considering
249 # edge links as seen by ONOS. If all the links including
250 # edge links are required, do depth-1
251 count = count + pow( fanout, k )
252 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800253 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800254 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800255 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800256
Jon Hall7eb38402015-01-08 17:19:54 -0800257 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800258 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800259 # by default it is 1
260 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400261 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800262 numSwitches = depth
263 numHostsPerSw = fanout
264 totalNumHosts = numSwitches * numHostsPerSw
265 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800266 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800267 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800268 topoDict = { "num_switches": int( numSwitches ),
269 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400270 return topoDict
271
kelvin-onlabd3b64892015-01-20 13:26:24 -0800272 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700273 """
274 Calculate the number of switches and links in a topo."""
275 # TODO: combine this function and numSwitchesNlinks
276 argList = self.options[ 'arg1' ].split( "," )
277 topoArgList = argList[ 0 ].split( " " )
278 argList = map( int, argList[ 1: ] )
279 topoArgList = topoArgList[ 1: ] + argList
280
281 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400282 return topoDict
283
GlennRCf07c44a2015-09-18 13:33:46 -0700284 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800285 """
286 Verifies the reachability of the hosts using pingall command.
287 Optional parameter timeout allows you to specify how long to
288 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700289 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700290 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700291 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700292 ping
293 acceptableFailed - Set the number of acceptable failed pings for the
294 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800295 Returns:
296 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700297 otherwise main.FALSE
298 """
299 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700300 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700301 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700302 if self.handle:
303 main.log.info(
304 self.name +
305 ": Checking reachabilty to the hosts using pingall" )
306 response = ""
307 failedPings = 0
308 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700309 cmd = "pingall"
310 if protocol == "IPv6":
311 cmd = "py net.pingAll6()"
312 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700313 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700314 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700315 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700316 pexpect.EOF,
317 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700318 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700319 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700320 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700321 response += self.handle.before
322 break
323 elif i == 1:
324 response += self.handle.before + self.handle.after
325 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700326 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700327 returnValue = main.FALSE
328 if shortCircuit:
329 main.log.error( self.name +
330 ": Aborting pingall - "
331 + str( failedPings ) +
332 " pings failed" )
333 break
Jon Hall390696c2015-05-05 17:13:41 -0700334 if ( time.time() - startTime ) > timeout:
335 returnValue = main.FALSE
336 main.log.error( self.name +
337 ": Aborting pingall - " +
338 "Function took too long " )
339 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700340 elif i == 2:
341 main.log.error( self.name +
342 ": EOF exception found" )
343 main.log.error( self.name + ": " +
344 self.handle.before )
345 main.cleanup()
346 main.exit()
347 elif i == 3:
348 response += self.handle.before
349 main.log.error( self.name +
350 ": TIMEOUT exception found" )
351 main.log.error( self.name +
352 ": " +
353 str( response ) )
354 # NOTE: Send ctrl-c to make sure pingall is done
355 self.handle.sendline( "\x03" )
356 self.handle.expect( "Interrupt" )
357 self.handle.expect( "mininet>" )
358 break
359 pattern = "Results\:"
360 main.log.info( "Pingall output: " + str( response ) )
361 if re.search( pattern, response ):
362 main.log.info( self.name + ": Pingall finished with "
363 + str( failedPings ) + " failed pings" )
364 return returnValue
365 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700366 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700367 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700368 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700369 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700370 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700371 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700372 main.log.error( self.name + ": Connection failed to the host" )
373 main.cleanup()
374 main.exit()
375 except pexpect.TIMEOUT:
376 if response:
377 main.log.info( "Pingall output: " + str( response ) )
378 main.log.error( self.name + ": pexpect.TIMEOUT found" )
379 return main.FALSE
380 except pexpect.EOF:
381 main.log.error( self.name + ": EOF exception found" )
382 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500383 main.cleanup()
384 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700385
Jon Hall7eb38402015-01-08 17:19:54 -0800386 def fpingHost( self, **pingParams ):
387 """
388 Uses the fping package for faster pinging...
389 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800390 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800391 command = args[ "SRC" ] + \
392 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
393 self.handle.sendline( command )
394 self.handle.expect(
395 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
396 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
397 response = self.handle.before
398 if re.search( ":\s-", response ):
399 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700400 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800401 elif re.search( ":\s\d{1,2}\.\d\d", response ):
402 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700403 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800404 main.log.info( self.name + ": Install fping on mininet machine... " )
405 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700406 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800407
Hari Krishna9592fc82015-07-31 15:11:15 -0700408 def pingallHosts( self, hostList ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400409 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700410 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700411
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400412 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700413 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700414
415 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400416 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700417
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400418 Returns main.FALSE if one or more of hosts specified
419 cannot reach each other"""
Hari Krishna9592fc82015-07-31 15:11:15 -0700420
421 cmd = " ping -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400422
423 try:
424 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700425
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400426 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700427 pingResponse = "IPv4 ping across specified hosts\n"
428 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400429 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700430 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400431 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700432 pingList = hostList[ :listIndex ] + \
433 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700434
435 pingResponse += str(str(host) + " -> ")
436
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400437 for temp in pingList:
438 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700439 pingCmd = str( host ) + cmd + str( temp )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400440 self.handle.sendline( pingCmd )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700441 self.handle.expect( "mininet>" )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400442 response = self.handle.before
443 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRCd10d3cc2015-09-24 12:47:16 -0700444 pingResponse += str(" h" + str( temp[1:] ))
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400445 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700446 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400447 # One of the host to host pair is unreachable
448 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700449 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700450 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700451 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700453 except pexpect.TIMEOUT:
454 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700455 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400456 except pexpect.EOF:
457 main.log.error( self.name + ": EOF exception found" )
458 main.log.error( self.name + ": " + self.handle.before )
459 main.cleanup()
460 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700461 except Exception:
462 main.log.exception( self.name + ": Uncaught exception!" )
463 main.cleanup()
464 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400465
kelvin-onlab9b42b0a2015-08-05 14:43:58 -0700466 def pingIpv6Hosts(self, hostList, prefix='1000::'):
Hari Krishna9592fc82015-07-31 15:11:15 -0700467 """
468 IPv6 ping all hosts in hostList. If no prefix passed this will use
469 default prefix of 1000::
470
471 Returns main.TRUE if all hosts specified can reach each other
472
GlennRC2cf7d952015-09-11 16:32:13 -0700473 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700474 """
475 try:
476 main.log.info( "Testing reachability between specified IPv6 hosts" )
477 isReachable = main.TRUE
478 cmd = " ping6 -c 1 -i 1 -W 8 "
GlennRC6d506272015-09-25 11:36:07 -0700479 pingResponse = "IPv6 Pingall output:\n"
480 failedPings = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700481 for host in hostList:
482 listIndex = hostList.index( host )
483 # List of hosts to ping other than itself
484 pingList = hostList[ :listIndex ] + \
485 hostList[ ( listIndex + 1 ): ]
486
GlennRC2cf7d952015-09-11 16:32:13 -0700487 pingResponse += str(str(host) + " -> ")
488
Hari Krishna9592fc82015-07-31 15:11:15 -0700489 for temp in pingList:
490 # Current host pings all other hosts specified
491 pingCmd = str( host ) + cmd + prefix + str( temp[1:] )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700492 self.handle.sendline( pingCmd )
493 self.handle.expect( "mininet>" )
Hari Krishna9592fc82015-07-31 15:11:15 -0700494 response = self.handle.before
495 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700496 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700497 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700498 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700499 # One of the host to host pair is unreachable
500 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700501 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700502 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700503 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700504 return isReachable
505
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700506 except pexpect.TIMEOUT:
507 main.log.exception( self.name + ": TIMEOUT exception" )
508 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 except pexpect.EOF:
510 main.log.error( self.name + ": EOF exception found" )
511 main.log.error( self.name + ": " + self.handle.before )
512 main.cleanup()
513 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700514 except Exception:
515 main.log.exception( self.name + ": Uncaught exception!" )
516 main.cleanup()
517 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700518
Jon Hall7eb38402015-01-08 17:19:54 -0800519 def pingHost( self, **pingParams ):
520 """
521 Ping from one mininet host to another
522 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800523 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800524 command = args[ "SRC" ] + " ping " + \
525 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700526 try:
Jon Hall61282e32015-03-19 11:34:11 -0700527 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800528 self.handle.sendline( command )
529 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700530 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800531 main.log.error(
532 self.name +
533 ": timeout when waiting for response from mininet" )
534 main.log.error( "response: " + str( self.handle.before ) )
535 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700536 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800537 main.log.error(
538 self.name +
539 ": timeout when waiting for response from mininet" )
540 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700541 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700542 if re.search( ',\s0\%\spacket\sloss', response ):
543 main.log.info( self.name + ": no packets lost, host is reachable" )
544 return main.TRUE
545 else:
546 main.log.error(
547 self.name +
548 ": PACKET LOST, HOST IS NOT REACHABLE" )
549 return main.FALSE
550
Jon Hallfbc828e2015-01-06 17:30:19 -0800551 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800552 main.log.error( self.name + ": EOF exception found" )
553 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700554 main.cleanup()
555 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700556 except Exception:
557 main.log.exception( self.name + ": Uncaught exception!" )
558 main.cleanup()
559 main.exit()
560
561 def ping6pair( self, **pingParams ):
562 """
GlennRC2cf7d952015-09-11 16:32:13 -0700563 IPv6 Ping between a pair of mininet hosts
Hari Krishna012a1c12015-08-25 14:23:58 -0700564 Currently the only supported Params are: SRC , TARGET
565 FLOWLABEL and -I (src interface) will be added later after running some tests.
566 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
567 """
568 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
569 command = args[ "SRC" ] + " ping6 " + \
570 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
571 try:
572 main.log.info( "Sending: " + command )
573 self.handle.sendline( command )
574 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
575 if i == 1:
576 main.log.error(
577 self.name +
578 ": timeout when waiting for response from mininet" )
579 main.log.error( "response: " + str( self.handle.before ) )
580 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
581 if i == 1:
582 main.log.error(
583 self.name +
584 ": timeout when waiting for response from mininet" )
585 main.log.error( "response: " + str( self.handle.before ) )
586 response = self.handle.before
587 main.log.info( self.name + ": Ping Response: " + response )
588 if re.search( ',\s0\%\spacket\sloss', response ):
589 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700590 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700591 else:
592 main.log.error(
593 self.name +
594 ": PACKET LOST, HOST IS NOT REACHABLE" )
595 return main.FALSE
596
597 except pexpect.EOF:
598 main.log.error( self.name + ": EOF exception found" )
599 main.log.error( self.name + ": " + self.handle.before )
600 main.cleanup()
601 main.exit()
602 except Exception:
603 main.log.exception( self.name + ": Uncaught exception!" )
604 main.cleanup()
605 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800606
Jon Hall7eb38402015-01-08 17:19:54 -0800607 def checkIP( self, host ):
608 """
609 Verifies the host's ip configured or not."""
610 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700611 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800612 response = self.execute(
613 cmd=host +
614 " ifconfig",
615 prompt="mininet>",
616 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800617 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800618 main.log.error( self.name + ": EOF exception found" )
619 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700620 main.cleanup()
621 main.exit()
adminbae64d82013-08-01 10:50:15 -0700622
Jon Hall7eb38402015-01-08 17:19:54 -0800623 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800624 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
625 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
626 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
627 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
628 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800629 # pattern = "inet addr:10.0.0.6"
630 if re.search( pattern, response ):
631 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700632 return main.TRUE
633 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800634 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700635 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800636 else:
637 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800638
Jon Hall7eb38402015-01-08 17:19:54 -0800639 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800640 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700641 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800642 response = self.execute(
643 cmd="h1 /usr/sbin/sshd -D&",
644 prompt="mininet>",
645 timeout=10 )
646 response = self.execute(
647 cmd="h4 /usr/sbin/sshd -D&",
648 prompt="mininet>",
649 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700650 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800651 vars( self )[ key ] = connectargs[ key ]
652 response = self.execute(
653 cmd="xterm h1 h4 ",
654 prompt="mininet>",
655 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800656 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800657 main.log.error( self.name + ": EOF exception found" )
658 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700659 main.cleanup()
660 main.exit()
adminbae64d82013-08-01 10:50:15 -0700661 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800662 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700663 if self.flag == 0:
664 self.flag = 1
665 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800666 else:
adminbae64d82013-08-01 10:50:15 -0700667 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800668
kelvin-onlaba1484582015-02-02 15:46:20 -0800669 def moveHost( self, host, oldSw, newSw, ):
670 """
671 Moves a host from one switch to another on the fly
672 Note: The intf between host and oldSw when detached
673 using detach(), will still show up in the 'net'
674 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700675 ( which is correct behavior since the interfaces
676 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800677 """
678 if self.handle:
679 try:
680 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700681 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800682 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800683 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800684 response = self.execute( cmd=cmd,
685 prompt="mininet>",
686 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700687
kelvin-onlaba1484582015-02-02 15:46:20 -0800688 # Determine hostintf and Oldswitchintf
689 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800690 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800691 print "cmd2= ", cmd
692 self.handle.sendline( cmd )
693 self.handle.expect( "mininet>" )
694
shahshreya73537862015-02-11 15:15:24 -0800695 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800696 cmd = "px ipaddr = hintf.IP()"
697 print "cmd3= ", cmd
698 self.handle.sendline( cmd )
699 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800700
701 cmd = "px macaddr = hintf.MAC()"
702 print "cmd3= ", cmd
703 self.handle.sendline( cmd )
704 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700705
kelvin-onlaba1484582015-02-02 15:46:20 -0800706 # Detach interface between oldSw-host
707 cmd = "px " + oldSw + ".detach( sintf )"
708 print "cmd4= ", cmd
709 self.handle.sendline( cmd )
710 self.handle.expect( "mininet>" )
711
712 # Add link between host-newSw
713 cmd = "py net.addLink(" + host + "," + newSw + ")"
714 print "cmd5= ", cmd
715 self.handle.sendline( cmd )
716 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700717
kelvin-onlaba1484582015-02-02 15:46:20 -0800718 # Determine hostintf and Newswitchintf
719 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800720 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800721 print "cmd6= ", cmd
722 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700723 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800724
725 # Attach interface between newSw-host
726 cmd = "px " + newSw + ".attach( sintf )"
727 print "cmd3= ", cmd
728 self.handle.sendline( cmd )
729 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700730
kelvin-onlaba1484582015-02-02 15:46:20 -0800731 # Set ipaddress of the host-newSw interface
732 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
733 print "cmd7 = ", cmd
734 self.handle.sendline( cmd )
735 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800736
737 # Set macaddress of the host-newSw interface
738 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
739 print "cmd8 = ", cmd
740 self.handle.sendline( cmd )
741 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700742
kelvin-onlaba1484582015-02-02 15:46:20 -0800743 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800744 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800745 self.handle.sendline( cmd )
746 self.handle.expect( "mininet>" )
747 print "output = ", self.handle.before
748
749 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800750 cmd = host + " ifconfig"
751 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800752 self.handle.sendline( cmd )
753 self.handle.expect( "mininet>" )
754 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700755
kelvin-onlaba1484582015-02-02 15:46:20 -0800756 return main.TRUE
757 except pexpect.EOF:
758 main.log.error( self.name + ": EOF exception found" )
759 main.log.error( self.name + ": " + self.handle.before )
760 return main.FALSE
761
Jon Hall7eb38402015-01-08 17:19:54 -0800762 def changeIP( self, host, intf, newIP, newNetmask ):
763 """
764 Changes the ip address of a host on the fly
765 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800766 if self.handle:
767 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800768 cmd = host + " ifconfig " + intf + " " + \
769 newIP + " " + 'netmask' + " " + newNetmask
770 self.handle.sendline( cmd )
771 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800772 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800773 main.log.info( "response = " + response )
774 main.log.info(
775 "Ip of host " +
776 host +
777 " changed to new IP " +
778 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800779 return main.TRUE
780 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800781 main.log.error( self.name + ": EOF exception found" )
782 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800783 return main.FALSE
784
Jon Hall7eb38402015-01-08 17:19:54 -0800785 def changeDefaultGateway( self, host, newGW ):
786 """
787 Changes the default gateway of a host
788 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800789 if self.handle:
790 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800791 cmd = host + " route add default gw " + newGW
792 self.handle.sendline( cmd )
793 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800794 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800795 main.log.info( "response = " + response )
796 main.log.info(
797 "Default gateway of host " +
798 host +
799 " changed to " +
800 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800801 return main.TRUE
802 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800803 main.log.error( self.name + ": EOF exception found" )
804 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800805 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800806
Jon Hall7eb38402015-01-08 17:19:54 -0800807 def addStaticMACAddress( self, host, GW, macaddr ):
808 """
Jon Hallefbd9792015-03-05 16:11:36 -0800809 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800810 if self.handle:
811 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800812 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
813 cmd = host + " arp -s " + GW + " " + macaddr
814 self.handle.sendline( cmd )
815 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800816 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800817 main.log.info( "response = " + response )
818 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800819 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800820 GW +
821 " changed to " +
822 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800823 return main.TRUE
824 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800825 main.log.error( self.name + ": EOF exception found" )
826 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800827 return main.FALSE
828
Jon Hall7eb38402015-01-08 17:19:54 -0800829 def verifyStaticGWandMAC( self, host ):
830 """
831 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800832 if self.handle:
833 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800834 # h1 arp -an
835 cmd = host + " arp -an "
836 self.handle.sendline( cmd )
837 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800838 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800839 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800840 return main.TRUE
841 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800842 main.log.error( self.name + ": EOF exception found" )
843 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800844 return main.FALSE
845
Jon Hall7eb38402015-01-08 17:19:54 -0800846 def getMacAddress( self, host ):
847 """
848 Verifies the host's ip configured or not."""
849 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700850 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800851 response = self.execute(
852 cmd=host +
853 " ifconfig",
854 prompt="mininet>",
855 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800856 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800857 main.log.error( self.name + ": EOF exception found" )
858 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700859 main.cleanup()
860 main.exit()
adminbae64d82013-08-01 10:50:15 -0700861
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700862 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800863 macAddressSearch = re.search( pattern, response, re.I )
864 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800865 main.log.info(
866 self.name +
867 ": Mac-Address of Host " +
868 host +
869 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800870 macAddress )
871 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700872 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800873 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700874
Jon Hall7eb38402015-01-08 17:19:54 -0800875 def getInterfaceMACAddress( self, host, interface ):
876 """
877 Return the IP address of the interface on the given host"""
878 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700879 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800880 response = self.execute( cmd=host + " ifconfig " + interface,
881 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800882 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800883 main.log.error( self.name + ": EOF exception found" )
884 main.log.error( self.name + ": " + self.handle.before )
885 main.cleanup()
886 main.exit()
887
888 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800889 macAddressSearch = re.search( pattern, response, re.I )
890 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800891 main.log.info( "No mac address found in %s" % response )
892 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800893 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800894 main.log.info(
895 "Mac-Address of " +
896 host +
897 ":" +
898 interface +
899 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800900 macAddress )
901 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800902 else:
903 main.log.error( "Connection failed to the host" )
904
905 def getIPAddress( self, host ):
906 """
907 Verifies the host's ip configured or not."""
908 if self.handle:
909 try:
910 response = self.execute(
911 cmd=host +
912 " ifconfig",
913 prompt="mininet>",
914 timeout=10 )
915 except pexpect.EOF:
916 main.log.error( self.name + ": EOF exception found" )
917 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700918 main.cleanup()
919 main.exit()
adminbae64d82013-08-01 10:50:15 -0700920
921 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800922 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800923 main.log.info(
924 self.name +
925 ": IP-Address of Host " +
926 host +
927 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800928 ipAddressSearch.group( 1 ) )
929 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800930 else:
931 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800932
Jon Hall7eb38402015-01-08 17:19:54 -0800933 def getSwitchDPID( self, switch ):
934 """
935 return the datapath ID of the switch"""
936 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700937 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700938 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800939 response = self.execute(
940 cmd=cmd,
941 prompt="mininet>",
942 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800943 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800944 main.log.error( self.name + ": EOF exception found" )
945 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700946 main.cleanup()
947 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800948 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800949 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700950 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800951 main.log.info(
952 "Couldn't find DPID for switch %s, found: %s" %
953 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700954 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800955 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700956 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800957 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700958
Jon Hall7eb38402015-01-08 17:19:54 -0800959 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700960 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800961 self.handle.sendline( "" )
962 self.expect( "mininet>" )
963 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700964 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800965 response = self.execute(
966 cmd=cmd,
967 prompt="mininet>",
968 timeout=10 )
969 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700970 response = self.handle.before
971 return response
972 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800973 main.log.error( self.name + ": EOF exception found" )
974 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700975 main.cleanup()
976 main.exit()
977
Jon Hall7eb38402015-01-08 17:19:54 -0800978 def getInterfaces( self, node ):
979 """
980 return information dict about interfaces connected to the node"""
981 if self.handle:
982 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800983 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700984 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700985 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800986 response = self.execute(
987 cmd=cmd,
988 prompt="mininet>",
989 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800990 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800991 main.log.error( self.name + ": EOF exception found" )
992 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700993 main.cleanup()
994 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700995 return response
996 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800997 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700998
Jon Hall7eb38402015-01-08 17:19:54 -0800999 def dump( self ):
1000 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001001 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001002 response = self.execute(
1003 cmd='dump',
1004 prompt='mininet>',
1005 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001006 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001007 main.log.error( self.name + ": EOF exception found" )
1008 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001009 main.cleanup()
1010 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001011 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001012
Jon Hall7eb38402015-01-08 17:19:54 -08001013 def intfs( self ):
1014 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001015 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001016 response = self.execute(
1017 cmd='intfs',
1018 prompt='mininet>',
1019 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001020 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001021 main.log.error( self.name + ": EOF exception found" )
1022 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001023 main.cleanup()
1024 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001025 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001026
Jon Hall7eb38402015-01-08 17:19:54 -08001027 def net( self ):
1028 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001029 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001030 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001031 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001032 main.log.error( self.name + ": EOF exception found" )
1033 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001034 main.cleanup()
1035 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001036 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001037
Jon Hallafa8a472015-06-12 14:02:42 -07001038 def links( self ):
1039 main.log.info( self.name + ": List network links" )
1040 try:
1041 response = self.execute( cmd='links', prompt='mininet>',
1042 timeout=10 )
1043 except pexpect.EOF:
1044 main.log.error( self.name + ": EOF exception found" )
1045 main.log.error( self.name + ": " + self.handle.before )
1046 main.cleanup()
1047 main.exit()
1048 return response
1049
GlennRC61321f22015-07-16 13:36:54 -07001050 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001051 '''
1052 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001053
kelvin-onlab7cce9382015-07-17 10:21:03 -07001054 @parm:
1055 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1056 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1057 '''
1058 for host1 in hosts:
1059 for host2 in hosts:
1060 if host1 != host2:
1061 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1062 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001063
1064 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001065 '''
1066 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1067 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001068
kelvin-onlab7cce9382015-07-17 10:21:03 -07001069 @parm:
1070 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1071 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1072 '''
1073 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1074 try:
1075 # Setup the mininet command
1076 cmd1 = 'iperf ' + host1 + " " + host2
1077 self.handle.sendline( cmd1 )
1078 outcome = self.handle.expect( "mininet>", timeout )
1079 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001080
kelvin-onlab7cce9382015-07-17 10:21:03 -07001081 # checks if there are results in the mininet response
1082 if "Results:" in response:
1083 main.log.report(self.name + ": iperf test completed")
1084 # parse the mn results
1085 response = response.split("\r\n")
1086 response = response[len(response)-2]
1087 response = response.split(": ")
1088 response = response[len(response)-1]
1089 response = response.replace("[", "")
1090 response = response.replace("]", "")
1091 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001092
kelvin-onlab7cce9382015-07-17 10:21:03 -07001093 # this is the bandwith two and from the two hosts
1094 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001095
kelvin-onlab7cce9382015-07-17 10:21:03 -07001096 # there should be two elements in the bandwidth list
1097 # ['host1 to host2', 'host2 to host1"]
1098 if len(bandwidth) == 2:
1099 main.log.report(self.name + ": iperf test successful")
1100 return main.TRUE
1101 else:
1102 main.log.error(self.name + ": invalid iperf results")
1103 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001104 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001105 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001106 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001107
GlennRC61321f22015-07-16 13:36:54 -07001108 except pexpect.TIMEOUT:
1109 main.log.error( self.name + ": TIMEOUT exception found")
1110 main.log.error( self.name + ": Exception: Cannot connect to iperf on port 5001" )
1111 return main.FALSE
1112
Jon Hallfbc828e2015-01-06 17:30:19 -08001113 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001114 main.log.error( self.name + ": EOF exception found" )
1115 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001116 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001117 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001118
1119 def iperfudpAll(self, hosts, bandwidth="10M"):
1120 '''
1121 Runs the iperfudp function with a given set of hosts and specified
1122 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001123
GlennRC61321f22015-07-16 13:36:54 -07001124 @param:
1125 bandwidth: the targeted bandwidth, in megabits ('M')
1126 '''
1127 for host1 in hosts:
1128 for host2 in hosts:
1129 if host1 != host2:
1130 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1131 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1132
1133 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1134
kelvin-onlab7cce9382015-07-17 10:21:03 -07001135 '''
1136 Creates an iperf UDP test with a specific bandwidth.
1137 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001138
kelvin-onlab7cce9382015-07-17 10:21:03 -07001139 @param:
1140 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1141 '''
1142 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1143 try:
1144 # setup the mininet command
1145 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1146 self.handle.sendline(cmd)
1147 self.handle.expect("mininet>")
1148 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001149
kelvin-onlab7cce9382015-07-17 10:21:03 -07001150 # check if there are in results in the mininet response
1151 if "Results:" in response:
1152 main.log.report(self.name + ": iperfudp test completed")
1153 # parse the results
1154 response = response.split("\r\n")
1155 response = response[len(response)-2]
1156 response = response.split(": ")
1157 response = response[len(response)-1]
1158 response = response.replace("[", "")
1159 response = response.replace("]", "")
1160 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001161
kelvin-onlab7cce9382015-07-17 10:21:03 -07001162 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001163
kelvin-onlab7cce9382015-07-17 10:21:03 -07001164 # check to see if there are at least three entries
1165 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1166 if len(mnBandwidth) == 3:
1167 # if one entry is blank then something is wrong
1168 for item in mnBandwidth:
1169 if item == "":
1170 main.log.error(self.name + ": Could not parse iperf output")
1171 main.log.error(self.name + ": invalid iperfudp results")
1172 return main.FALSE
1173 # otherwise results are vaild
1174 main.log.report(self.name + ": iperfudp test successful")
1175 return main.TRUE
1176 else:
1177 main.log.error(self.name + ": invalid iperfudp results")
1178 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001179
kelvin-onlab7cce9382015-07-17 10:21:03 -07001180 except pexpect.EOF:
1181 main.log.error( self.name + ": EOF exception found" )
1182 main.log.error( self.name + ": " + self.handle.before )
1183 main.cleanup()
1184 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001185
Jon Hall7eb38402015-01-08 17:19:54 -08001186 def nodes( self ):
1187 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001188 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001189 response = self.execute(
1190 cmd='nodes',
1191 prompt='mininet>',
1192 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001193 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001194 main.log.error( self.name + ": EOF exception found" )
1195 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001196 main.cleanup()
1197 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001198 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001199
Jon Hall7eb38402015-01-08 17:19:54 -08001200 def pingpair( self ):
1201 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001202 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001203 response = self.execute(
1204 cmd='pingpair',
1205 prompt='mininet>',
1206 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001207 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001208 main.log.error( self.name + ": EOF exception found" )
1209 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001210 main.cleanup()
1211 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001212
Jon Hall7eb38402015-01-08 17:19:54 -08001213 if re.search( ',\s0\%\spacket\sloss', response ):
1214 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001215 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001216 else:
1217 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001218 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001219
Jon Hall7eb38402015-01-08 17:19:54 -08001220 def link( self, **linkargs ):
1221 """
1222 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001223 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001224 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1225 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1226 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1227 main.log.info(
1228 "Bring link between '" +
1229 end1 +
1230 "' and '" +
1231 end2 +
1232 "' '" +
1233 option +
1234 "'" )
1235 command = "link " + \
1236 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001237 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001238 self.handle.sendline( command )
1239 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001240 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001241 main.log.error( self.name + ": EOF exception found" )
1242 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001243 main.cleanup()
1244 main.exit()
adminbae64d82013-08-01 10:50:15 -07001245 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001246
pingping-lin8244a3b2015-09-16 13:36:56 -07001247 def switch( self, **switchargs ):
1248 """
1249 start/stop a switch
1250 """
1251 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1252 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1253 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1254 command = "switch " + str( sw ) + " " + str( option )
1255 main.log.info( command )
1256 try:
1257 self.handle.sendline( command )
1258 self.handle.expect( "mininet>" )
1259 except pexpect.TIMEOUT:
1260 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1261 main.cleanup()
1262 main.exit()
1263 except pexpect.EOF:
1264 main.log.error( self.name + ": EOF exception found" )
1265 main.log.error( self.name + ": " + self.handle.before )
1266 main.cleanup()
1267 main.exit()
1268 return main.TRUE
1269
pingping-lin5bb663b2015-09-24 11:47:50 -07001270 def node( self, nodeName, commandStr ):
1271 """
1272 Carry out a command line on a given node
1273 @parm:
1274 nodeName: the node name in Mininet testbed
1275 commandStr: the command line will be carried out on the node
1276 Example: main.Mininet.node( nodeName="h1", commandStr="ls" )
1277 """
1278 command = str( nodeName ) + " " + str( commandStr )
1279 main.log.info( command )
1280
1281 try:
1282 response = self.execute( cmd = command, prompt = "mininet>" )
1283 if re.search( "Unknown command", response ):
1284 main.log.warn( response )
1285 return main.FALSE
1286 except pexpect.TIMEOUT:
1287 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1288 main.cleanup()
1289 main.exit()
1290 except pexpect.EOF:
1291 main.log.error( self.name + ": EOF exception found" )
1292 main.log.error( self.name + ": " + self.handle.before )
1293 main.cleanup()
1294 main.exit()
1295 main.log.info( " response is :" )
1296 main.log.info( response )
1297 return response
1298
Jon Hall7eb38402015-01-08 17:19:54 -08001299 def yank( self, **yankargs ):
1300 """
1301 yank a mininet switch interface to a host"""
1302 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001303 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001304 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1305 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1306 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001307 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001308 response = self.execute(
1309 cmd=command,
1310 prompt="mininet>",
1311 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001312 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001313 main.log.error( self.name + ": EOF exception found" )
1314 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001315 main.cleanup()
1316 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001317 return main.TRUE
1318
Jon Hall7eb38402015-01-08 17:19:54 -08001319 def plug( self, **plugargs ):
1320 """
1321 plug the yanked mininet switch interface to a switch"""
1322 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001323 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001324 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1325 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1326 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001327 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001328 response = self.execute(
1329 cmd=command,
1330 prompt="mininet>",
1331 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001332 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001333 main.log.error( self.name + ": EOF exception found" )
1334 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001335 main.cleanup()
1336 main.exit()
adminbae64d82013-08-01 10:50:15 -07001337 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001338
Jon Hall7eb38402015-01-08 17:19:54 -08001339 def dpctl( self, **dpctlargs ):
1340 """
1341 Run dpctl command on all switches."""
1342 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001343 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001344 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1345 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1346 command = "dpctl " + cmd + " " + str( cmdargs )
1347 try:
1348 response = self.execute(
1349 cmd=command,
1350 prompt="mininet>",
1351 timeout=10 )
1352 except pexpect.EOF:
1353 main.log.error( self.name + ": EOF exception found" )
1354 main.log.error( self.name + ": " + self.handle.before )
1355 main.cleanup()
1356 main.exit()
1357 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001358
kelvin-onlabd3b64892015-01-20 13:26:24 -08001359 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001360 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001361 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001362 fileInput = path + '/lib/Mininet/INSTALL'
1363 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001364 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001365 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001366 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001367 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001368 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001369 return version
adminbae64d82013-08-01 10:50:15 -07001370
kelvin-onlabd3b64892015-01-20 13:26:24 -08001371 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001372 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001373 Parameters:
1374 sw: The name of an OVS switch. Example "s1"
1375 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001376 The output of the command from the mininet cli
1377 or main.FALSE on timeout"""
1378 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001379 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001380 response = self.execute(
1381 cmd=command,
1382 prompt="mininet>",
1383 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001384 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001385 return response
admin2a9548d2014-06-17 14:08:07 -07001386 else:
1387 return main.FALSE
1388 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001389 main.log.error( self.name + ": EOF exception found" )
1390 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001391 main.cleanup()
1392 main.exit()
adminbae64d82013-08-01 10:50:15 -07001393
Charles Chan029be652015-08-24 01:46:10 +08001394 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001395 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001396 Description:
1397 Assign switches to the controllers ( for ovs use only )
1398 Required:
1399 sw - Name of the switch. This can be a list or a string.
1400 ip - Ip addresses of controllers. This can be a list or a string.
1401 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001402 port - ONOS use port 6653, if no list of ports is passed, then
1403 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001404 ptcp - ptcp number, This can be a string or a list that has
1405 the same length as switch. This is optional and not required
1406 when using ovs switches.
1407 NOTE: If switches and ptcp are given in a list type they should have the
1408 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1409 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001410
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001411 Return:
1412 Returns main.TRUE if mininet correctly assigned switches to
1413 controllers, otherwise it will return main.FALSE or an appropriate
1414 exception(s)
1415 """
1416 assignResult = main.TRUE
1417 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001418 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001419 command = "sh ovs-vsctl set-controller "
1420 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001421 try:
1422 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001423 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001424 if isinstance( port, types.StringType ) or \
1425 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001426 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001427 elif isinstance( port, types.ListType ):
1428 main.log.error( self.name + ": Only one controller " +
1429 "assigned and a list of ports has" +
1430 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001431 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001432 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001433 main.log.error( self.name + ": Invalid controller port " +
1434 "number. Please specify correct " +
1435 "controller port" )
1436 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001437
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001438 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001439 if isinstance( port, types.StringType ) or \
1440 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001441 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001442 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1443 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001444 elif isinstance( port, types.ListType ):
1445 if ( len( ip ) != len( port ) ):
1446 main.log.error( self.name + ": Port list = " +
1447 str( len( port ) ) +
1448 "should be the same as controller" +
1449 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001450 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001451 else:
1452 onosIp = ""
1453 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001454 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1455 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001456 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001457 main.log.error( self.name + ": Invalid controller port " +
1458 "number. Please specify correct " +
1459 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001460 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001461 else:
1462 main.log.error( self.name + ": Invalid ip address" )
1463 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001464
1465 if isinstance( sw, types.StringType ):
1466 command += sw + " "
1467 if ptcp:
1468 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001469 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001470 elif isinstance( ptcp, types.ListType ):
1471 main.log.error( self.name + ": Only one switch is " +
1472 "being set and multiple PTCP is " +
1473 "being passed " )
1474 else:
1475 main.log.error( self.name + ": Invalid PTCP" )
1476 ptcp = ""
1477 command += onosIp
1478 commandList.append( command )
1479
1480 elif isinstance( sw, types.ListType ):
1481 if ptcp:
1482 if isinstance( ptcp, types.ListType ):
1483 if len( ptcp ) != len( sw ):
1484 main.log.error( self.name + ": PTCP length = " +
1485 str( len( ptcp ) ) +
1486 " is not the same as switch" +
1487 " length = " +
1488 str( len( sw ) ) )
1489 return main.FALSE
1490 else:
1491 for switch, ptcpNum in zip( sw, ptcp ):
1492 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001493 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001494 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001495 tempCmd += onosIp
1496 commandList.append( tempCmd )
1497 else:
1498 main.log.error( self.name + ": Invalid PTCP" )
1499 return main.FALSE
1500 else:
1501 for switch in sw:
1502 tempCmd = "sh ovs-vsctl set-controller "
1503 tempCmd += switch + " " + onosIp
1504 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001505 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001506 main.log.error( self.name + ": Invalid switch type " )
1507 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001508
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001509 for cmd in commandList:
1510 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001511 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001512 except pexpect.TIMEOUT:
1513 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1514 return main.FALSE
1515 except pexpect.EOF:
1516 main.log.error( self.name + ": EOF exception found" )
1517 main.log.error( self.name + ": " + self.handle.before )
1518 main.cleanup()
1519 main.exit()
1520 return main.TRUE
1521 except Exception:
1522 main.log.exception( self.name + ": Uncaught exception!" )
1523 main.cleanup()
1524 main.exit()
adminbae64d82013-08-01 10:50:15 -07001525
kelvin-onlabd3b64892015-01-20 13:26:24 -08001526 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001527 """
1528 Removes the controller target from sw"""
1529 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001530 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001531 response = self.execute(
1532 cmd=command,
1533 prompt="mininet>",
1534 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001535 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001536 main.log.error( self.name + ": EOF exception found" )
1537 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001538 main.cleanup()
1539 main.exit()
1540 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001541 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001542
kelvin-onlabd3b64892015-01-20 13:26:24 -08001543 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001544 """
Jon Hallb1290e82014-11-18 16:17:48 -05001545 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001546 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001547 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001548 NOTE: cannot currently specify what type of switch
1549 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001550 sw = name of the new switch as a string
1551 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001552 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001553 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001554 """
1555 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001556 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001557 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001558 response = self.execute(
1559 cmd=command,
1560 prompt="mininet>",
1561 timeout=10 )
1562 if re.search( "already exists!", response ):
1563 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001564 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001565 elif re.search( "Error", response ):
1566 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001567 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001568 elif re.search( "usage:", response ):
1569 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001570 return main.FALSE
1571 else:
1572 return main.TRUE
1573 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001574 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001575 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001576 main.cleanup()
1577 main.exit()
1578
kelvin-onlabd3b64892015-01-20 13:26:24 -08001579 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001580 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001581 delete a switch from the mininet topology
1582 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001583 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001584 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001585 sw = name of the switch as a string
1586 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001587 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001588 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001589 response = self.execute(
1590 cmd=command,
1591 prompt="mininet>",
1592 timeout=10 )
1593 if re.search( "no switch named", response ):
1594 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001595 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001596 elif re.search( "Error", response ):
1597 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001598 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001599 elif re.search( "usage:", response ):
1600 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001601 return main.FALSE
1602 else:
1603 return main.TRUE
1604 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001605 main.log.error( self.name + ": EOF exception found" )
1606 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001607 main.cleanup()
1608 main.exit()
1609
kelvin-onlabd3b64892015-01-20 13:26:24 -08001610 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001611 """
1612 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001613 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001614 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001615 NOTE: cannot currently specify what type of link
1616 required params:
1617 node1 = the string node name of the first endpoint of the link
1618 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001619 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001620 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001621 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001622 response = self.execute(
1623 cmd=command,
1624 prompt="mininet>",
1625 timeout=10 )
1626 if re.search( "doesnt exist!", response ):
1627 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001628 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001629 elif re.search( "Error", response ):
1630 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001631 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001632 elif re.search( "usage:", response ):
1633 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001634 return main.FALSE
1635 else:
1636 return main.TRUE
1637 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001638 main.log.error( self.name + ": EOF exception found" )
1639 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001640 main.cleanup()
1641 main.exit()
1642
kelvin-onlabd3b64892015-01-20 13:26:24 -08001643 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001644 """
1645 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001646 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001647 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001648 required params:
1649 node1 = the string node name of the first endpoint of the link
1650 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001651 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001652 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001653 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001654 response = self.execute(
1655 cmd=command,
1656 prompt="mininet>",
1657 timeout=10 )
1658 if re.search( "no node named", response ):
1659 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001660 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001661 elif re.search( "Error", response ):
1662 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001663 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001664 elif re.search( "usage:", response ):
1665 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001666 return main.FALSE
1667 else:
1668 return main.TRUE
1669 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001670 main.log.error( self.name + ": EOF exception found" )
1671 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001672 main.cleanup()
1673 main.exit()
1674
kelvin-onlabd3b64892015-01-20 13:26:24 -08001675 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001676 """
Jon Hallb1290e82014-11-18 16:17:48 -05001677 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001678 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001679 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001680 NOTE: cannot currently specify what type of host
1681 required params:
1682 hostname = the string hostname
1683 optional key-value params
1684 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001685 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001686 """
1687 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001688 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001689 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001690 response = self.execute(
1691 cmd=command,
1692 prompt="mininet>",
1693 timeout=10 )
1694 if re.search( "already exists!", response ):
1695 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001696 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001697 elif re.search( "doesnt exists!", response ):
1698 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001699 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001700 elif re.search( "Error", response ):
1701 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001702 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001703 elif re.search( "usage:", response ):
1704 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001705 return main.FALSE
1706 else:
1707 return main.TRUE
1708 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001709 main.log.error( self.name + ": EOF exception found" )
1710 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001711 main.cleanup()
1712 main.exit()
1713
kelvin-onlabd3b64892015-01-20 13:26:24 -08001714 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001715 """
1716 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001717 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001718 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001719 NOTE: this uses a custom mn function
1720 required params:
1721 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001722 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001723 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001724 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001725 response = self.execute(
1726 cmd=command,
1727 prompt="mininet>",
1728 timeout=10 )
1729 if re.search( "no host named", response ):
1730 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001731 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001732 elif re.search( "Error", response ):
1733 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001734 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001735 elif re.search( "usage:", response ):
1736 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001737 return main.FALSE
1738 else:
1739 return main.TRUE
1740 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001741 main.log.error( self.name + ": EOF exception found" )
1742 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001743 main.cleanup()
1744 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001745
Jon Hall7eb38402015-01-08 17:19:54 -08001746 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001747 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001748 Called at the end of the test to stop the mininet and
1749 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001750 """
Jon Halld80cc142015-07-06 13:36:05 -07001751 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001752 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001753 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001754 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001755 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001756 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001757 elif i == 1:
1758 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001759 # print "Disconnecting Mininet"
1760 if self.handle:
1761 self.handle.sendline( "exit" )
1762 self.handle.expect( "exit" )
1763 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001764 else:
1765 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001766 return response
1767
Jon Halld80cc142015-07-06 13:36:05 -07001768 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001769 """
Jon Hall21270ac2015-02-16 17:59:55 -08001770 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001771 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001772 main.FALSE if the pexpect handle does not exist.
1773
Jon Halld61331b2015-02-17 16:35:47 -08001774 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001775 """
Jon Halld61331b2015-02-17 16:35:47 -08001776 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001777 response = ''
1778 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001779 try:
Jon Halld80cc142015-07-06 13:36:05 -07001780 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001781 i = self.handle.expect( [ 'mininet>',
1782 '\$',
1783 pexpect.EOF,
1784 pexpect.TIMEOUT ],
1785 timeout )
1786 if i == 0:
1787 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001788 response = self.execute(
1789 cmd="exit",
1790 prompt="(.*)",
1791 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001792 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001793 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001794 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001795
kelvin-onlab56a3f462015-02-06 14:04:43 -08001796 if i == 1:
1797 main.log.info( " Mininet trying to exit while not " +
1798 "in the mininet prompt" )
1799 elif i == 2:
1800 main.log.error( "Something went wrong exiting mininet" )
1801 elif i == 3: # timeout
1802 main.log.error( "Something went wrong exiting mininet " +
1803 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001804
Hari Krishnab35c6d02015-03-18 11:13:51 -07001805 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001806 self.handle.sendline( "" )
1807 self.handle.expect( '\$' )
1808 self.handle.sendline(
1809 "sudo kill -9 \`ps -ef | grep \"" +
1810 fileName +
1811 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001812 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001813 main.log.error( self.name + ": EOF exception found" )
1814 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001815 main.cleanup()
1816 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001817 else:
1818 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001819 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001820 return response
1821
Jon Halla5cb3412015-08-18 14:08:22 -07001822 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001823 """
1824 Description:
1825 Sends arp message from mininet host for hosts discovery
1826 Required:
1827 host - hosts name
1828 Optional:
1829 ip - ip address that does not exist in the network so there would
1830 be no reply.
1831 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001832 if ethDevice:
1833 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001834 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001835 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001836 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001837 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001838 i = self.handle.expect( [ "mininet>", "arping: " ] )
1839 if i == 0:
1840 return main.TRUE
1841 elif i == 1:
1842 response = self.handle.before + self.handle.after
1843 self.handle.expect( "mininet>" )
1844 response += self.handle.before + self.handle.after
1845 main.log.warn( "Error sending arping, output was: " +
1846 response )
1847 return main.FALSE
1848 except pexpect.TIMEOUT:
1849 main.log.error( self.name + ": TIMEOUT exception found" )
1850 main.log.warn( self.handle.before )
1851 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001852 except pexpect.EOF:
1853 main.log.error( self.name + ": EOF exception found" )
1854 main.log.error( self.name + ": " + self.handle.before )
1855 main.cleanup()
1856 main.exit()
admin07529932013-11-22 14:58:28 -08001857
Jon Hall7eb38402015-01-08 17:19:54 -08001858 def decToHex( self, num ):
1859 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001860
Jon Hall7eb38402015-01-08 17:19:54 -08001861 def getSwitchFlowCount( self, switch ):
1862 """
1863 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001864 if self.handle:
1865 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1866 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001867 response = self.execute(
1868 cmd=cmd,
1869 prompt="mininet>",
1870 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001871 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001872 main.log.error( self.name + ": EOF exception found" )
1873 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001874 main.cleanup()
1875 main.exit()
1876 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001877 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001878 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001879 main.log.info(
1880 "Couldn't find flows on switch %s, found: %s" %
1881 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001882 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001883 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001884 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001885 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001886
kelvin-onlabd3b64892015-01-20 13:26:24 -08001887 def checkFlows( self, sw, dumpFormat=None ):
1888 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001889 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001890 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001891 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001892 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001893 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001894 response = self.execute(
1895 cmd=command,
1896 prompt="mininet>",
1897 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001898 return response
1899 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001900 main.log.error( self.name + ": EOF exception found" )
1901 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001902 main.cleanup()
1903 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001904
Jon Hall9043c902015-07-30 14:23:44 -07001905 def getFlowTable( self, protoVersion, sw ):
1906 """
1907 Returns certain fields of an OVS flow table. Will force output to
1908 either OF 1.0 or 1.3 format for consistency.
1909
1910 TODO add option to look at cookies. ignoring them for now
1911
1912 NOTE: Use format to force consistent flow table output across
1913 versions
1914 """
1915 try:
1916 self.handle.sendline( "" )
1917 self.handle.expect( "mininet>" )
1918 command = "sh ovs-ofctl dump-flows " + sw
1919 if protoVersion == 1.0:
1920 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\
1921 " print $1 $3 $6 $7 $8}' | "
1922 elif protoVersion == 1.3:
1923 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\
1924 " print $1 $3 $6 $7}' | "
1925 else:
1926 main.log.error(
1927 "Unknown protoVersion in getFlowTable(). given: (" +
1928 str( type( protoVersion ) ) +
1929 ") '" + str( protoVersion ) + "'" )
1930 return None
1931 command += "cut -d ',' -f 2- | sort -n -k1 -r"
1932 self.handle.sendline( command )
1933 self.handle.expect( "sort" )
1934 self.handle.expect( "OFPST_FLOW" )
1935 response = self.handle.before
1936 return response
1937 except pexpect.EOF:
1938 main.log.error( self.name + ": EOF exception found" )
1939 main.log.error( self.name + ": " + self.handle.before )
1940 main.cleanup()
1941 main.exit()
1942 except pexpect.TIMEOUT:
1943 main.log.exception( self.name + ": Timeout exception: " )
1944 return None
1945
1946 def flowComp( self, flow1, flow2 ):
1947 if flow1 == flow2:
1948 return main.TRUE
1949 else:
1950 main.log.info( "Flow tables do not match, printing tables:" )
1951 main.log.info( "Flow Table 1:" )
1952 main.log.info( flow1 )
1953 main.log.info( "Flow Table 2:" )
1954 main.log.info( flow2 )
1955 return main.FALSE
1956
Charles Chan029be652015-08-24 01:46:10 +08001957 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001958 """
Jon Hallefbd9792015-03-05 16:11:36 -08001959 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001960 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001961 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001962 self.handle.sendline( "" )
1963 self.handle.expect( "mininet>" )
1964 self.handle.sendline(
1965 "sh sudo tcpdump -n -i " +
1966 intf +
1967 " " +
1968 port +
1969 " -w " +
1970 filename.strip() +
1971 " &" )
1972 self.handle.sendline( "" )
1973 i = self.handle.expect( [ 'No\ssuch\device',
1974 'listening\son',
1975 pexpect.TIMEOUT,
1976 "mininet>" ],
1977 timeout=10 )
1978 main.log.warn( self.handle.before + self.handle.after )
1979 self.handle.sendline( "" )
1980 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001981 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001982 main.log.error(
1983 self.name +
1984 ": tcpdump - No such device exists. " +
1985 "tcpdump attempted on: " +
1986 intf )
admin2a9548d2014-06-17 14:08:07 -07001987 return main.FALSE
1988 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001989 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001990 return main.TRUE
1991 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001992 main.log.error(
1993 self.name +
1994 ": tcpdump command timed out! Check interface name," +
1995 " given interface was: " +
1996 intf )
admin2a9548d2014-06-17 14:08:07 -07001997 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001998 elif i == 3:
1999 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002000 return main.TRUE
2001 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002002 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07002003 return main.FALSE
2004 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002005 main.log.error( self.name + ": EOF exception found" )
2006 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002007 main.cleanup()
2008 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002009 except Exception:
2010 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002011 main.cleanup()
2012 main.exit()
2013
kelvin-onlabd3b64892015-01-20 13:26:24 -08002014 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08002015 """
2016 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07002017 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002018 self.handle.sendline( "sh sudo pkill tcpdump" )
2019 self.handle.expect( "mininet>" )
2020 self.handle.sendline( "" )
2021 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002022 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002023 main.log.error( self.name + ": EOF exception found" )
2024 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07002025 main.cleanup()
2026 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002027 except Exception:
2028 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002029 main.cleanup()
2030 main.exit()
2031
Jon Halld80cc142015-07-06 13:36:05 -07002032 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002033 """
2034 Read ports from a Mininet switch.
2035
2036 Returns a json structure containing information about the
2037 ports of the given switch.
2038 """
2039 response = self.getInterfaces( nodeName )
2040 # TODO: Sanity check on response. log if no such switch exists
2041 ports = []
2042 for line in response.split( "\n" ):
2043 if not line.startswith( "name=" ):
2044 continue
2045 portVars = {}
2046 for var in line.split( "," ):
2047 key, value = var.split( "=" )
2048 portVars[ key ] = value
2049 isUp = portVars.pop( 'enabled', "True" )
2050 isUp = "True" in isUp
2051 if verbose:
2052 main.log.info( "Reading switch port %s(%s)" %
2053 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2054 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002055 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002056 mac = None
2057 ips = []
2058 ip = portVars[ 'ip' ]
2059 if ip == 'None':
2060 ip = None
2061 ips.append( ip )
2062 name = portVars[ 'name' ]
2063 if name == 'None':
2064 name = None
2065 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2066 if name == 'lo':
2067 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2068 else:
2069 portNo = re.search( portRe, name ).group( 'port' )
2070 ports.append( { 'of_port': portNo,
2071 'mac': str( mac ).replace( '\'', '' ),
2072 'name': name,
2073 'ips': ips,
2074 'enabled': isUp } )
2075 return ports
2076
Jon Halld80cc142015-07-06 13:36:05 -07002077 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002078 """
2079 Read switches from Mininet.
2080
2081 Returns a dictionary whose keys are the switch names and the value is
2082 a dictionary containing information about the switch.
2083 """
Jon Halla22481b2015-07-28 17:46:01 -07002084 # NOTE: To support new Mininet switch classes, just append the new
2085 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002086
Jon Halla22481b2015-07-28 17:46:01 -07002087 # Regex patterns to parse 'dump' output
2088 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002089 # <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 -07002090 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002091 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2092 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2093 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2094 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2095 swRE = r"<(?P<class>" + switchClasses + r")" +\
2096 r"(?P<options>\{.*\})?\s" +\
2097 r"(?P<name>[^:]+)\:\s" +\
2098 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2099 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002100 # Update mn port info
2101 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002102 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002103 dump = self.dump().split( "\n" )
2104 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002105 result = re.search( swRE, line, re.I )
2106 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002107 name = result.group( 'name' )
2108 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002109 pid = result.group( 'pid' )
2110 swClass = result.group( 'class' )
2111 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002112 if verbose:
2113 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2114 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002115 output[ name ] = { "dpid": dpid,
2116 "ports": ports,
2117 "swClass": swClass,
2118 "pid": pid,
2119 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002120 return output
2121
Jon Halld80cc142015-07-06 13:36:05 -07002122 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002123 """
2124 Read hosts from Mininet.
2125
2126 Returns a dictionary whose keys are the host names and the value is
2127 a dictionary containing information about the host.
2128 """
2129 # Regex patterns to parse dump output
2130 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002131 # <Host h1: pid=12725>
2132 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2133 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2134 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002135 # NOTE: Does not correctly match hosts with multi-links
2136 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2137 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002138 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002139 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002140 # update mn port info
2141 self.update()
2142 # Get mininet dump
2143 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002144 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002145 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002146 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002147 result = re.search( hostRE, line )
2148 name = result.group( 'name' )
2149 interfaces = []
2150 response = self.getInterfaces( name )
2151 # Populate interface info
2152 for line in response.split( "\n" ):
2153 if line.startswith( "name=" ):
2154 portVars = {}
2155 for var in line.split( "," ):
2156 key, value = var.split( "=" )
2157 portVars[ key ] = value
2158 isUp = portVars.pop( 'enabled', "True" )
2159 isUp = "True" in isUp
2160 if verbose:
2161 main.log.info( "Reading host port %s(%s)" %
2162 ( portVars[ 'name' ],
2163 portVars[ 'mac' ] ) )
2164 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002165 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002166 mac = None
2167 ips = []
2168 ip = portVars[ 'ip' ]
2169 if ip == 'None':
2170 ip = None
2171 ips.append( ip )
2172 intfName = portVars[ 'name' ]
2173 if name == 'None':
2174 name = None
2175 interfaces.append( {
2176 "name": intfName,
2177 "ips": ips,
2178 "mac": str( mac ),
2179 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002180 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002181 return hosts
2182
2183 def getLinks( self ):
2184 """
2185 Gathers information about current Mininet links. These links may not
2186 be up if one of the ports is down.
2187
2188 Returns a list of dictionaries with link endpoints.
2189
2190 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002191 { 'node1': str( node1 name )
2192 'node2': str( node2 name )
2193 'port1': str( port1 of_port )
2194 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002195 Note: The port number returned is the eth#, not necessarily the of_port
2196 number. In Mininet, for OVS switch, these should be the same. For
2197 hosts, this is just the eth#.
2198 """
2199 self.update()
2200 response = self.links().split( '\n' )
2201
2202 # Examples:
2203 # s1-eth3<->s2-eth1 (OK OK)
2204 # s13-eth3<->h27-eth0 (OK OK)
2205 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2206 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2207 links = []
2208 for line in response:
2209 match = re.search( linkRE, line )
2210 if match:
2211 node1 = match.group( 'node1' )
2212 node2 = match.group( 'node2' )
2213 port1 = match.group( 'port1' )
2214 port2 = match.group( 'port2' )
2215 links.append( { 'node1': node1,
2216 'node2': node2,
2217 'port1': port1,
2218 'port2': port2 } )
2219 return links
2220
2221 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002222 """
2223 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002224 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002225
Jon Hallafa8a472015-06-12 14:02:42 -07002226 Dependencies:
2227 1. numpy - "sudo pip install numpy"
2228 """
2229 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002230 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002231 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002232 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002233 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002234 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002235 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002236 main.log.error(
2237 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002238 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002239 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002240 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002241 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002242 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002243 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002244 onosDPIDs.append(
2245 switch[ 'id' ].replace(
2246 ":",
2247 '' ).replace(
2248 "of",
2249 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002250 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002251
Jon Hall7eb38402015-01-08 17:19:54 -08002252 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002253 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002254 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002255 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002256 main.log.error( str( list1 ) )
2257 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002258 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002259 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002260 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002261 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002262 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002263
Jon Hall7eb38402015-01-08 17:19:54 -08002264 # FIXME: this does not look for extra ports in ONOS, only checks that
2265 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002266 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002267
Jon Hall7eb38402015-01-08 17:19:54 -08002268 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002269 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002270 mnPorts = []
2271 onosPorts = []
2272 switchResult = main.TRUE
2273 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002274 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002275 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002276 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002277 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002278 if onosSwitch[ 'device' ][ 'id' ].replace(
2279 ':',
2280 '' ).replace(
2281 "of",
2282 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002283 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002284 if port[ 'isEnabled' ]:
2285 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002286 # onosPorts.append( 'local' )
2287 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002288 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002289 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002290 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002291 mnPorts.sort( key=float )
2292 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002293
kelvin-onlabd3b64892015-01-20 13:26:24 -08002294 mnPortsLog = mnPorts
2295 onosPortsLog = onosPorts
2296 mnPorts = [ x for x in mnPorts ]
2297 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002298
Jon Hall7eb38402015-01-08 17:19:54 -08002299 # TODO: handle other reserved port numbers besides LOCAL
2300 # NOTE: Reserved ports
2301 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2302 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002303 for mnPort in mnPortsLog:
2304 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002305 # don't set results to true here as this is just one of
2306 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002307 mnPorts.remove( mnPort )
2308 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002309
Jon Hall7eb38402015-01-08 17:19:54 -08002310 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002311 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002312 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002313 if 65534 in mnPorts:
2314 mnPorts.remove( 65534 )
2315 if long( uint64( -2 ) ) in onosPorts:
2316 onosPorts.remove( long( uint64( -2 ) ) )
2317 if len( mnPorts ): # the ports of this switch don't match
2318 switchResult = main.FALSE
2319 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2320 if len( onosPorts ): # the ports of this switch don't match
2321 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002322 main.log.warn(
2323 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002324 str( onosPorts ) )
2325 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002326 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002327 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002328 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002329 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2330 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2331 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002332 finalResults = finalResults and portsResults
2333 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002334
Jon Hallafa8a472015-06-12 14:02:42 -07002335 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002336 """
2337 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002338 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002339
Jon Hallafa8a472015-06-12 14:02:42 -07002340 """
Jon Hall7eb38402015-01-08 17:19:54 -08002341 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002342 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002343 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002344
Jon Halld80cc142015-07-06 13:36:05 -07002345 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002346 for l in links:
2347 try:
2348 node1 = switches[ l[ 'node1' ] ]
2349 node2 = switches[ l[ 'node2' ] ]
2350 enabled = True
2351 for port in node1[ 'ports' ]:
2352 if port[ 'of_port' ] == l[ 'port1' ]:
2353 enabled = enabled and port[ 'enabled' ]
2354 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002355 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002356 enabled = enabled and port[ 'enabled' ]
2357 if enabled:
2358 mnLinks.append( l )
2359 except KeyError:
2360 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002361 if 2 * len( mnLinks ) == len( onos ):
2362 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002363 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002364 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002365 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002366 "Mininet has " + str( len( mnLinks ) ) +
2367 " bidirectional links and ONOS has " +
2368 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002369
Jon Hall7eb38402015-01-08 17:19:54 -08002370 # iterate through MN links and check if an ONOS link exists in
2371 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002372 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002373 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002374 node1 = None
2375 port1 = None
2376 node2 = None
2377 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002378 firstDir = main.FALSE
2379 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002380 for swName, switch in switches.iteritems():
2381 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002382 node1 = switch[ 'dpid' ]
2383 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002384 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002385 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002386 if node1 is not None and node2 is not None:
2387 break
Jon Hallafa8a472015-06-12 14:02:42 -07002388 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002389 node2 = switch[ 'dpid' ]
2390 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002391 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002392 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002393 if node1 is not None and node2 is not None:
2394 break
2395
kelvin-onlabd3b64892015-01-20 13:26:24 -08002396 for onosLink in onos:
2397 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002398 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002399 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002400 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002401 onosPort1 = onosLink[ 'src' ][ 'port' ]
2402 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002403
Jon Hall72cf1dc2014-10-20 21:04:50 -04002404 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002405 if str( onosNode1 ) == str( node1 ) and str(
2406 onosNode2 ) == str( node2 ):
2407 if int( onosPort1 ) == int( port1 ) and int(
2408 onosPort2 ) == int( port2 ):
2409 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002410 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002411 main.log.warn(
2412 'The port numbers do not match for ' +
2413 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002414 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002415 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002416 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002417 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002418 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002419
2420 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002421 elif ( str( onosNode1 ) == str( node2 ) and
2422 str( onosNode2 ) == str( node1 ) ):
2423 if ( int( onosPort1 ) == int( port2 )
2424 and int( onosPort2 ) == int( port1 ) ):
2425 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002426 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002427 main.log.warn(
2428 'The port numbers do not match for ' +
2429 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002430 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002431 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002432 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002433 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002434 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002435 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002436 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002437 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002438 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002439 'ONOS does not have the link %s/%s -> %s/%s' %
2440 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002441 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002442 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002443 'ONOS does not have the link %s/%s -> %s/%s' %
2444 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002445 linkResults = linkResults and firstDir and secondDir
2446 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002447
Jon Hallafa8a472015-06-12 14:02:42 -07002448 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002449 """
Jon Hallafa8a472015-06-12 14:02:42 -07002450 Compare mn and onos Hosts.
2451 Since Mininet hosts are quiet, ONOS will only know of them when they
2452 speak. For this reason, we will only check that the hosts in ONOS
2453 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002454
Jon Hallafa8a472015-06-12 14:02:42 -07002455 Arguments:
2456 hostsJson: parsed json object from the onos hosts api
2457 Returns:
2458 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002459 import json
2460 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002461 for onosHost in hostsJson:
2462 onosMAC = onosHost[ 'mac' ].lower()
2463 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002464 for mnHost, info in hosts.iteritems():
2465 for mnIntf in info[ 'interfaces' ]:
2466 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002467 match = True
2468 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002469 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002470 pass # all is well
2471 else:
2472 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002473 main.log.error( "ONOS host " +
2474 onosHost[ 'id' ] +
2475 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002476 str( onosHost[ 'ipAddresses' ] ) +
2477 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002478 str( ip ) +
2479 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002480 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002481 onosHost,
2482 sort_keys=True,
2483 indent=4,
2484 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002485 main.log.info( output )
2486 hostResults = main.FALSE
2487 if not match:
2488 hostResults = main.FALSE
2489 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2490 "corresponding Mininet host." )
2491 output = json.dumps( onosHost,
2492 sort_keys=True,
2493 indent=4,
2494 separators=( ',', ': ' ) )
2495 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002496 return hostResults
2497
Jon Hallafa8a472015-06-12 14:02:42 -07002498 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002499 """
2500 Returns a list of all hosts
2501 Don't ask questions just use it"""
2502 self.handle.sendline( "" )
2503 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002504
Jon Hall7eb38402015-01-08 17:19:54 -08002505 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2506 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002507
kelvin-onlabd3b64892015-01-20 13:26:24 -08002508 handlePy = self.handle.before
2509 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2510 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002511
Jon Hall7eb38402015-01-08 17:19:54 -08002512 self.handle.sendline( "" )
2513 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002514
kelvin-onlabd3b64892015-01-20 13:26:24 -08002515 hostStr = handlePy.replace( "]", "" )
2516 hostStr = hostStr.replace( "'", "" )
2517 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002518 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002519 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002520
kelvin-onlabd3b64892015-01-20 13:26:24 -08002521 return hostList
adminbae64d82013-08-01 10:50:15 -07002522
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002523 def getSwitch( self ):
2524 """
2525 Returns a list of all switches
2526 Again, don't ask question just use it...
2527 """
2528 # get host list...
2529 hostList = self.getHosts()
2530 # Make host set
2531 hostSet = set( hostList )
2532
2533 # Getting all the nodes in mininet
2534 self.handle.sendline( "" )
2535 self.handle.expect( "mininet>" )
2536
2537 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2538 self.handle.expect( "mininet>" )
2539
2540 handlePy = self.handle.before
2541 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2542 handlePy = handlePy.rstrip()
2543
2544 self.handle.sendline( "" )
2545 self.handle.expect( "mininet>" )
2546
2547 nodesStr = handlePy.replace( "]", "" )
2548 nodesStr = nodesStr.replace( "'", "" )
2549 nodesStr = nodesStr.replace( "[", "" )
2550 nodesStr = nodesStr.replace( " ", "" )
2551 nodesList = nodesStr.split( "," )
2552
2553 nodesSet = set( nodesList )
2554 # discarding default controller(s) node
2555 nodesSet.discard( 'c0' )
2556 nodesSet.discard( 'c1' )
2557 nodesSet.discard( 'c2' )
2558
2559 switchSet = nodesSet - hostSet
2560 switchList = list( switchSet )
2561
2562 return switchList
2563
Jon Hall7eb38402015-01-08 17:19:54 -08002564 def update( self ):
2565 """
2566 updates the port address and status information for
2567 each port in mn"""
2568 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002569 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002570 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002571 self.handle.sendline( "" )
2572 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002573
Jon Hall7eb38402015-01-08 17:19:54 -08002574 self.handle.sendline( "update" )
2575 self.handle.expect( "update" )
2576 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002577
Jon Hall7eb38402015-01-08 17:19:54 -08002578 self.handle.sendline( "" )
2579 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002580
Jon Hallb1290e82014-11-18 16:17:48 -05002581 return main.TRUE
2582 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002583 main.log.error( self.name + ": EOF exception found" )
2584 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002585 main.cleanup()
2586 main.exit()
2587
Jon Halld80cc142015-07-06 13:36:05 -07002588 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002589 """
2590 Add vlan tag to a host.
2591 Dependencies:
2592 This class depends on the "vlan" package
2593 $ sudo apt-get install vlan
2594 Configuration:
2595 Load the 8021q module into the kernel
2596 $sudo modprobe 8021q
2597
2598 To make this setup permanent:
2599 $ sudo su -c 'echo "8021q" >> /etc/modules'
2600 """
2601 if self.handle:
2602 try:
Jon Halld80cc142015-07-06 13:36:05 -07002603 # get the ip address of the host
2604 main.log.info( "Get the ip address of the host" )
2605 ipaddr = self.getIPAddress( host )
2606 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002607
Jon Halld80cc142015-07-06 13:36:05 -07002608 # remove IP from interface intf
2609 # Ex: h1 ifconfig h1-eth0 inet 0
2610 main.log.info( "Remove IP from interface " )
2611 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2612 self.handle.sendline( cmd2 )
2613 self.handle.expect( "mininet>" )
2614 response = self.handle.before
2615 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002616
Jon Halld80cc142015-07-06 13:36:05 -07002617 # create VLAN interface
2618 # Ex: h1 vconfig add h1-eth0 100
2619 main.log.info( "Create Vlan" )
2620 cmd3 = host + " vconfig add " + intf + " " + vlan
2621 self.handle.sendline( cmd3 )
2622 self.handle.expect( "mininet>" )
2623 response = self.handle.before
2624 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002625
Jon Halld80cc142015-07-06 13:36:05 -07002626 # assign the host's IP to the VLAN interface
2627 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2628 main.log.info( "Assign the host IP to the vlan interface" )
2629 vintf = intf + "." + vlan
2630 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2631 self.handle.sendline( cmd4 )
2632 self.handle.expect( "mininet>" )
2633 response = self.handle.before
2634 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002635
2636 return main.TRUE
2637 except pexpect.EOF:
2638 main.log.error( self.name + ": EOF exception found" )
2639 main.log.error( self.name + ": " + self.handle.before )
2640 return main.FALSE
2641
adminbae64d82013-08-01 10:50:15 -07002642if __name__ != "__main__":
2643 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002644 sys.modules[ __name__ ] = MininetCliDriver()