blob: be421365654db35d0c03926065628f0ad77dde35 [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
427
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400428 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700429 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400430 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700431 pingList = hostList[ :listIndex ] + \
432 hostList[ ( listIndex + 1 ): ]
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400433 for temp in pingList:
434 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700435 pingCmd = str( host ) + cmd + str( temp )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400436 self.handle.sendline( pingCmd )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700437 self.handle.expect( "mininet>" )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400438 response = self.handle.before
439 if re.search( ',\s0\%\spacket\sloss', response ):
Jon Halld80cc142015-07-06 13:36:05 -0700440 main.log.info( str( host ) + " -> " + str( temp ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400441 else:
Jon Halla5cb3412015-08-18 14:08:22 -0700442 main.log.warn(
Jon Halld80cc142015-07-06 13:36:05 -0700443 str( host ) + " -> X (" + str( temp ) + ") "
444 " Destination Unreachable" )
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400445 # One of the host to host pair is unreachable
446 isReachable = main.FALSE
kelvin-onlab2ff57022015-05-29 10:48:51 -0700447 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700448 except pexpect.TIMEOUT:
449 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700450 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451 except pexpect.EOF:
452 main.log.error( self.name + ": EOF exception found" )
453 main.log.error( self.name + ": " + self.handle.before )
454 main.cleanup()
455 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700456 except Exception:
457 main.log.exception( self.name + ": Uncaught exception!" )
458 main.cleanup()
459 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400460
kelvin-onlab9b42b0a2015-08-05 14:43:58 -0700461 def pingIpv6Hosts(self, hostList, prefix='1000::'):
Hari Krishna9592fc82015-07-31 15:11:15 -0700462 """
463 IPv6 ping all hosts in hostList. If no prefix passed this will use
464 default prefix of 1000::
465
466 Returns main.TRUE if all hosts specified can reach each other
467
GlennRC2cf7d952015-09-11 16:32:13 -0700468 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700469 """
470 try:
471 main.log.info( "Testing reachability between specified IPv6 hosts" )
472 isReachable = main.TRUE
473 cmd = " ping6 -c 1 -i 1 -W 8 "
GlennRC2cf7d952015-09-11 16:32:13 -0700474 pingResponse = ""
Hari Krishna7d1eacf2015-09-14 09:32:21 -0700475 main.log.info("IPv6 Pingall output:")
Hari Krishna9592fc82015-07-31 15:11:15 -0700476 for host in hostList:
477 listIndex = hostList.index( host )
478 # List of hosts to ping other than itself
479 pingList = hostList[ :listIndex ] + \
480 hostList[ ( listIndex + 1 ): ]
481
GlennRC2cf7d952015-09-11 16:32:13 -0700482 pingResponse += str(str(host) + " -> ")
483
Hari Krishna9592fc82015-07-31 15:11:15 -0700484 for temp in pingList:
485 # Current host pings all other hosts specified
486 pingCmd = str( host ) + cmd + prefix + str( temp[1:] )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700487 self.handle.sendline( pingCmd )
488 self.handle.expect( "mininet>" )
Hari Krishna9592fc82015-07-31 15:11:15 -0700489 response = self.handle.before
490 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700491 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700492 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700493 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700494 # One of the host to host pair is unreachable
495 isReachable = main.FALSE
GlennRC2cf7d952015-09-11 16:32:13 -0700496 main.log.info(pingResponse)
497 pingResponse = ""
Hari Krishna9592fc82015-07-31 15:11:15 -0700498 return isReachable
499
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700500 except pexpect.TIMEOUT:
501 main.log.exception( self.name + ": TIMEOUT exception" )
502 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700503 except pexpect.EOF:
504 main.log.error( self.name + ": EOF exception found" )
505 main.log.error( self.name + ": " + self.handle.before )
506 main.cleanup()
507 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700508 except Exception:
509 main.log.exception( self.name + ": Uncaught exception!" )
510 main.cleanup()
511 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700512
Jon Hall7eb38402015-01-08 17:19:54 -0800513 def pingHost( self, **pingParams ):
514 """
515 Ping from one mininet host to another
516 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800517 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800518 command = args[ "SRC" ] + " ping " + \
519 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700520 try:
Jon Hall61282e32015-03-19 11:34:11 -0700521 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800522 self.handle.sendline( command )
523 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700524 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800525 main.log.error(
526 self.name +
527 ": timeout when waiting for response from mininet" )
528 main.log.error( "response: " + str( self.handle.before ) )
529 i = self.handle.expect( [ "mininet>", 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 ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700535 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700536 if re.search( ',\s0\%\spacket\sloss', response ):
537 main.log.info( self.name + ": no packets lost, host is reachable" )
538 return main.TRUE
539 else:
540 main.log.error(
541 self.name +
542 ": PACKET LOST, HOST IS NOT REACHABLE" )
543 return main.FALSE
544
Jon Hallfbc828e2015-01-06 17:30:19 -0800545 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800546 main.log.error( self.name + ": EOF exception found" )
547 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700548 main.cleanup()
549 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700550 except Exception:
551 main.log.exception( self.name + ": Uncaught exception!" )
552 main.cleanup()
553 main.exit()
554
555 def ping6pair( self, **pingParams ):
556 """
GlennRC2cf7d952015-09-11 16:32:13 -0700557 IPv6 Ping between a pair of mininet hosts
Hari Krishna012a1c12015-08-25 14:23:58 -0700558 Currently the only supported Params are: SRC , TARGET
559 FLOWLABEL and -I (src interface) will be added later after running some tests.
560 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
561 """
562 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
563 command = args[ "SRC" ] + " ping6 " + \
564 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
565 try:
566 main.log.info( "Sending: " + command )
567 self.handle.sendline( command )
568 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
569 if i == 1:
570 main.log.error(
571 self.name +
572 ": timeout when waiting for response from mininet" )
573 main.log.error( "response: " + str( self.handle.before ) )
574 i = self.handle.expect( [ "mininet>", 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 response = self.handle.before
581 main.log.info( self.name + ": Ping Response: " + response )
582 if re.search( ',\s0\%\spacket\sloss', response ):
583 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700584 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700585 else:
586 main.log.error(
587 self.name +
588 ": PACKET LOST, HOST IS NOT REACHABLE" )
589 return main.FALSE
590
591 except pexpect.EOF:
592 main.log.error( self.name + ": EOF exception found" )
593 main.log.error( self.name + ": " + self.handle.before )
594 main.cleanup()
595 main.exit()
596 except Exception:
597 main.log.exception( self.name + ": Uncaught exception!" )
598 main.cleanup()
599 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800600
Jon Hall7eb38402015-01-08 17:19:54 -0800601 def checkIP( self, host ):
602 """
603 Verifies the host's ip configured or not."""
604 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700605 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800606 response = self.execute(
607 cmd=host +
608 " ifconfig",
609 prompt="mininet>",
610 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800611 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800612 main.log.error( self.name + ": EOF exception found" )
613 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700614 main.cleanup()
615 main.exit()
adminbae64d82013-08-01 10:50:15 -0700616
Jon Hall7eb38402015-01-08 17:19:54 -0800617 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800618 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
619 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
620 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
621 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
622 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800623 # pattern = "inet addr:10.0.0.6"
624 if re.search( pattern, response ):
625 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700626 return main.TRUE
627 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800628 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700629 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800630 else:
631 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800632
Jon Hall7eb38402015-01-08 17:19:54 -0800633 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800634 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700635 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800636 response = self.execute(
637 cmd="h1 /usr/sbin/sshd -D&",
638 prompt="mininet>",
639 timeout=10 )
640 response = self.execute(
641 cmd="h4 /usr/sbin/sshd -D&",
642 prompt="mininet>",
643 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700644 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800645 vars( self )[ key ] = connectargs[ key ]
646 response = self.execute(
647 cmd="xterm h1 h4 ",
648 prompt="mininet>",
649 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800650 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800651 main.log.error( self.name + ": EOF exception found" )
652 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700653 main.cleanup()
654 main.exit()
adminbae64d82013-08-01 10:50:15 -0700655 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800656 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700657 if self.flag == 0:
658 self.flag = 1
659 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800660 else:
adminbae64d82013-08-01 10:50:15 -0700661 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800662
kelvin-onlaba1484582015-02-02 15:46:20 -0800663 def moveHost( self, host, oldSw, newSw, ):
664 """
665 Moves a host from one switch to another on the fly
666 Note: The intf between host and oldSw when detached
667 using detach(), will still show up in the 'net'
668 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700669 ( which is correct behavior since the interfaces
670 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800671 """
672 if self.handle:
673 try:
674 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700675 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800676 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800677 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800678 response = self.execute( cmd=cmd,
679 prompt="mininet>",
680 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700681
kelvin-onlaba1484582015-02-02 15:46:20 -0800682 # Determine hostintf and Oldswitchintf
683 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800684 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800685 print "cmd2= ", cmd
686 self.handle.sendline( cmd )
687 self.handle.expect( "mininet>" )
688
shahshreya73537862015-02-11 15:15:24 -0800689 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800690 cmd = "px ipaddr = hintf.IP()"
691 print "cmd3= ", cmd
692 self.handle.sendline( cmd )
693 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800694
695 cmd = "px macaddr = hintf.MAC()"
696 print "cmd3= ", cmd
697 self.handle.sendline( cmd )
698 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700699
kelvin-onlaba1484582015-02-02 15:46:20 -0800700 # Detach interface between oldSw-host
701 cmd = "px " + oldSw + ".detach( sintf )"
702 print "cmd4= ", cmd
703 self.handle.sendline( cmd )
704 self.handle.expect( "mininet>" )
705
706 # Add link between host-newSw
707 cmd = "py net.addLink(" + host + "," + newSw + ")"
708 print "cmd5= ", cmd
709 self.handle.sendline( cmd )
710 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700711
kelvin-onlaba1484582015-02-02 15:46:20 -0800712 # Determine hostintf and Newswitchintf
713 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800714 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800715 print "cmd6= ", cmd
716 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700717 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800718
719 # Attach interface between newSw-host
720 cmd = "px " + newSw + ".attach( sintf )"
721 print "cmd3= ", cmd
722 self.handle.sendline( cmd )
723 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700724
kelvin-onlaba1484582015-02-02 15:46:20 -0800725 # Set ipaddress of the host-newSw interface
726 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
727 print "cmd7 = ", cmd
728 self.handle.sendline( cmd )
729 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800730
731 # Set macaddress of the host-newSw interface
732 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
733 print "cmd8 = ", cmd
734 self.handle.sendline( cmd )
735 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700736
kelvin-onlaba1484582015-02-02 15:46:20 -0800737 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800738 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800739 self.handle.sendline( cmd )
740 self.handle.expect( "mininet>" )
741 print "output = ", self.handle.before
742
743 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800744 cmd = host + " ifconfig"
745 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800746 self.handle.sendline( cmd )
747 self.handle.expect( "mininet>" )
748 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700749
kelvin-onlaba1484582015-02-02 15:46:20 -0800750 return main.TRUE
751 except pexpect.EOF:
752 main.log.error( self.name + ": EOF exception found" )
753 main.log.error( self.name + ": " + self.handle.before )
754 return main.FALSE
755
Jon Hall7eb38402015-01-08 17:19:54 -0800756 def changeIP( self, host, intf, newIP, newNetmask ):
757 """
758 Changes the ip address of a host on the fly
759 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800760 if self.handle:
761 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800762 cmd = host + " ifconfig " + intf + " " + \
763 newIP + " " + 'netmask' + " " + newNetmask
764 self.handle.sendline( cmd )
765 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800766 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800767 main.log.info( "response = " + response )
768 main.log.info(
769 "Ip of host " +
770 host +
771 " changed to new IP " +
772 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800773 return main.TRUE
774 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800775 main.log.error( self.name + ": EOF exception found" )
776 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800777 return main.FALSE
778
Jon Hall7eb38402015-01-08 17:19:54 -0800779 def changeDefaultGateway( self, host, newGW ):
780 """
781 Changes the default gateway of a host
782 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800783 if self.handle:
784 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800785 cmd = host + " route add default gw " + newGW
786 self.handle.sendline( cmd )
787 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800788 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800789 main.log.info( "response = " + response )
790 main.log.info(
791 "Default gateway of host " +
792 host +
793 " changed to " +
794 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800795 return main.TRUE
796 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800797 main.log.error( self.name + ": EOF exception found" )
798 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800799 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800800
Jon Hall7eb38402015-01-08 17:19:54 -0800801 def addStaticMACAddress( self, host, GW, macaddr ):
802 """
Jon Hallefbd9792015-03-05 16:11:36 -0800803 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800804 if self.handle:
805 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800806 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
807 cmd = host + " arp -s " + GW + " " + macaddr
808 self.handle.sendline( cmd )
809 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800810 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800811 main.log.info( "response = " + response )
812 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800813 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800814 GW +
815 " changed to " +
816 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800817 return main.TRUE
818 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800819 main.log.error( self.name + ": EOF exception found" )
820 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800821 return main.FALSE
822
Jon Hall7eb38402015-01-08 17:19:54 -0800823 def verifyStaticGWandMAC( self, host ):
824 """
825 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800826 if self.handle:
827 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800828 # h1 arp -an
829 cmd = host + " arp -an "
830 self.handle.sendline( cmd )
831 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800832 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800833 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800834 return main.TRUE
835 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800836 main.log.error( self.name + ": EOF exception found" )
837 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800838 return main.FALSE
839
Jon Hall7eb38402015-01-08 17:19:54 -0800840 def getMacAddress( self, host ):
841 """
842 Verifies the host's ip configured or not."""
843 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700844 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800845 response = self.execute(
846 cmd=host +
847 " ifconfig",
848 prompt="mininet>",
849 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800850 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800851 main.log.error( self.name + ": EOF exception found" )
852 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700853 main.cleanup()
854 main.exit()
adminbae64d82013-08-01 10:50:15 -0700855
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700856 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800857 macAddressSearch = re.search( pattern, response, re.I )
858 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800859 main.log.info(
860 self.name +
861 ": Mac-Address of Host " +
862 host +
863 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800864 macAddress )
865 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700866 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800867 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700868
Jon Hall7eb38402015-01-08 17:19:54 -0800869 def getInterfaceMACAddress( self, host, interface ):
870 """
871 Return the IP address of the interface on the given host"""
872 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700873 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800874 response = self.execute( cmd=host + " ifconfig " + interface,
875 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800876 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800877 main.log.error( self.name + ": EOF exception found" )
878 main.log.error( self.name + ": " + self.handle.before )
879 main.cleanup()
880 main.exit()
881
882 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800883 macAddressSearch = re.search( pattern, response, re.I )
884 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800885 main.log.info( "No mac address found in %s" % response )
886 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800887 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800888 main.log.info(
889 "Mac-Address of " +
890 host +
891 ":" +
892 interface +
893 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800894 macAddress )
895 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800896 else:
897 main.log.error( "Connection failed to the host" )
898
899 def getIPAddress( self, host ):
900 """
901 Verifies the host's ip configured or not."""
902 if self.handle:
903 try:
904 response = self.execute(
905 cmd=host +
906 " ifconfig",
907 prompt="mininet>",
908 timeout=10 )
909 except pexpect.EOF:
910 main.log.error( self.name + ": EOF exception found" )
911 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700912 main.cleanup()
913 main.exit()
adminbae64d82013-08-01 10:50:15 -0700914
915 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800916 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800917 main.log.info(
918 self.name +
919 ": IP-Address of Host " +
920 host +
921 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800922 ipAddressSearch.group( 1 ) )
923 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800924 else:
925 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800926
Jon Hall7eb38402015-01-08 17:19:54 -0800927 def getSwitchDPID( self, switch ):
928 """
929 return the datapath ID of the switch"""
930 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700931 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700932 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800933 response = self.execute(
934 cmd=cmd,
935 prompt="mininet>",
936 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800937 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800938 main.log.error( self.name + ": EOF exception found" )
939 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700940 main.cleanup()
941 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800942 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800943 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700944 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800945 main.log.info(
946 "Couldn't find DPID for switch %s, found: %s" %
947 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700948 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800949 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700950 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800951 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700952
Jon Hall7eb38402015-01-08 17:19:54 -0800953 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700954 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800955 self.handle.sendline( "" )
956 self.expect( "mininet>" )
957 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700958 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800959 response = self.execute(
960 cmd=cmd,
961 prompt="mininet>",
962 timeout=10 )
963 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700964 response = self.handle.before
965 return response
966 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800967 main.log.error( self.name + ": EOF exception found" )
968 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700969 main.cleanup()
970 main.exit()
971
Jon Hall7eb38402015-01-08 17:19:54 -0800972 def getInterfaces( self, node ):
973 """
974 return information dict about interfaces connected to the node"""
975 if self.handle:
976 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800977 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700978 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700979 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800980 response = self.execute(
981 cmd=cmd,
982 prompt="mininet>",
983 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800984 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800985 main.log.error( self.name + ": EOF exception found" )
986 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700987 main.cleanup()
988 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700989 return response
990 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800991 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700992
Jon Hall7eb38402015-01-08 17:19:54 -0800993 def dump( self ):
994 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700995 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800996 response = self.execute(
997 cmd='dump',
998 prompt='mininet>',
999 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001000 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001001 main.log.error( self.name + ": EOF exception found" )
1002 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001003 main.cleanup()
1004 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001005 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001006
Jon Hall7eb38402015-01-08 17:19:54 -08001007 def intfs( self ):
1008 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001009 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001010 response = self.execute(
1011 cmd='intfs',
1012 prompt='mininet>',
1013 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001014 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001015 main.log.error( self.name + ": EOF exception found" )
1016 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001017 main.cleanup()
1018 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001019 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001020
Jon Hall7eb38402015-01-08 17:19:54 -08001021 def net( self ):
1022 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001023 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001024 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001025 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001026 main.log.error( self.name + ": EOF exception found" )
1027 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001028 main.cleanup()
1029 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001030 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001031
Jon Hallafa8a472015-06-12 14:02:42 -07001032 def links( self ):
1033 main.log.info( self.name + ": List network links" )
1034 try:
1035 response = self.execute( cmd='links', prompt='mininet>',
1036 timeout=10 )
1037 except pexpect.EOF:
1038 main.log.error( self.name + ": EOF exception found" )
1039 main.log.error( self.name + ": " + self.handle.before )
1040 main.cleanup()
1041 main.exit()
1042 return response
1043
GlennRC61321f22015-07-16 13:36:54 -07001044 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001045 '''
1046 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001047
kelvin-onlab7cce9382015-07-17 10:21:03 -07001048 @parm:
1049 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1050 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1051 '''
1052 for host1 in hosts:
1053 for host2 in hosts:
1054 if host1 != host2:
1055 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1056 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001057
1058 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001059 '''
1060 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1061 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001062
kelvin-onlab7cce9382015-07-17 10:21:03 -07001063 @parm:
1064 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1065 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1066 '''
1067 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1068 try:
1069 # Setup the mininet command
1070 cmd1 = 'iperf ' + host1 + " " + host2
1071 self.handle.sendline( cmd1 )
1072 outcome = self.handle.expect( "mininet>", timeout )
1073 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001074
kelvin-onlab7cce9382015-07-17 10:21:03 -07001075 # checks if there are results in the mininet response
1076 if "Results:" in response:
1077 main.log.report(self.name + ": iperf test completed")
1078 # parse the mn results
1079 response = response.split("\r\n")
1080 response = response[len(response)-2]
1081 response = response.split(": ")
1082 response = response[len(response)-1]
1083 response = response.replace("[", "")
1084 response = response.replace("]", "")
1085 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001086
kelvin-onlab7cce9382015-07-17 10:21:03 -07001087 # this is the bandwith two and from the two hosts
1088 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001089
kelvin-onlab7cce9382015-07-17 10:21:03 -07001090 # there should be two elements in the bandwidth list
1091 # ['host1 to host2', 'host2 to host1"]
1092 if len(bandwidth) == 2:
1093 main.log.report(self.name + ": iperf test successful")
1094 return main.TRUE
1095 else:
1096 main.log.error(self.name + ": invalid iperf results")
1097 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001098 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001099 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001100 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001101
GlennRC61321f22015-07-16 13:36:54 -07001102 except pexpect.TIMEOUT:
1103 main.log.error( self.name + ": TIMEOUT exception found")
1104 main.log.error( self.name + ": Exception: Cannot connect to iperf on port 5001" )
1105 return main.FALSE
1106
Jon Hallfbc828e2015-01-06 17:30:19 -08001107 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001108 main.log.error( self.name + ": EOF exception found" )
1109 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001110 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001111 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001112
1113 def iperfudpAll(self, hosts, bandwidth="10M"):
1114 '''
1115 Runs the iperfudp function with a given set of hosts and specified
1116 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001117
GlennRC61321f22015-07-16 13:36:54 -07001118 @param:
1119 bandwidth: the targeted bandwidth, in megabits ('M')
1120 '''
1121 for host1 in hosts:
1122 for host2 in hosts:
1123 if host1 != host2:
1124 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1125 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1126
1127 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1128
kelvin-onlab7cce9382015-07-17 10:21:03 -07001129 '''
1130 Creates an iperf UDP test with a specific bandwidth.
1131 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001132
kelvin-onlab7cce9382015-07-17 10:21:03 -07001133 @param:
1134 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1135 '''
1136 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1137 try:
1138 # setup the mininet command
1139 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1140 self.handle.sendline(cmd)
1141 self.handle.expect("mininet>")
1142 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001143
kelvin-onlab7cce9382015-07-17 10:21:03 -07001144 # check if there are in results in the mininet response
1145 if "Results:" in response:
1146 main.log.report(self.name + ": iperfudp test completed")
1147 # parse the results
1148 response = response.split("\r\n")
1149 response = response[len(response)-2]
1150 response = response.split(": ")
1151 response = response[len(response)-1]
1152 response = response.replace("[", "")
1153 response = response.replace("]", "")
1154 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001155
kelvin-onlab7cce9382015-07-17 10:21:03 -07001156 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001157
kelvin-onlab7cce9382015-07-17 10:21:03 -07001158 # check to see if there are at least three entries
1159 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1160 if len(mnBandwidth) == 3:
1161 # if one entry is blank then something is wrong
1162 for item in mnBandwidth:
1163 if item == "":
1164 main.log.error(self.name + ": Could not parse iperf output")
1165 main.log.error(self.name + ": invalid iperfudp results")
1166 return main.FALSE
1167 # otherwise results are vaild
1168 main.log.report(self.name + ": iperfudp test successful")
1169 return main.TRUE
1170 else:
1171 main.log.error(self.name + ": invalid iperfudp results")
1172 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001173
kelvin-onlab7cce9382015-07-17 10:21:03 -07001174 except pexpect.EOF:
1175 main.log.error( self.name + ": EOF exception found" )
1176 main.log.error( self.name + ": " + self.handle.before )
1177 main.cleanup()
1178 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001179
Jon Hall7eb38402015-01-08 17:19:54 -08001180 def nodes( self ):
1181 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001182 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001183 response = self.execute(
1184 cmd='nodes',
1185 prompt='mininet>',
1186 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001187 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001188 main.log.error( self.name + ": EOF exception found" )
1189 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001190 main.cleanup()
1191 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001192 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001193
Jon Hall7eb38402015-01-08 17:19:54 -08001194 def pingpair( self ):
1195 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001196 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001197 response = self.execute(
1198 cmd='pingpair',
1199 prompt='mininet>',
1200 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001201 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001202 main.log.error( self.name + ": EOF exception found" )
1203 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001204 main.cleanup()
1205 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001206
Jon Hall7eb38402015-01-08 17:19:54 -08001207 if re.search( ',\s0\%\spacket\sloss', response ):
1208 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001209 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001210 else:
1211 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001212 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001213
Jon Hall7eb38402015-01-08 17:19:54 -08001214 def link( self, **linkargs ):
1215 """
1216 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001217 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001218 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1219 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1220 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1221 main.log.info(
1222 "Bring link between '" +
1223 end1 +
1224 "' and '" +
1225 end2 +
1226 "' '" +
1227 option +
1228 "'" )
1229 command = "link " + \
1230 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001231 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001232 self.handle.sendline( command )
1233 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001234 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001235 main.log.error( self.name + ": EOF exception found" )
1236 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001237 main.cleanup()
1238 main.exit()
adminbae64d82013-08-01 10:50:15 -07001239 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001240
pingping-lin8244a3b2015-09-16 13:36:56 -07001241 def switch( self, **switchargs ):
1242 """
1243 start/stop a switch
1244 """
1245 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1246 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1247 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1248 command = "switch " + str( sw ) + " " + str( option )
1249 main.log.info( command )
1250 try:
1251 self.handle.sendline( command )
1252 self.handle.expect( "mininet>" )
1253 except pexpect.TIMEOUT:
1254 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1255 main.cleanup()
1256 main.exit()
1257 except pexpect.EOF:
1258 main.log.error( self.name + ": EOF exception found" )
1259 main.log.error( self.name + ": " + self.handle.before )
1260 main.cleanup()
1261 main.exit()
1262 return main.TRUE
1263
Jon Hall7eb38402015-01-08 17:19:54 -08001264 def yank( self, **yankargs ):
1265 """
1266 yank a mininet switch interface to a host"""
1267 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001268 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001269 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1270 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1271 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001272 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001273 response = self.execute(
1274 cmd=command,
1275 prompt="mininet>",
1276 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001277 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001278 main.log.error( self.name + ": EOF exception found" )
1279 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001280 main.cleanup()
1281 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001282 return main.TRUE
1283
Jon Hall7eb38402015-01-08 17:19:54 -08001284 def plug( self, **plugargs ):
1285 """
1286 plug the yanked mininet switch interface to a switch"""
1287 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001288 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001289 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1290 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1291 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001292 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001293 response = self.execute(
1294 cmd=command,
1295 prompt="mininet>",
1296 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001297 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001298 main.log.error( self.name + ": EOF exception found" )
1299 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001300 main.cleanup()
1301 main.exit()
adminbae64d82013-08-01 10:50:15 -07001302 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001303
Jon Hall7eb38402015-01-08 17:19:54 -08001304 def dpctl( self, **dpctlargs ):
1305 """
1306 Run dpctl command on all switches."""
1307 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001308 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001309 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1310 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1311 command = "dpctl " + cmd + " " + str( cmdargs )
1312 try:
1313 response = self.execute(
1314 cmd=command,
1315 prompt="mininet>",
1316 timeout=10 )
1317 except pexpect.EOF:
1318 main.log.error( self.name + ": EOF exception found" )
1319 main.log.error( self.name + ": " + self.handle.before )
1320 main.cleanup()
1321 main.exit()
1322 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001323
kelvin-onlabd3b64892015-01-20 13:26:24 -08001324 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001325 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001326 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001327 fileInput = path + '/lib/Mininet/INSTALL'
1328 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001329 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001330 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001331 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001332 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001333 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001334 return version
adminbae64d82013-08-01 10:50:15 -07001335
kelvin-onlabd3b64892015-01-20 13:26:24 -08001336 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001337 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001338 Parameters:
1339 sw: The name of an OVS switch. Example "s1"
1340 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001341 The output of the command from the mininet cli
1342 or main.FALSE on timeout"""
1343 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001344 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001345 response = self.execute(
1346 cmd=command,
1347 prompt="mininet>",
1348 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001349 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001350 return response
admin2a9548d2014-06-17 14:08:07 -07001351 else:
1352 return main.FALSE
1353 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001354 main.log.error( self.name + ": EOF exception found" )
1355 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001356 main.cleanup()
1357 main.exit()
adminbae64d82013-08-01 10:50:15 -07001358
Charles Chan029be652015-08-24 01:46:10 +08001359 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001360 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001361 Description:
1362 Assign switches to the controllers ( for ovs use only )
1363 Required:
1364 sw - Name of the switch. This can be a list or a string.
1365 ip - Ip addresses of controllers. This can be a list or a string.
1366 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001367 port - ONOS use port 6653, if no list of ports is passed, then
1368 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001369 ptcp - ptcp number, This can be a string or a list that has
1370 the same length as switch. This is optional and not required
1371 when using ovs switches.
1372 NOTE: If switches and ptcp are given in a list type they should have the
1373 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1374 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001375
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001376 Return:
1377 Returns main.TRUE if mininet correctly assigned switches to
1378 controllers, otherwise it will return main.FALSE or an appropriate
1379 exception(s)
1380 """
1381 assignResult = main.TRUE
1382 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001383 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001384 command = "sh ovs-vsctl set-controller "
1385 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001386 try:
1387 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001388 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001389 if isinstance( port, types.StringType ) or \
1390 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001391 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001392 elif isinstance( port, types.ListType ):
1393 main.log.error( self.name + ": Only one controller " +
1394 "assigned and a list of ports has" +
1395 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001396 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001397 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001398 main.log.error( self.name + ": Invalid controller port " +
1399 "number. Please specify correct " +
1400 "controller port" )
1401 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001402
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001403 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001404 if isinstance( port, types.StringType ) or \
1405 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001406 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001407 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1408 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001409 elif isinstance( port, types.ListType ):
1410 if ( len( ip ) != len( port ) ):
1411 main.log.error( self.name + ": Port list = " +
1412 str( len( port ) ) +
1413 "should be the same as controller" +
1414 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001415 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001416 else:
1417 onosIp = ""
1418 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001419 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1420 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001421 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001422 main.log.error( self.name + ": Invalid controller port " +
1423 "number. Please specify correct " +
1424 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001425 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001426 else:
1427 main.log.error( self.name + ": Invalid ip address" )
1428 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001429
1430 if isinstance( sw, types.StringType ):
1431 command += sw + " "
1432 if ptcp:
1433 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001434 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001435 elif isinstance( ptcp, types.ListType ):
1436 main.log.error( self.name + ": Only one switch is " +
1437 "being set and multiple PTCP is " +
1438 "being passed " )
1439 else:
1440 main.log.error( self.name + ": Invalid PTCP" )
1441 ptcp = ""
1442 command += onosIp
1443 commandList.append( command )
1444
1445 elif isinstance( sw, types.ListType ):
1446 if ptcp:
1447 if isinstance( ptcp, types.ListType ):
1448 if len( ptcp ) != len( sw ):
1449 main.log.error( self.name + ": PTCP length = " +
1450 str( len( ptcp ) ) +
1451 " is not the same as switch" +
1452 " length = " +
1453 str( len( sw ) ) )
1454 return main.FALSE
1455 else:
1456 for switch, ptcpNum in zip( sw, ptcp ):
1457 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001458 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001459 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001460 tempCmd += onosIp
1461 commandList.append( tempCmd )
1462 else:
1463 main.log.error( self.name + ": Invalid PTCP" )
1464 return main.FALSE
1465 else:
1466 for switch in sw:
1467 tempCmd = "sh ovs-vsctl set-controller "
1468 tempCmd += switch + " " + onosIp
1469 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001470 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001471 main.log.error( self.name + ": Invalid switch type " )
1472 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001473
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001474 for cmd in commandList:
1475 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001476 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001477 except pexpect.TIMEOUT:
1478 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1479 return main.FALSE
1480 except pexpect.EOF:
1481 main.log.error( self.name + ": EOF exception found" )
1482 main.log.error( self.name + ": " + self.handle.before )
1483 main.cleanup()
1484 main.exit()
1485 return main.TRUE
1486 except Exception:
1487 main.log.exception( self.name + ": Uncaught exception!" )
1488 main.cleanup()
1489 main.exit()
adminbae64d82013-08-01 10:50:15 -07001490
kelvin-onlabd3b64892015-01-20 13:26:24 -08001491 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001492 """
1493 Removes the controller target from sw"""
1494 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001495 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001496 response = self.execute(
1497 cmd=command,
1498 prompt="mininet>",
1499 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001500 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001501 main.log.error( self.name + ": EOF exception found" )
1502 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001503 main.cleanup()
1504 main.exit()
1505 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001506 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001507
kelvin-onlabd3b64892015-01-20 13:26:24 -08001508 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001509 """
Jon Hallb1290e82014-11-18 16:17:48 -05001510 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001511 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001512 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001513 NOTE: cannot currently specify what type of switch
1514 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001515 sw = name of the new switch as a string
1516 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001517 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001518 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001519 """
1520 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001521 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001522 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001523 response = self.execute(
1524 cmd=command,
1525 prompt="mininet>",
1526 timeout=10 )
1527 if re.search( "already exists!", response ):
1528 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001529 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001530 elif re.search( "Error", response ):
1531 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001532 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001533 elif re.search( "usage:", response ):
1534 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001535 return main.FALSE
1536 else:
1537 return main.TRUE
1538 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001539 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001540 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001541 main.cleanup()
1542 main.exit()
1543
kelvin-onlabd3b64892015-01-20 13:26:24 -08001544 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001545 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001546 delete a switch from the mininet topology
1547 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001548 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001549 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001550 sw = name of the switch as a string
1551 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001552 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001553 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001554 response = self.execute(
1555 cmd=command,
1556 prompt="mininet>",
1557 timeout=10 )
1558 if re.search( "no switch named", response ):
1559 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001560 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001561 elif re.search( "Error", response ):
1562 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001563 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001564 elif re.search( "usage:", response ):
1565 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001566 return main.FALSE
1567 else:
1568 return main.TRUE
1569 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001570 main.log.error( self.name + ": EOF exception found" )
1571 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001572 main.cleanup()
1573 main.exit()
1574
kelvin-onlabd3b64892015-01-20 13:26:24 -08001575 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001576 """
1577 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001578 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001579 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001580 NOTE: cannot currently specify what type of link
1581 required params:
1582 node1 = the string node name of the first endpoint of the link
1583 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001584 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001585 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001586 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001587 response = self.execute(
1588 cmd=command,
1589 prompt="mininet>",
1590 timeout=10 )
1591 if re.search( "doesnt exist!", response ):
1592 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001593 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001594 elif re.search( "Error", response ):
1595 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001596 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001597 elif re.search( "usage:", response ):
1598 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001599 return main.FALSE
1600 else:
1601 return main.TRUE
1602 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001603 main.log.error( self.name + ": EOF exception found" )
1604 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001605 main.cleanup()
1606 main.exit()
1607
kelvin-onlabd3b64892015-01-20 13:26:24 -08001608 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001609 """
1610 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001611 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001612 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001613 required params:
1614 node1 = the string node name of the first endpoint of the link
1615 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001616 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001617 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001618 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001619 response = self.execute(
1620 cmd=command,
1621 prompt="mininet>",
1622 timeout=10 )
1623 if re.search( "no node named", response ):
1624 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001625 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001626 elif re.search( "Error", 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( "usage:", response ):
1630 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001631 return main.FALSE
1632 else:
1633 return main.TRUE
1634 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001635 main.log.error( self.name + ": EOF exception found" )
1636 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001637 main.cleanup()
1638 main.exit()
1639
kelvin-onlabd3b64892015-01-20 13:26:24 -08001640 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001641 """
Jon Hallb1290e82014-11-18 16:17:48 -05001642 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001643 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001644 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001645 NOTE: cannot currently specify what type of host
1646 required params:
1647 hostname = the string hostname
1648 optional key-value params
1649 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001650 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001651 """
1652 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001653 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001654 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001655 response = self.execute(
1656 cmd=command,
1657 prompt="mininet>",
1658 timeout=10 )
1659 if re.search( "already exists!", response ):
1660 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001661 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001662 elif re.search( "doesnt exists!", response ):
1663 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001664 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001665 elif re.search( "Error", response ):
1666 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001667 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001668 elif re.search( "usage:", response ):
1669 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001670 return main.FALSE
1671 else:
1672 return main.TRUE
1673 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001674 main.log.error( self.name + ": EOF exception found" )
1675 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001676 main.cleanup()
1677 main.exit()
1678
kelvin-onlabd3b64892015-01-20 13:26:24 -08001679 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001680 """
1681 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001682 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001683 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001684 NOTE: this uses a custom mn function
1685 required params:
1686 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001687 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001688 command = "delhost " + str( hostname )
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( "no host named", 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( "Error", 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( "usage:", response ):
1701 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001702 return main.FALSE
1703 else:
1704 return main.TRUE
1705 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001706 main.log.error( self.name + ": EOF exception found" )
1707 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001708 main.cleanup()
1709 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001710
Jon Hall7eb38402015-01-08 17:19:54 -08001711 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001712 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001713 Called at the end of the test to stop the mininet and
1714 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001715 """
Jon Halld80cc142015-07-06 13:36:05 -07001716 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001717 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001718 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001719 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001720 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001721 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001722 elif i == 1:
1723 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001724 # print "Disconnecting Mininet"
1725 if self.handle:
1726 self.handle.sendline( "exit" )
1727 self.handle.expect( "exit" )
1728 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001729 else:
1730 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001731 return response
1732
Jon Halld80cc142015-07-06 13:36:05 -07001733 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001734 """
Jon Hall21270ac2015-02-16 17:59:55 -08001735 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001736 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001737 main.FALSE if the pexpect handle does not exist.
1738
Jon Halld61331b2015-02-17 16:35:47 -08001739 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001740 """
Jon Halld61331b2015-02-17 16:35:47 -08001741 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001742 response = ''
1743 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001744 try:
Jon Halld80cc142015-07-06 13:36:05 -07001745 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001746 i = self.handle.expect( [ 'mininet>',
1747 '\$',
1748 pexpect.EOF,
1749 pexpect.TIMEOUT ],
1750 timeout )
1751 if i == 0:
1752 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001753 response = self.execute(
1754 cmd="exit",
1755 prompt="(.*)",
1756 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001757 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001758 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001759 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001760
kelvin-onlab56a3f462015-02-06 14:04:43 -08001761 if i == 1:
1762 main.log.info( " Mininet trying to exit while not " +
1763 "in the mininet prompt" )
1764 elif i == 2:
1765 main.log.error( "Something went wrong exiting mininet" )
1766 elif i == 3: # timeout
1767 main.log.error( "Something went wrong exiting mininet " +
1768 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001769
Hari Krishnab35c6d02015-03-18 11:13:51 -07001770 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001771 self.handle.sendline( "" )
1772 self.handle.expect( '\$' )
1773 self.handle.sendline(
1774 "sudo kill -9 \`ps -ef | grep \"" +
1775 fileName +
1776 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001777 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001778 main.log.error( self.name + ": EOF exception found" )
1779 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001780 main.cleanup()
1781 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001782 else:
1783 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001784 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001785 return response
1786
Jon Halla5cb3412015-08-18 14:08:22 -07001787 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001788 """
1789 Description:
1790 Sends arp message from mininet host for hosts discovery
1791 Required:
1792 host - hosts name
1793 Optional:
1794 ip - ip address that does not exist in the network so there would
1795 be no reply.
1796 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001797 if ethDevice:
1798 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001799 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001800 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001801 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001802 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001803 i = self.handle.expect( [ "mininet>", "arping: " ] )
1804 if i == 0:
1805 return main.TRUE
1806 elif i == 1:
1807 response = self.handle.before + self.handle.after
1808 self.handle.expect( "mininet>" )
1809 response += self.handle.before + self.handle.after
1810 main.log.warn( "Error sending arping, output was: " +
1811 response )
1812 return main.FALSE
1813 except pexpect.TIMEOUT:
1814 main.log.error( self.name + ": TIMEOUT exception found" )
1815 main.log.warn( self.handle.before )
1816 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001817 except pexpect.EOF:
1818 main.log.error( self.name + ": EOF exception found" )
1819 main.log.error( self.name + ": " + self.handle.before )
1820 main.cleanup()
1821 main.exit()
admin07529932013-11-22 14:58:28 -08001822
Jon Hall7eb38402015-01-08 17:19:54 -08001823 def decToHex( self, num ):
1824 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001825
Jon Hall7eb38402015-01-08 17:19:54 -08001826 def getSwitchFlowCount( self, switch ):
1827 """
1828 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001829 if self.handle:
1830 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1831 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001832 response = self.execute(
1833 cmd=cmd,
1834 prompt="mininet>",
1835 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001836 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001837 main.log.error( self.name + ": EOF exception found" )
1838 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001839 main.cleanup()
1840 main.exit()
1841 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001842 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001843 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001844 main.log.info(
1845 "Couldn't find flows on switch %s, found: %s" %
1846 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001847 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001848 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001849 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001850 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001851
kelvin-onlabd3b64892015-01-20 13:26:24 -08001852 def checkFlows( self, sw, dumpFormat=None ):
1853 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001854 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001855 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001856 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001857 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001858 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001859 response = self.execute(
1860 cmd=command,
1861 prompt="mininet>",
1862 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001863 return response
1864 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001865 main.log.error( self.name + ": EOF exception found" )
1866 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001867 main.cleanup()
1868 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001869
Jon Hall9043c902015-07-30 14:23:44 -07001870 def getFlowTable( self, protoVersion, sw ):
1871 """
1872 Returns certain fields of an OVS flow table. Will force output to
1873 either OF 1.0 or 1.3 format for consistency.
1874
1875 TODO add option to look at cookies. ignoring them for now
1876
1877 NOTE: Use format to force consistent flow table output across
1878 versions
1879 """
1880 try:
1881 self.handle.sendline( "" )
1882 self.handle.expect( "mininet>" )
1883 command = "sh ovs-ofctl dump-flows " + sw
1884 if protoVersion == 1.0:
1885 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\
1886 " print $1 $3 $6 $7 $8}' | "
1887 elif protoVersion == 1.3:
1888 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\
1889 " print $1 $3 $6 $7}' | "
1890 else:
1891 main.log.error(
1892 "Unknown protoVersion in getFlowTable(). given: (" +
1893 str( type( protoVersion ) ) +
1894 ") '" + str( protoVersion ) + "'" )
1895 return None
1896 command += "cut -d ',' -f 2- | sort -n -k1 -r"
1897 self.handle.sendline( command )
1898 self.handle.expect( "sort" )
1899 self.handle.expect( "OFPST_FLOW" )
1900 response = self.handle.before
1901 return response
1902 except pexpect.EOF:
1903 main.log.error( self.name + ": EOF exception found" )
1904 main.log.error( self.name + ": " + self.handle.before )
1905 main.cleanup()
1906 main.exit()
1907 except pexpect.TIMEOUT:
1908 main.log.exception( self.name + ": Timeout exception: " )
1909 return None
1910
1911 def flowComp( self, flow1, flow2 ):
1912 if flow1 == flow2:
1913 return main.TRUE
1914 else:
1915 main.log.info( "Flow tables do not match, printing tables:" )
1916 main.log.info( "Flow Table 1:" )
1917 main.log.info( flow1 )
1918 main.log.info( "Flow Table 2:" )
1919 main.log.info( flow2 )
1920 return main.FALSE
1921
Charles Chan029be652015-08-24 01:46:10 +08001922 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001923 """
Jon Hallefbd9792015-03-05 16:11:36 -08001924 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001925 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001926 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001927 self.handle.sendline( "" )
1928 self.handle.expect( "mininet>" )
1929 self.handle.sendline(
1930 "sh sudo tcpdump -n -i " +
1931 intf +
1932 " " +
1933 port +
1934 " -w " +
1935 filename.strip() +
1936 " &" )
1937 self.handle.sendline( "" )
1938 i = self.handle.expect( [ 'No\ssuch\device',
1939 'listening\son',
1940 pexpect.TIMEOUT,
1941 "mininet>" ],
1942 timeout=10 )
1943 main.log.warn( self.handle.before + self.handle.after )
1944 self.handle.sendline( "" )
1945 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001946 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001947 main.log.error(
1948 self.name +
1949 ": tcpdump - No such device exists. " +
1950 "tcpdump attempted on: " +
1951 intf )
admin2a9548d2014-06-17 14:08:07 -07001952 return main.FALSE
1953 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001954 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001955 return main.TRUE
1956 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001957 main.log.error(
1958 self.name +
1959 ": tcpdump command timed out! Check interface name," +
1960 " given interface was: " +
1961 intf )
admin2a9548d2014-06-17 14:08:07 -07001962 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001963 elif i == 3:
1964 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001965 return main.TRUE
1966 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001967 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001968 return main.FALSE
1969 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001970 main.log.error( self.name + ": EOF exception found" )
1971 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001972 main.cleanup()
1973 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001974 except Exception:
1975 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001976 main.cleanup()
1977 main.exit()
1978
kelvin-onlabd3b64892015-01-20 13:26:24 -08001979 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001980 """
1981 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001982 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001983 self.handle.sendline( "sh sudo pkill tcpdump" )
1984 self.handle.expect( "mininet>" )
1985 self.handle.sendline( "" )
1986 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001987 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001988 main.log.error( self.name + ": EOF exception found" )
1989 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001990 main.cleanup()
1991 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001992 except Exception:
1993 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001994 main.cleanup()
1995 main.exit()
1996
Jon Halld80cc142015-07-06 13:36:05 -07001997 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001998 """
1999 Read ports from a Mininet switch.
2000
2001 Returns a json structure containing information about the
2002 ports of the given switch.
2003 """
2004 response = self.getInterfaces( nodeName )
2005 # TODO: Sanity check on response. log if no such switch exists
2006 ports = []
2007 for line in response.split( "\n" ):
2008 if not line.startswith( "name=" ):
2009 continue
2010 portVars = {}
2011 for var in line.split( "," ):
2012 key, value = var.split( "=" )
2013 portVars[ key ] = value
2014 isUp = portVars.pop( 'enabled', "True" )
2015 isUp = "True" in isUp
2016 if verbose:
2017 main.log.info( "Reading switch port %s(%s)" %
2018 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2019 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002020 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002021 mac = None
2022 ips = []
2023 ip = portVars[ 'ip' ]
2024 if ip == 'None':
2025 ip = None
2026 ips.append( ip )
2027 name = portVars[ 'name' ]
2028 if name == 'None':
2029 name = None
2030 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2031 if name == 'lo':
2032 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2033 else:
2034 portNo = re.search( portRe, name ).group( 'port' )
2035 ports.append( { 'of_port': portNo,
2036 'mac': str( mac ).replace( '\'', '' ),
2037 'name': name,
2038 'ips': ips,
2039 'enabled': isUp } )
2040 return ports
2041
Jon Halld80cc142015-07-06 13:36:05 -07002042 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002043 """
2044 Read switches from Mininet.
2045
2046 Returns a dictionary whose keys are the switch names and the value is
2047 a dictionary containing information about the switch.
2048 """
Jon Halla22481b2015-07-28 17:46:01 -07002049 # NOTE: To support new Mininet switch classes, just append the new
2050 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002051
Jon Halla22481b2015-07-28 17:46:01 -07002052 # Regex patterns to parse 'dump' output
2053 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002054 # <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 -07002055 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002056 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2057 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2058 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2059 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2060 swRE = r"<(?P<class>" + switchClasses + r")" +\
2061 r"(?P<options>\{.*\})?\s" +\
2062 r"(?P<name>[^:]+)\:\s" +\
2063 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2064 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002065 # Update mn port info
2066 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002067 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002068 dump = self.dump().split( "\n" )
2069 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002070 result = re.search( swRE, line, re.I )
2071 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002072 name = result.group( 'name' )
2073 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002074 pid = result.group( 'pid' )
2075 swClass = result.group( 'class' )
2076 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002077 if verbose:
2078 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2079 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002080 output[ name ] = { "dpid": dpid,
2081 "ports": ports,
2082 "swClass": swClass,
2083 "pid": pid,
2084 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002085 return output
2086
Jon Halld80cc142015-07-06 13:36:05 -07002087 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002088 """
2089 Read hosts from Mininet.
2090
2091 Returns a dictionary whose keys are the host names and the value is
2092 a dictionary containing information about the host.
2093 """
2094 # Regex patterns to parse dump output
2095 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002096 # <Host h1: pid=12725>
2097 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2098 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2099 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002100 # NOTE: Does not correctly match hosts with multi-links
2101 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2102 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002103 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002104 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002105 # update mn port info
2106 self.update()
2107 # Get mininet dump
2108 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002109 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002110 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002111 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002112 result = re.search( hostRE, line )
2113 name = result.group( 'name' )
2114 interfaces = []
2115 response = self.getInterfaces( name )
2116 # Populate interface info
2117 for line in response.split( "\n" ):
2118 if line.startswith( "name=" ):
2119 portVars = {}
2120 for var in line.split( "," ):
2121 key, value = var.split( "=" )
2122 portVars[ key ] = value
2123 isUp = portVars.pop( 'enabled', "True" )
2124 isUp = "True" in isUp
2125 if verbose:
2126 main.log.info( "Reading host port %s(%s)" %
2127 ( portVars[ 'name' ],
2128 portVars[ 'mac' ] ) )
2129 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002130 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002131 mac = None
2132 ips = []
2133 ip = portVars[ 'ip' ]
2134 if ip == 'None':
2135 ip = None
2136 ips.append( ip )
2137 intfName = portVars[ 'name' ]
2138 if name == 'None':
2139 name = None
2140 interfaces.append( {
2141 "name": intfName,
2142 "ips": ips,
2143 "mac": str( mac ),
2144 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002145 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002146 return hosts
2147
2148 def getLinks( self ):
2149 """
2150 Gathers information about current Mininet links. These links may not
2151 be up if one of the ports is down.
2152
2153 Returns a list of dictionaries with link endpoints.
2154
2155 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002156 { 'node1': str( node1 name )
2157 'node2': str( node2 name )
2158 'port1': str( port1 of_port )
2159 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002160 Note: The port number returned is the eth#, not necessarily the of_port
2161 number. In Mininet, for OVS switch, these should be the same. For
2162 hosts, this is just the eth#.
2163 """
2164 self.update()
2165 response = self.links().split( '\n' )
2166
2167 # Examples:
2168 # s1-eth3<->s2-eth1 (OK OK)
2169 # s13-eth3<->h27-eth0 (OK OK)
2170 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2171 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2172 links = []
2173 for line in response:
2174 match = re.search( linkRE, line )
2175 if match:
2176 node1 = match.group( 'node1' )
2177 node2 = match.group( 'node2' )
2178 port1 = match.group( 'port1' )
2179 port2 = match.group( 'port2' )
2180 links.append( { 'node1': node1,
2181 'node2': node2,
2182 'port1': port1,
2183 'port2': port2 } )
2184 return links
2185
2186 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002187 """
2188 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002189 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002190
Jon Hallafa8a472015-06-12 14:02:42 -07002191 Dependencies:
2192 1. numpy - "sudo pip install numpy"
2193 """
2194 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002195 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002196 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002197 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002198 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002199 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002200 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002201 main.log.error(
2202 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002203 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002204 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002205 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002206 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002207 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002208 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002209 onosDPIDs.append(
2210 switch[ 'id' ].replace(
2211 ":",
2212 '' ).replace(
2213 "of",
2214 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002215 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002216
Jon Hall7eb38402015-01-08 17:19:54 -08002217 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002218 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002219 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002220 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002221 main.log.error( str( list1 ) )
2222 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002223 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002224 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002225 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002226 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002227 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002228
Jon Hall7eb38402015-01-08 17:19:54 -08002229 # FIXME: this does not look for extra ports in ONOS, only checks that
2230 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002231 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002232
Jon Hall7eb38402015-01-08 17:19:54 -08002233 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002234 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002235 mnPorts = []
2236 onosPorts = []
2237 switchResult = main.TRUE
2238 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002239 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002240 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002241 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002242 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002243 if onosSwitch[ 'device' ][ 'id' ].replace(
2244 ':',
2245 '' ).replace(
2246 "of",
2247 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002248 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002249 if port[ 'isEnabled' ]:
2250 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002251 # onosPorts.append( 'local' )
2252 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002253 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002254 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002255 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002256 mnPorts.sort( key=float )
2257 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002258
kelvin-onlabd3b64892015-01-20 13:26:24 -08002259 mnPortsLog = mnPorts
2260 onosPortsLog = onosPorts
2261 mnPorts = [ x for x in mnPorts ]
2262 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002263
Jon Hall7eb38402015-01-08 17:19:54 -08002264 # TODO: handle other reserved port numbers besides LOCAL
2265 # NOTE: Reserved ports
2266 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2267 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002268 for mnPort in mnPortsLog:
2269 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002270 # don't set results to true here as this is just one of
2271 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002272 mnPorts.remove( mnPort )
2273 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002274
Jon Hall7eb38402015-01-08 17:19:54 -08002275 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002276 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002277 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002278 if 65534 in mnPorts:
2279 mnPorts.remove( 65534 )
2280 if long( uint64( -2 ) ) in onosPorts:
2281 onosPorts.remove( long( uint64( -2 ) ) )
2282 if len( mnPorts ): # the ports of this switch don't match
2283 switchResult = main.FALSE
2284 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2285 if len( onosPorts ): # the ports of this switch don't match
2286 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002287 main.log.warn(
2288 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002289 str( onosPorts ) )
2290 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002291 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002292 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002293 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002294 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2295 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2296 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002297 finalResults = finalResults and portsResults
2298 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002299
Jon Hallafa8a472015-06-12 14:02:42 -07002300 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002301 """
2302 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002303 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002304
Jon Hallafa8a472015-06-12 14:02:42 -07002305 """
Jon Hall7eb38402015-01-08 17:19:54 -08002306 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002307 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002308 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002309
Jon Halld80cc142015-07-06 13:36:05 -07002310 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002311 for l in links:
2312 try:
2313 node1 = switches[ l[ 'node1' ] ]
2314 node2 = switches[ l[ 'node2' ] ]
2315 enabled = True
2316 for port in node1[ 'ports' ]:
2317 if port[ 'of_port' ] == l[ 'port1' ]:
2318 enabled = enabled and port[ 'enabled' ]
2319 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002320 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002321 enabled = enabled and port[ 'enabled' ]
2322 if enabled:
2323 mnLinks.append( l )
2324 except KeyError:
2325 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002326 if 2 * len( mnLinks ) == len( onos ):
2327 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002328 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002329 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002330 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002331 "Mininet has " + str( len( mnLinks ) ) +
2332 " bidirectional links and ONOS has " +
2333 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002334
Jon Hall7eb38402015-01-08 17:19:54 -08002335 # iterate through MN links and check if an ONOS link exists in
2336 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002337 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002338 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002339 node1 = None
2340 port1 = None
2341 node2 = None
2342 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002343 firstDir = main.FALSE
2344 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002345 for swName, switch in switches.iteritems():
2346 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002347 node1 = switch[ 'dpid' ]
2348 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002349 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002350 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002351 if node1 is not None and node2 is not None:
2352 break
Jon Hallafa8a472015-06-12 14:02:42 -07002353 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002354 node2 = switch[ 'dpid' ]
2355 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002356 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002357 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002358 if node1 is not None and node2 is not None:
2359 break
2360
kelvin-onlabd3b64892015-01-20 13:26:24 -08002361 for onosLink in onos:
2362 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002363 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002364 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002365 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002366 onosPort1 = onosLink[ 'src' ][ 'port' ]
2367 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002368
Jon Hall72cf1dc2014-10-20 21:04:50 -04002369 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002370 if str( onosNode1 ) == str( node1 ) and str(
2371 onosNode2 ) == str( node2 ):
2372 if int( onosPort1 ) == int( port1 ) and int(
2373 onosPort2 ) == int( port2 ):
2374 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002375 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002376 main.log.warn(
2377 'The port numbers do not match for ' +
2378 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002379 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002380 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002381 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002382 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002383 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002384
2385 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002386 elif ( str( onosNode1 ) == str( node2 ) and
2387 str( onosNode2 ) == str( node1 ) ):
2388 if ( int( onosPort1 ) == int( port2 )
2389 and int( onosPort2 ) == int( port1 ) ):
2390 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002391 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002392 main.log.warn(
2393 'The port numbers do not match for ' +
2394 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002395 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002396 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002397 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002398 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002399 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002400 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002401 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002402 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002403 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002404 'ONOS does not have the link %s/%s -> %s/%s' %
2405 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002406 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002407 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002408 'ONOS does not have the link %s/%s -> %s/%s' %
2409 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002410 linkResults = linkResults and firstDir and secondDir
2411 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002412
Jon Hallafa8a472015-06-12 14:02:42 -07002413 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002414 """
Jon Hallafa8a472015-06-12 14:02:42 -07002415 Compare mn and onos Hosts.
2416 Since Mininet hosts are quiet, ONOS will only know of them when they
2417 speak. For this reason, we will only check that the hosts in ONOS
2418 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002419
Jon Hallafa8a472015-06-12 14:02:42 -07002420 Arguments:
2421 hostsJson: parsed json object from the onos hosts api
2422 Returns:
2423 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002424 import json
2425 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002426 for onosHost in hostsJson:
2427 onosMAC = onosHost[ 'mac' ].lower()
2428 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002429 for mnHost, info in hosts.iteritems():
2430 for mnIntf in info[ 'interfaces' ]:
2431 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002432 match = True
2433 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002434 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002435 pass # all is well
2436 else:
2437 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002438 main.log.error( "ONOS host " +
2439 onosHost[ 'id' ] +
2440 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002441 str( onosHost[ 'ipAddresses' ] ) +
2442 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002443 str( ip ) +
2444 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002445 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002446 onosHost,
2447 sort_keys=True,
2448 indent=4,
2449 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002450 main.log.info( output )
2451 hostResults = main.FALSE
2452 if not match:
2453 hostResults = main.FALSE
2454 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2455 "corresponding Mininet host." )
2456 output = json.dumps( onosHost,
2457 sort_keys=True,
2458 indent=4,
2459 separators=( ',', ': ' ) )
2460 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002461 return hostResults
2462
Jon Hallafa8a472015-06-12 14:02:42 -07002463 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002464 """
2465 Returns a list of all hosts
2466 Don't ask questions just use it"""
2467 self.handle.sendline( "" )
2468 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002469
Jon Hall7eb38402015-01-08 17:19:54 -08002470 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2471 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002472
kelvin-onlabd3b64892015-01-20 13:26:24 -08002473 handlePy = self.handle.before
2474 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2475 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002476
Jon Hall7eb38402015-01-08 17:19:54 -08002477 self.handle.sendline( "" )
2478 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002479
kelvin-onlabd3b64892015-01-20 13:26:24 -08002480 hostStr = handlePy.replace( "]", "" )
2481 hostStr = hostStr.replace( "'", "" )
2482 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002483 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002484 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002485
kelvin-onlabd3b64892015-01-20 13:26:24 -08002486 return hostList
adminbae64d82013-08-01 10:50:15 -07002487
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002488 def getSwitch( self ):
2489 """
2490 Returns a list of all switches
2491 Again, don't ask question just use it...
2492 """
2493 # get host list...
2494 hostList = self.getHosts()
2495 # Make host set
2496 hostSet = set( hostList )
2497
2498 # Getting all the nodes in mininet
2499 self.handle.sendline( "" )
2500 self.handle.expect( "mininet>" )
2501
2502 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2503 self.handle.expect( "mininet>" )
2504
2505 handlePy = self.handle.before
2506 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2507 handlePy = handlePy.rstrip()
2508
2509 self.handle.sendline( "" )
2510 self.handle.expect( "mininet>" )
2511
2512 nodesStr = handlePy.replace( "]", "" )
2513 nodesStr = nodesStr.replace( "'", "" )
2514 nodesStr = nodesStr.replace( "[", "" )
2515 nodesStr = nodesStr.replace( " ", "" )
2516 nodesList = nodesStr.split( "," )
2517
2518 nodesSet = set( nodesList )
2519 # discarding default controller(s) node
2520 nodesSet.discard( 'c0' )
2521 nodesSet.discard( 'c1' )
2522 nodesSet.discard( 'c2' )
2523
2524 switchSet = nodesSet - hostSet
2525 switchList = list( switchSet )
2526
2527 return switchList
2528
Jon Hall7eb38402015-01-08 17:19:54 -08002529 def update( self ):
2530 """
2531 updates the port address and status information for
2532 each port in mn"""
2533 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002534 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002535 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002536 self.handle.sendline( "" )
2537 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002538
Jon Hall7eb38402015-01-08 17:19:54 -08002539 self.handle.sendline( "update" )
2540 self.handle.expect( "update" )
2541 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002542
Jon Hall7eb38402015-01-08 17:19:54 -08002543 self.handle.sendline( "" )
2544 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002545
Jon Hallb1290e82014-11-18 16:17:48 -05002546 return main.TRUE
2547 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002548 main.log.error( self.name + ": EOF exception found" )
2549 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002550 main.cleanup()
2551 main.exit()
2552
Jon Halld80cc142015-07-06 13:36:05 -07002553 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002554 """
2555 Add vlan tag to a host.
2556 Dependencies:
2557 This class depends on the "vlan" package
2558 $ sudo apt-get install vlan
2559 Configuration:
2560 Load the 8021q module into the kernel
2561 $sudo modprobe 8021q
2562
2563 To make this setup permanent:
2564 $ sudo su -c 'echo "8021q" >> /etc/modules'
2565 """
2566 if self.handle:
2567 try:
Jon Halld80cc142015-07-06 13:36:05 -07002568 # get the ip address of the host
2569 main.log.info( "Get the ip address of the host" )
2570 ipaddr = self.getIPAddress( host )
2571 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002572
Jon Halld80cc142015-07-06 13:36:05 -07002573 # remove IP from interface intf
2574 # Ex: h1 ifconfig h1-eth0 inet 0
2575 main.log.info( "Remove IP from interface " )
2576 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2577 self.handle.sendline( cmd2 )
2578 self.handle.expect( "mininet>" )
2579 response = self.handle.before
2580 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002581
Jon Halld80cc142015-07-06 13:36:05 -07002582 # create VLAN interface
2583 # Ex: h1 vconfig add h1-eth0 100
2584 main.log.info( "Create Vlan" )
2585 cmd3 = host + " vconfig add " + intf + " " + vlan
2586 self.handle.sendline( cmd3 )
2587 self.handle.expect( "mininet>" )
2588 response = self.handle.before
2589 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002590
Jon Halld80cc142015-07-06 13:36:05 -07002591 # assign the host's IP to the VLAN interface
2592 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2593 main.log.info( "Assign the host IP to the vlan interface" )
2594 vintf = intf + "." + vlan
2595 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2596 self.handle.sendline( cmd4 )
2597 self.handle.expect( "mininet>" )
2598 response = self.handle.before
2599 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002600
2601 return main.TRUE
2602 except pexpect.EOF:
2603 main.log.error( self.name + ": EOF exception found" )
2604 main.log.error( self.name + ": " + self.handle.before )
2605 return main.FALSE
2606
adminbae64d82013-08-01 10:50:15 -07002607if __name__ != "__main__":
2608 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002609 sys.modules[ __name__ ] = MininetCliDriver()