blob: 7a4605c2bfc75d545eed23e2365f6a3585695783 [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
Jon Halld80cc142015-07-06 13:36:05 -0700284 def pingall( self, 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
309 self.handle.sendline( "pingall" )
Jon Hall390696c2015-05-05 17:13:41 -0700310 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700311 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700312 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700313 pexpect.EOF,
314 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700315 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700316 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700317 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700318 response += self.handle.before
319 break
320 elif i == 1:
321 response += self.handle.before + self.handle.after
322 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700323 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700324 returnValue = main.FALSE
325 if shortCircuit:
326 main.log.error( self.name +
327 ": Aborting pingall - "
328 + str( failedPings ) +
329 " pings failed" )
330 break
Jon Hall390696c2015-05-05 17:13:41 -0700331 if ( time.time() - startTime ) > timeout:
332 returnValue = main.FALSE
333 main.log.error( self.name +
334 ": Aborting pingall - " +
335 "Function took too long " )
336 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700337 elif i == 2:
338 main.log.error( self.name +
339 ": EOF exception found" )
340 main.log.error( self.name + ": " +
341 self.handle.before )
342 main.cleanup()
343 main.exit()
344 elif i == 3:
345 response += self.handle.before
346 main.log.error( self.name +
347 ": TIMEOUT exception found" )
348 main.log.error( self.name +
349 ": " +
350 str( response ) )
351 # NOTE: Send ctrl-c to make sure pingall is done
352 self.handle.sendline( "\x03" )
353 self.handle.expect( "Interrupt" )
354 self.handle.expect( "mininet>" )
355 break
356 pattern = "Results\:"
357 main.log.info( "Pingall output: " + str( response ) )
358 if re.search( pattern, response ):
359 main.log.info( self.name + ": Pingall finished with "
360 + str( failedPings ) + " failed pings" )
361 return returnValue
362 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700363 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700364 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700365 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700366 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700367 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700368 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700369 main.log.error( self.name + ": Connection failed to the host" )
370 main.cleanup()
371 main.exit()
372 except pexpect.TIMEOUT:
373 if response:
374 main.log.info( "Pingall output: " + str( response ) )
375 main.log.error( self.name + ": pexpect.TIMEOUT found" )
376 return main.FALSE
377 except pexpect.EOF:
378 main.log.error( self.name + ": EOF exception found" )
379 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500380 main.cleanup()
381 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700382
Jon Hall7eb38402015-01-08 17:19:54 -0800383 def fpingHost( self, **pingParams ):
384 """
385 Uses the fping package for faster pinging...
386 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800387 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800388 command = args[ "SRC" ] + \
389 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
390 self.handle.sendline( command )
391 self.handle.expect(
392 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
393 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
394 response = self.handle.before
395 if re.search( ":\s-", response ):
396 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700397 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800398 elif re.search( ":\s\d{1,2}\.\d\d", response ):
399 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700400 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800401 main.log.info( self.name + ": Install fping on mininet machine... " )
402 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700403 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800404
Hari Krishna9592fc82015-07-31 15:11:15 -0700405 def pingallHosts( self, hostList ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400406 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700407 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700408
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400409 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700410 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700411
412 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400413 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700414
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400415 Returns main.FALSE if one or more of hosts specified
416 cannot reach each other"""
Hari Krishna9592fc82015-07-31 15:11:15 -0700417
418 cmd = " ping -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400419
420 try:
421 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700422
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400423 isReachable = main.TRUE
424
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400425 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700426 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400427 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700428 pingList = hostList[ :listIndex ] + \
429 hostList[ ( listIndex + 1 ): ]
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400430 for temp in pingList:
431 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700432 pingCmd = str( host ) + cmd + str( temp )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400433 self.handle.sendline( pingCmd )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700434 self.handle.expect( "mininet>" )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400435 response = self.handle.before
436 if re.search( ',\s0\%\spacket\sloss', response ):
Jon Halld80cc142015-07-06 13:36:05 -0700437 main.log.info( str( host ) + " -> " + str( temp ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400438 else:
Jon Halla5cb3412015-08-18 14:08:22 -0700439 main.log.warn(
Jon Halld80cc142015-07-06 13:36:05 -0700440 str( host ) + " -> X (" + str( temp ) + ") "
441 " Destination Unreachable" )
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400442 # One of the host to host pair is unreachable
443 isReachable = main.FALSE
kelvin-onlab2ff57022015-05-29 10:48:51 -0700444 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700445 except pexpect.TIMEOUT:
446 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700447 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400448 except pexpect.EOF:
449 main.log.error( self.name + ": EOF exception found" )
450 main.log.error( self.name + ": " + self.handle.before )
451 main.cleanup()
452 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700453 except Exception:
454 main.log.exception( self.name + ": Uncaught exception!" )
455 main.cleanup()
456 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400457
kelvin-onlab9b42b0a2015-08-05 14:43:58 -0700458 def pingIpv6Hosts(self, hostList, prefix='1000::'):
Hari Krishna9592fc82015-07-31 15:11:15 -0700459 """
460 IPv6 ping all hosts in hostList. If no prefix passed this will use
461 default prefix of 1000::
462
463 Returns main.TRUE if all hosts specified can reach each other
464
GlennRC2cf7d952015-09-11 16:32:13 -0700465 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700466 """
467 try:
468 main.log.info( "Testing reachability between specified IPv6 hosts" )
469 isReachable = main.TRUE
470 cmd = " ping6 -c 1 -i 1 -W 8 "
GlennRC2cf7d952015-09-11 16:32:13 -0700471 pingResponse = ""
Hari Krishna7d1eacf2015-09-14 09:32:21 -0700472 main.log.info("IPv6 Pingall output:")
Hari Krishna9592fc82015-07-31 15:11:15 -0700473 for host in hostList:
474 listIndex = hostList.index( host )
475 # List of hosts to ping other than itself
476 pingList = hostList[ :listIndex ] + \
477 hostList[ ( listIndex + 1 ): ]
478
GlennRC2cf7d952015-09-11 16:32:13 -0700479 pingResponse += str(str(host) + " -> ")
480
Hari Krishna9592fc82015-07-31 15:11:15 -0700481 for temp in pingList:
482 # Current host pings all other hosts specified
483 pingCmd = str( host ) + cmd + prefix + str( temp[1:] )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700484 self.handle.sendline( pingCmd )
485 self.handle.expect( "mininet>" )
Hari Krishna9592fc82015-07-31 15:11:15 -0700486 response = self.handle.before
487 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700488 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700489 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700490 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700491 # One of the host to host pair is unreachable
492 isReachable = main.FALSE
GlennRC2cf7d952015-09-11 16:32:13 -0700493 main.log.info(pingResponse)
494 pingResponse = ""
Hari Krishna9592fc82015-07-31 15:11:15 -0700495 return isReachable
496
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700497 except pexpect.TIMEOUT:
498 main.log.exception( self.name + ": TIMEOUT exception" )
499 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700500 except pexpect.EOF:
501 main.log.error( self.name + ": EOF exception found" )
502 main.log.error( self.name + ": " + self.handle.before )
503 main.cleanup()
504 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700505 except Exception:
506 main.log.exception( self.name + ": Uncaught exception!" )
507 main.cleanup()
508 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700509
Jon Hall7eb38402015-01-08 17:19:54 -0800510 def pingHost( self, **pingParams ):
511 """
512 Ping from one mininet host to another
513 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800514 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800515 command = args[ "SRC" ] + " ping " + \
516 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700517 try:
Jon Hall61282e32015-03-19 11:34:11 -0700518 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800519 self.handle.sendline( command )
520 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700521 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800522 main.log.error(
523 self.name +
524 ": timeout when waiting for response from mininet" )
525 main.log.error( "response: " + str( self.handle.before ) )
526 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700527 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800528 main.log.error(
529 self.name +
530 ": timeout when waiting for response from mininet" )
531 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700532 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700533 if re.search( ',\s0\%\spacket\sloss', response ):
534 main.log.info( self.name + ": no packets lost, host is reachable" )
535 return main.TRUE
536 else:
537 main.log.error(
538 self.name +
539 ": PACKET LOST, HOST IS NOT REACHABLE" )
540 return main.FALSE
541
Jon Hallfbc828e2015-01-06 17:30:19 -0800542 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800543 main.log.error( self.name + ": EOF exception found" )
544 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700545 main.cleanup()
546 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700547 except Exception:
548 main.log.exception( self.name + ": Uncaught exception!" )
549 main.cleanup()
550 main.exit()
551
552 def ping6pair( self, **pingParams ):
553 """
GlennRC2cf7d952015-09-11 16:32:13 -0700554 IPv6 Ping between a pair of mininet hosts
Hari Krishna012a1c12015-08-25 14:23:58 -0700555 Currently the only supported Params are: SRC , TARGET
556 FLOWLABEL and -I (src interface) will be added later after running some tests.
557 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
558 """
559 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
560 command = args[ "SRC" ] + " ping6 " + \
561 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
562 try:
563 main.log.info( "Sending: " + command )
564 self.handle.sendline( command )
565 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
566 if i == 1:
567 main.log.error(
568 self.name +
569 ": timeout when waiting for response from mininet" )
570 main.log.error( "response: " + str( self.handle.before ) )
571 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
572 if i == 1:
573 main.log.error(
574 self.name +
575 ": timeout when waiting for response from mininet" )
576 main.log.error( "response: " + str( self.handle.before ) )
577 response = self.handle.before
578 main.log.info( self.name + ": Ping Response: " + response )
579 if re.search( ',\s0\%\spacket\sloss', response ):
580 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700581 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700582 else:
583 main.log.error(
584 self.name +
585 ": PACKET LOST, HOST IS NOT REACHABLE" )
586 return main.FALSE
587
588 except pexpect.EOF:
589 main.log.error( self.name + ": EOF exception found" )
590 main.log.error( self.name + ": " + self.handle.before )
591 main.cleanup()
592 main.exit()
593 except Exception:
594 main.log.exception( self.name + ": Uncaught exception!" )
595 main.cleanup()
596 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800597
Jon Hall7eb38402015-01-08 17:19:54 -0800598 def checkIP( self, host ):
599 """
600 Verifies the host's ip configured or not."""
601 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700602 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800603 response = self.execute(
604 cmd=host +
605 " ifconfig",
606 prompt="mininet>",
607 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800609 main.log.error( self.name + ": EOF exception found" )
610 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700611 main.cleanup()
612 main.exit()
adminbae64d82013-08-01 10:50:15 -0700613
Jon Hall7eb38402015-01-08 17:19:54 -0800614 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800615 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
616 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
617 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
618 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
619 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800620 # pattern = "inet addr:10.0.0.6"
621 if re.search( pattern, response ):
622 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700623 return main.TRUE
624 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800625 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700626 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800627 else:
628 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800629
Jon Hall7eb38402015-01-08 17:19:54 -0800630 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800631 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700632 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800633 response = self.execute(
634 cmd="h1 /usr/sbin/sshd -D&",
635 prompt="mininet>",
636 timeout=10 )
637 response = self.execute(
638 cmd="h4 /usr/sbin/sshd -D&",
639 prompt="mininet>",
640 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700641 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800642 vars( self )[ key ] = connectargs[ key ]
643 response = self.execute(
644 cmd="xterm h1 h4 ",
645 prompt="mininet>",
646 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800647 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800648 main.log.error( self.name + ": EOF exception found" )
649 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700650 main.cleanup()
651 main.exit()
adminbae64d82013-08-01 10:50:15 -0700652 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800653 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700654 if self.flag == 0:
655 self.flag = 1
656 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800657 else:
adminbae64d82013-08-01 10:50:15 -0700658 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800659
kelvin-onlaba1484582015-02-02 15:46:20 -0800660 def moveHost( self, host, oldSw, newSw, ):
661 """
662 Moves a host from one switch to another on the fly
663 Note: The intf between host and oldSw when detached
664 using detach(), will still show up in the 'net'
665 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700666 ( which is correct behavior since the interfaces
667 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800668 """
669 if self.handle:
670 try:
671 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700672 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800673 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800674 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800675 response = self.execute( cmd=cmd,
676 prompt="mininet>",
677 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700678
kelvin-onlaba1484582015-02-02 15:46:20 -0800679 # Determine hostintf and Oldswitchintf
680 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800681 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800682 print "cmd2= ", cmd
683 self.handle.sendline( cmd )
684 self.handle.expect( "mininet>" )
685
shahshreya73537862015-02-11 15:15:24 -0800686 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800687 cmd = "px ipaddr = hintf.IP()"
688 print "cmd3= ", cmd
689 self.handle.sendline( cmd )
690 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800691
692 cmd = "px macaddr = hintf.MAC()"
693 print "cmd3= ", cmd
694 self.handle.sendline( cmd )
695 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700696
kelvin-onlaba1484582015-02-02 15:46:20 -0800697 # Detach interface between oldSw-host
698 cmd = "px " + oldSw + ".detach( sintf )"
699 print "cmd4= ", cmd
700 self.handle.sendline( cmd )
701 self.handle.expect( "mininet>" )
702
703 # Add link between host-newSw
704 cmd = "py net.addLink(" + host + "," + newSw + ")"
705 print "cmd5= ", cmd
706 self.handle.sendline( cmd )
707 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700708
kelvin-onlaba1484582015-02-02 15:46:20 -0800709 # Determine hostintf and Newswitchintf
710 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800711 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800712 print "cmd6= ", cmd
713 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700714 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800715
716 # Attach interface between newSw-host
717 cmd = "px " + newSw + ".attach( sintf )"
718 print "cmd3= ", cmd
719 self.handle.sendline( cmd )
720 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700721
kelvin-onlaba1484582015-02-02 15:46:20 -0800722 # Set ipaddress of the host-newSw interface
723 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
724 print "cmd7 = ", cmd
725 self.handle.sendline( cmd )
726 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800727
728 # Set macaddress of the host-newSw interface
729 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
730 print "cmd8 = ", cmd
731 self.handle.sendline( cmd )
732 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700733
kelvin-onlaba1484582015-02-02 15:46:20 -0800734 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800735 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800736 self.handle.sendline( cmd )
737 self.handle.expect( "mininet>" )
738 print "output = ", self.handle.before
739
740 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800741 cmd = host + " ifconfig"
742 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800743 self.handle.sendline( cmd )
744 self.handle.expect( "mininet>" )
745 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700746
kelvin-onlaba1484582015-02-02 15:46:20 -0800747 return main.TRUE
748 except pexpect.EOF:
749 main.log.error( self.name + ": EOF exception found" )
750 main.log.error( self.name + ": " + self.handle.before )
751 return main.FALSE
752
Jon Hall7eb38402015-01-08 17:19:54 -0800753 def changeIP( self, host, intf, newIP, newNetmask ):
754 """
755 Changes the ip address of a host on the fly
756 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800757 if self.handle:
758 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800759 cmd = host + " ifconfig " + intf + " " + \
760 newIP + " " + 'netmask' + " " + newNetmask
761 self.handle.sendline( cmd )
762 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800763 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800764 main.log.info( "response = " + response )
765 main.log.info(
766 "Ip of host " +
767 host +
768 " changed to new IP " +
769 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800770 return main.TRUE
771 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800772 main.log.error( self.name + ": EOF exception found" )
773 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800774 return main.FALSE
775
Jon Hall7eb38402015-01-08 17:19:54 -0800776 def changeDefaultGateway( self, host, newGW ):
777 """
778 Changes the default gateway of a host
779 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800780 if self.handle:
781 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800782 cmd = host + " route add default gw " + newGW
783 self.handle.sendline( cmd )
784 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800785 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800786 main.log.info( "response = " + response )
787 main.log.info(
788 "Default gateway of host " +
789 host +
790 " changed to " +
791 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800792 return main.TRUE
793 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800794 main.log.error( self.name + ": EOF exception found" )
795 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800796 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800797
Jon Hall7eb38402015-01-08 17:19:54 -0800798 def addStaticMACAddress( self, host, GW, macaddr ):
799 """
Jon Hallefbd9792015-03-05 16:11:36 -0800800 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800801 if self.handle:
802 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800803 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
804 cmd = host + " arp -s " + GW + " " + macaddr
805 self.handle.sendline( cmd )
806 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800807 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800808 main.log.info( "response = " + response )
809 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800810 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800811 GW +
812 " changed to " +
813 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800814 return main.TRUE
815 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800816 main.log.error( self.name + ": EOF exception found" )
817 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800818 return main.FALSE
819
Jon Hall7eb38402015-01-08 17:19:54 -0800820 def verifyStaticGWandMAC( self, host ):
821 """
822 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800823 if self.handle:
824 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800825 # h1 arp -an
826 cmd = host + " arp -an "
827 self.handle.sendline( cmd )
828 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800829 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800830 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800831 return main.TRUE
832 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800833 main.log.error( self.name + ": EOF exception found" )
834 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800835 return main.FALSE
836
Jon Hall7eb38402015-01-08 17:19:54 -0800837 def getMacAddress( self, host ):
838 """
839 Verifies the host's ip configured or not."""
840 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700841 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800842 response = self.execute(
843 cmd=host +
844 " ifconfig",
845 prompt="mininet>",
846 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800847 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800848 main.log.error( self.name + ": EOF exception found" )
849 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700850 main.cleanup()
851 main.exit()
adminbae64d82013-08-01 10:50:15 -0700852
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700853 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800854 macAddressSearch = re.search( pattern, response, re.I )
855 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800856 main.log.info(
857 self.name +
858 ": Mac-Address of Host " +
859 host +
860 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800861 macAddress )
862 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700863 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800864 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700865
Jon Hall7eb38402015-01-08 17:19:54 -0800866 def getInterfaceMACAddress( self, host, interface ):
867 """
868 Return the IP address of the interface on the given host"""
869 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700870 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800871 response = self.execute( cmd=host + " ifconfig " + interface,
872 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800873 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800874 main.log.error( self.name + ": EOF exception found" )
875 main.log.error( self.name + ": " + self.handle.before )
876 main.cleanup()
877 main.exit()
878
879 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800880 macAddressSearch = re.search( pattern, response, re.I )
881 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800882 main.log.info( "No mac address found in %s" % response )
883 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800884 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800885 main.log.info(
886 "Mac-Address of " +
887 host +
888 ":" +
889 interface +
890 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800891 macAddress )
892 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800893 else:
894 main.log.error( "Connection failed to the host" )
895
896 def getIPAddress( self, host ):
897 """
898 Verifies the host's ip configured or not."""
899 if self.handle:
900 try:
901 response = self.execute(
902 cmd=host +
903 " ifconfig",
904 prompt="mininet>",
905 timeout=10 )
906 except pexpect.EOF:
907 main.log.error( self.name + ": EOF exception found" )
908 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700909 main.cleanup()
910 main.exit()
adminbae64d82013-08-01 10:50:15 -0700911
912 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800913 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800914 main.log.info(
915 self.name +
916 ": IP-Address of Host " +
917 host +
918 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800919 ipAddressSearch.group( 1 ) )
920 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800921 else:
922 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800923
Jon Hall7eb38402015-01-08 17:19:54 -0800924 def getSwitchDPID( self, switch ):
925 """
926 return the datapath ID of the switch"""
927 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700928 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700929 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800930 response = self.execute(
931 cmd=cmd,
932 prompt="mininet>",
933 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800934 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800935 main.log.error( self.name + ": EOF exception found" )
936 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700937 main.cleanup()
938 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800939 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800940 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700941 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800942 main.log.info(
943 "Couldn't find DPID for switch %s, found: %s" %
944 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700945 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800946 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700947 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800948 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700949
Jon Hall7eb38402015-01-08 17:19:54 -0800950 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700951 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800952 self.handle.sendline( "" )
953 self.expect( "mininet>" )
954 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700955 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800956 response = self.execute(
957 cmd=cmd,
958 prompt="mininet>",
959 timeout=10 )
960 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700961 response = self.handle.before
962 return response
963 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800964 main.log.error( self.name + ": EOF exception found" )
965 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700966 main.cleanup()
967 main.exit()
968
Jon Hall7eb38402015-01-08 17:19:54 -0800969 def getInterfaces( self, node ):
970 """
971 return information dict about interfaces connected to the node"""
972 if self.handle:
973 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800974 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700975 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700976 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800977 response = self.execute(
978 cmd=cmd,
979 prompt="mininet>",
980 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800981 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800982 main.log.error( self.name + ": EOF exception found" )
983 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700984 main.cleanup()
985 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700986 return response
987 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800988 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700989
Jon Hall7eb38402015-01-08 17:19:54 -0800990 def dump( self ):
991 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700992 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800993 response = self.execute(
994 cmd='dump',
995 prompt='mininet>',
996 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800997 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800998 main.log.error( self.name + ": EOF exception found" )
999 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001000 main.cleanup()
1001 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001002 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001003
Jon Hall7eb38402015-01-08 17:19:54 -08001004 def intfs( self ):
1005 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001006 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001007 response = self.execute(
1008 cmd='intfs',
1009 prompt='mininet>',
1010 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001011 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001012 main.log.error( self.name + ": EOF exception found" )
1013 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001014 main.cleanup()
1015 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001016 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001017
Jon Hall7eb38402015-01-08 17:19:54 -08001018 def net( self ):
1019 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001020 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001021 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001022 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001023 main.log.error( self.name + ": EOF exception found" )
1024 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001025 main.cleanup()
1026 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001027 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001028
Jon Hallafa8a472015-06-12 14:02:42 -07001029 def links( self ):
1030 main.log.info( self.name + ": List network links" )
1031 try:
1032 response = self.execute( cmd='links', prompt='mininet>',
1033 timeout=10 )
1034 except pexpect.EOF:
1035 main.log.error( self.name + ": EOF exception found" )
1036 main.log.error( self.name + ": " + self.handle.before )
1037 main.cleanup()
1038 main.exit()
1039 return response
1040
GlennRC61321f22015-07-16 13:36:54 -07001041 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001042 '''
1043 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001044
kelvin-onlab7cce9382015-07-17 10:21:03 -07001045 @parm:
1046 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1047 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1048 '''
1049 for host1 in hosts:
1050 for host2 in hosts:
1051 if host1 != host2:
1052 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1053 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001054
1055 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001056 '''
1057 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1058 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001059
kelvin-onlab7cce9382015-07-17 10:21:03 -07001060 @parm:
1061 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1062 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1063 '''
1064 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1065 try:
1066 # Setup the mininet command
1067 cmd1 = 'iperf ' + host1 + " " + host2
1068 self.handle.sendline( cmd1 )
1069 outcome = self.handle.expect( "mininet>", timeout )
1070 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001071
kelvin-onlab7cce9382015-07-17 10:21:03 -07001072 # checks if there are results in the mininet response
1073 if "Results:" in response:
1074 main.log.report(self.name + ": iperf test completed")
1075 # parse the mn results
1076 response = response.split("\r\n")
1077 response = response[len(response)-2]
1078 response = response.split(": ")
1079 response = response[len(response)-1]
1080 response = response.replace("[", "")
1081 response = response.replace("]", "")
1082 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001083
kelvin-onlab7cce9382015-07-17 10:21:03 -07001084 # this is the bandwith two and from the two hosts
1085 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001086
kelvin-onlab7cce9382015-07-17 10:21:03 -07001087 # there should be two elements in the bandwidth list
1088 # ['host1 to host2', 'host2 to host1"]
1089 if len(bandwidth) == 2:
1090 main.log.report(self.name + ": iperf test successful")
1091 return main.TRUE
1092 else:
1093 main.log.error(self.name + ": invalid iperf results")
1094 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001095 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001096 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001097 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001098
GlennRC61321f22015-07-16 13:36:54 -07001099 except pexpect.TIMEOUT:
1100 main.log.error( self.name + ": TIMEOUT exception found")
1101 main.log.error( self.name + ": Exception: Cannot connect to iperf on port 5001" )
1102 return main.FALSE
1103
Jon Hallfbc828e2015-01-06 17:30:19 -08001104 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001105 main.log.error( self.name + ": EOF exception found" )
1106 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001107 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001108 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001109
1110 def iperfudpAll(self, hosts, bandwidth="10M"):
1111 '''
1112 Runs the iperfudp function with a given set of hosts and specified
1113 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001114
GlennRC61321f22015-07-16 13:36:54 -07001115 @param:
1116 bandwidth: the targeted bandwidth, in megabits ('M')
1117 '''
1118 for host1 in hosts:
1119 for host2 in hosts:
1120 if host1 != host2:
1121 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1122 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1123
1124 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1125
kelvin-onlab7cce9382015-07-17 10:21:03 -07001126 '''
1127 Creates an iperf UDP test with a specific bandwidth.
1128 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001129
kelvin-onlab7cce9382015-07-17 10:21:03 -07001130 @param:
1131 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1132 '''
1133 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1134 try:
1135 # setup the mininet command
1136 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1137 self.handle.sendline(cmd)
1138 self.handle.expect("mininet>")
1139 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001140
kelvin-onlab7cce9382015-07-17 10:21:03 -07001141 # check if there are in results in the mininet response
1142 if "Results:" in response:
1143 main.log.report(self.name + ": iperfudp test completed")
1144 # parse the results
1145 response = response.split("\r\n")
1146 response = response[len(response)-2]
1147 response = response.split(": ")
1148 response = response[len(response)-1]
1149 response = response.replace("[", "")
1150 response = response.replace("]", "")
1151 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001152
kelvin-onlab7cce9382015-07-17 10:21:03 -07001153 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001154
kelvin-onlab7cce9382015-07-17 10:21:03 -07001155 # check to see if there are at least three entries
1156 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1157 if len(mnBandwidth) == 3:
1158 # if one entry is blank then something is wrong
1159 for item in mnBandwidth:
1160 if item == "":
1161 main.log.error(self.name + ": Could not parse iperf output")
1162 main.log.error(self.name + ": invalid iperfudp results")
1163 return main.FALSE
1164 # otherwise results are vaild
1165 main.log.report(self.name + ": iperfudp test successful")
1166 return main.TRUE
1167 else:
1168 main.log.error(self.name + ": invalid iperfudp results")
1169 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001170
kelvin-onlab7cce9382015-07-17 10:21:03 -07001171 except pexpect.EOF:
1172 main.log.error( self.name + ": EOF exception found" )
1173 main.log.error( self.name + ": " + self.handle.before )
1174 main.cleanup()
1175 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001176
Jon Hall7eb38402015-01-08 17:19:54 -08001177 def nodes( self ):
1178 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001179 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 response = self.execute(
1181 cmd='nodes',
1182 prompt='mininet>',
1183 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001184 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001185 main.log.error( self.name + ": EOF exception found" )
1186 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001187 main.cleanup()
1188 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001189 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001190
Jon Hall7eb38402015-01-08 17:19:54 -08001191 def pingpair( self ):
1192 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001193 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001194 response = self.execute(
1195 cmd='pingpair',
1196 prompt='mininet>',
1197 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001198 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001199 main.log.error( self.name + ": EOF exception found" )
1200 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001201 main.cleanup()
1202 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001203
Jon Hall7eb38402015-01-08 17:19:54 -08001204 if re.search( ',\s0\%\spacket\sloss', response ):
1205 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001206 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001207 else:
1208 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001209 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001210
Jon Hall7eb38402015-01-08 17:19:54 -08001211 def link( self, **linkargs ):
1212 """
1213 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001214 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001215 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1216 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1217 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1218 main.log.info(
1219 "Bring link between '" +
1220 end1 +
1221 "' and '" +
1222 end2 +
1223 "' '" +
1224 option +
1225 "'" )
1226 command = "link " + \
1227 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001228 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001229 self.handle.sendline( command )
1230 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001231 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001232 main.log.error( self.name + ": EOF exception found" )
1233 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001234 main.cleanup()
1235 main.exit()
adminbae64d82013-08-01 10:50:15 -07001236 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001237
Jon Hall7eb38402015-01-08 17:19:54 -08001238 def yank( self, **yankargs ):
1239 """
1240 yank a mininet switch interface to a host"""
1241 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001242 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001243 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1244 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1245 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001246 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001247 response = self.execute(
1248 cmd=command,
1249 prompt="mininet>",
1250 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001251 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001252 main.log.error( self.name + ": EOF exception found" )
1253 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001254 main.cleanup()
1255 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001256 return main.TRUE
1257
Jon Hall7eb38402015-01-08 17:19:54 -08001258 def plug( self, **plugargs ):
1259 """
1260 plug the yanked mininet switch interface to a switch"""
1261 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001262 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001263 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1264 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1265 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001266 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001267 response = self.execute(
1268 cmd=command,
1269 prompt="mininet>",
1270 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001271 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001272 main.log.error( self.name + ": EOF exception found" )
1273 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001274 main.cleanup()
1275 main.exit()
adminbae64d82013-08-01 10:50:15 -07001276 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001277
Jon Hall7eb38402015-01-08 17:19:54 -08001278 def dpctl( self, **dpctlargs ):
1279 """
1280 Run dpctl command on all switches."""
1281 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001282 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001283 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1284 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1285 command = "dpctl " + cmd + " " + str( cmdargs )
1286 try:
1287 response = self.execute(
1288 cmd=command,
1289 prompt="mininet>",
1290 timeout=10 )
1291 except pexpect.EOF:
1292 main.log.error( self.name + ": EOF exception found" )
1293 main.log.error( self.name + ": " + self.handle.before )
1294 main.cleanup()
1295 main.exit()
1296 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001297
kelvin-onlabd3b64892015-01-20 13:26:24 -08001298 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001299 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001300 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001301 fileInput = path + '/lib/Mininet/INSTALL'
1302 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001303 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001304 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001305 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001306 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001307 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001308 return version
adminbae64d82013-08-01 10:50:15 -07001309
kelvin-onlabd3b64892015-01-20 13:26:24 -08001310 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001311 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001312 Parameters:
1313 sw: The name of an OVS switch. Example "s1"
1314 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001315 The output of the command from the mininet cli
1316 or main.FALSE on timeout"""
1317 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001318 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001319 response = self.execute(
1320 cmd=command,
1321 prompt="mininet>",
1322 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001323 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001324 return response
admin2a9548d2014-06-17 14:08:07 -07001325 else:
1326 return main.FALSE
1327 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001328 main.log.error( self.name + ": EOF exception found" )
1329 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001330 main.cleanup()
1331 main.exit()
adminbae64d82013-08-01 10:50:15 -07001332
Charles Chan029be652015-08-24 01:46:10 +08001333 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001334 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001335 Description:
1336 Assign switches to the controllers ( for ovs use only )
1337 Required:
1338 sw - Name of the switch. This can be a list or a string.
1339 ip - Ip addresses of controllers. This can be a list or a string.
1340 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001341 port - ONOS use port 6653, if no list of ports is passed, then
1342 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001343 ptcp - ptcp number, This can be a string or a list that has
1344 the same length as switch. This is optional and not required
1345 when using ovs switches.
1346 NOTE: If switches and ptcp are given in a list type they should have the
1347 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1348 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001349
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001350 Return:
1351 Returns main.TRUE if mininet correctly assigned switches to
1352 controllers, otherwise it will return main.FALSE or an appropriate
1353 exception(s)
1354 """
1355 assignResult = main.TRUE
1356 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001357 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001358 command = "sh ovs-vsctl set-controller "
1359 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001360 try:
1361 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001362 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001363 if isinstance( port, types.StringType ) or \
1364 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001365 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001366 elif isinstance( port, types.ListType ):
1367 main.log.error( self.name + ": Only one controller " +
1368 "assigned and a list of ports has" +
1369 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001370 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001371 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001372 main.log.error( self.name + ": Invalid controller port " +
1373 "number. Please specify correct " +
1374 "controller port" )
1375 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001376
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001377 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001378 if isinstance( port, types.StringType ) or \
1379 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001380 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001381 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1382 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001383 elif isinstance( port, types.ListType ):
1384 if ( len( ip ) != len( port ) ):
1385 main.log.error( self.name + ": Port list = " +
1386 str( len( port ) ) +
1387 "should be the same as controller" +
1388 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001389 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001390 else:
1391 onosIp = ""
1392 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001393 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1394 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001395 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001396 main.log.error( self.name + ": Invalid controller port " +
1397 "number. Please specify correct " +
1398 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001399 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001400 else:
1401 main.log.error( self.name + ": Invalid ip address" )
1402 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001403
1404 if isinstance( sw, types.StringType ):
1405 command += sw + " "
1406 if ptcp:
1407 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001408 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001409 elif isinstance( ptcp, types.ListType ):
1410 main.log.error( self.name + ": Only one switch is " +
1411 "being set and multiple PTCP is " +
1412 "being passed " )
1413 else:
1414 main.log.error( self.name + ": Invalid PTCP" )
1415 ptcp = ""
1416 command += onosIp
1417 commandList.append( command )
1418
1419 elif isinstance( sw, types.ListType ):
1420 if ptcp:
1421 if isinstance( ptcp, types.ListType ):
1422 if len( ptcp ) != len( sw ):
1423 main.log.error( self.name + ": PTCP length = " +
1424 str( len( ptcp ) ) +
1425 " is not the same as switch" +
1426 " length = " +
1427 str( len( sw ) ) )
1428 return main.FALSE
1429 else:
1430 for switch, ptcpNum in zip( sw, ptcp ):
1431 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001432 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001433 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001434 tempCmd += onosIp
1435 commandList.append( tempCmd )
1436 else:
1437 main.log.error( self.name + ": Invalid PTCP" )
1438 return main.FALSE
1439 else:
1440 for switch in sw:
1441 tempCmd = "sh ovs-vsctl set-controller "
1442 tempCmd += switch + " " + onosIp
1443 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001444 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001445 main.log.error( self.name + ": Invalid switch type " )
1446 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001447
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001448 for cmd in commandList:
1449 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001450 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001451 except pexpect.TIMEOUT:
1452 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1453 return main.FALSE
1454 except pexpect.EOF:
1455 main.log.error( self.name + ": EOF exception found" )
1456 main.log.error( self.name + ": " + self.handle.before )
1457 main.cleanup()
1458 main.exit()
1459 return main.TRUE
1460 except Exception:
1461 main.log.exception( self.name + ": Uncaught exception!" )
1462 main.cleanup()
1463 main.exit()
adminbae64d82013-08-01 10:50:15 -07001464
kelvin-onlabd3b64892015-01-20 13:26:24 -08001465 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001466 """
1467 Removes the controller target from sw"""
1468 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001469 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001470 response = self.execute(
1471 cmd=command,
1472 prompt="mininet>",
1473 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001474 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001475 main.log.error( self.name + ": EOF exception found" )
1476 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001477 main.cleanup()
1478 main.exit()
1479 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001480 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001481
kelvin-onlabd3b64892015-01-20 13:26:24 -08001482 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001483 """
Jon Hallb1290e82014-11-18 16:17:48 -05001484 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001485 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001486 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001487 NOTE: cannot currently specify what type of switch
1488 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001489 sw = name of the new switch as a string
1490 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001491 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001492 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001493 """
1494 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001495 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001496 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001497 response = self.execute(
1498 cmd=command,
1499 prompt="mininet>",
1500 timeout=10 )
1501 if re.search( "already exists!", response ):
1502 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001503 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001504 elif re.search( "Error", response ):
1505 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001506 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001507 elif re.search( "usage:", response ):
1508 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001509 return main.FALSE
1510 else:
1511 return main.TRUE
1512 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001513 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001514 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001515 main.cleanup()
1516 main.exit()
1517
kelvin-onlabd3b64892015-01-20 13:26:24 -08001518 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001519 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001520 delete a switch from the mininet topology
1521 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001522 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001523 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001524 sw = name of the switch as a string
1525 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001526 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001527 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001528 response = self.execute(
1529 cmd=command,
1530 prompt="mininet>",
1531 timeout=10 )
1532 if re.search( "no switch named", response ):
1533 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001534 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001535 elif re.search( "Error", response ):
1536 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001537 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001538 elif re.search( "usage:", response ):
1539 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001540 return main.FALSE
1541 else:
1542 return main.TRUE
1543 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001544 main.log.error( self.name + ": EOF exception found" )
1545 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001546 main.cleanup()
1547 main.exit()
1548
kelvin-onlabd3b64892015-01-20 13:26:24 -08001549 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001550 """
1551 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001552 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001553 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001554 NOTE: cannot currently specify what type of link
1555 required params:
1556 node1 = the string node name of the first endpoint of the link
1557 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001558 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001559 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001560 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001561 response = self.execute(
1562 cmd=command,
1563 prompt="mininet>",
1564 timeout=10 )
1565 if re.search( "doesnt exist!", response ):
1566 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001567 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001568 elif re.search( "Error", response ):
1569 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001570 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001571 elif re.search( "usage:", response ):
1572 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001573 return main.FALSE
1574 else:
1575 return main.TRUE
1576 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001577 main.log.error( self.name + ": EOF exception found" )
1578 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001579 main.cleanup()
1580 main.exit()
1581
kelvin-onlabd3b64892015-01-20 13:26:24 -08001582 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001583 """
1584 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001585 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001586 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001587 required params:
1588 node1 = the string node name of the first endpoint of the link
1589 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001590 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001591 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001592 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001593 response = self.execute(
1594 cmd=command,
1595 prompt="mininet>",
1596 timeout=10 )
1597 if re.search( "no node named", response ):
1598 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001599 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001600 elif re.search( "Error", response ):
1601 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001602 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001603 elif re.search( "usage:", response ):
1604 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001605 return main.FALSE
1606 else:
1607 return main.TRUE
1608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 main.log.error( self.name + ": EOF exception found" )
1610 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001611 main.cleanup()
1612 main.exit()
1613
kelvin-onlabd3b64892015-01-20 13:26:24 -08001614 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001615 """
Jon Hallb1290e82014-11-18 16:17:48 -05001616 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001617 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001618 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001619 NOTE: cannot currently specify what type of host
1620 required params:
1621 hostname = the string hostname
1622 optional key-value params
1623 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001624 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001625 """
1626 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001627 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001628 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001629 response = self.execute(
1630 cmd=command,
1631 prompt="mininet>",
1632 timeout=10 )
1633 if re.search( "already exists!", response ):
1634 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001635 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001636 elif re.search( "doesnt exists!", response ):
1637 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001638 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001639 elif re.search( "Error", response ):
1640 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001641 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001642 elif re.search( "usage:", response ):
1643 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001644 return main.FALSE
1645 else:
1646 return main.TRUE
1647 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001648 main.log.error( self.name + ": EOF exception found" )
1649 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001650 main.cleanup()
1651 main.exit()
1652
kelvin-onlabd3b64892015-01-20 13:26:24 -08001653 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001654 """
1655 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001656 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001657 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001658 NOTE: this uses a custom mn function
1659 required params:
1660 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001661 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001662 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001663 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001664 response = self.execute(
1665 cmd=command,
1666 prompt="mininet>",
1667 timeout=10 )
1668 if re.search( "no host named", response ):
1669 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001670 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001671 elif re.search( "Error", response ):
1672 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001673 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001674 elif re.search( "usage:", response ):
1675 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001676 return main.FALSE
1677 else:
1678 return main.TRUE
1679 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001680 main.log.error( self.name + ": EOF exception found" )
1681 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001682 main.cleanup()
1683 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001684
Jon Hall7eb38402015-01-08 17:19:54 -08001685 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001686 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001687 Called at the end of the test to stop the mininet and
1688 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001689 """
Jon Halld80cc142015-07-06 13:36:05 -07001690 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001691 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001692 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001693 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001694 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001695 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001696 elif i == 1:
1697 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001698 # print "Disconnecting Mininet"
1699 if self.handle:
1700 self.handle.sendline( "exit" )
1701 self.handle.expect( "exit" )
1702 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001703 else:
1704 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001705 return response
1706
Jon Halld80cc142015-07-06 13:36:05 -07001707 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001708 """
Jon Hall21270ac2015-02-16 17:59:55 -08001709 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001710 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001711 main.FALSE if the pexpect handle does not exist.
1712
Jon Halld61331b2015-02-17 16:35:47 -08001713 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001714 """
Jon Halld61331b2015-02-17 16:35:47 -08001715 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001716 response = ''
1717 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001718 try:
Jon Halld80cc142015-07-06 13:36:05 -07001719 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001720 i = self.handle.expect( [ 'mininet>',
1721 '\$',
1722 pexpect.EOF,
1723 pexpect.TIMEOUT ],
1724 timeout )
1725 if i == 0:
1726 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001727 response = self.execute(
1728 cmd="exit",
1729 prompt="(.*)",
1730 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001731 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001732 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001733 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001734
kelvin-onlab56a3f462015-02-06 14:04:43 -08001735 if i == 1:
1736 main.log.info( " Mininet trying to exit while not " +
1737 "in the mininet prompt" )
1738 elif i == 2:
1739 main.log.error( "Something went wrong exiting mininet" )
1740 elif i == 3: # timeout
1741 main.log.error( "Something went wrong exiting mininet " +
1742 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001743
Hari Krishnab35c6d02015-03-18 11:13:51 -07001744 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001745 self.handle.sendline( "" )
1746 self.handle.expect( '\$' )
1747 self.handle.sendline(
1748 "sudo kill -9 \`ps -ef | grep \"" +
1749 fileName +
1750 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001751 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001752 main.log.error( self.name + ": EOF exception found" )
1753 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001754 main.cleanup()
1755 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001756 else:
1757 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001758 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001759 return response
1760
Jon Halla5cb3412015-08-18 14:08:22 -07001761 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001762 """
1763 Description:
1764 Sends arp message from mininet host for hosts discovery
1765 Required:
1766 host - hosts name
1767 Optional:
1768 ip - ip address that does not exist in the network so there would
1769 be no reply.
1770 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001771 if ethDevice:
1772 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001773 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001774 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001775 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001776 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001777 i = self.handle.expect( [ "mininet>", "arping: " ] )
1778 if i == 0:
1779 return main.TRUE
1780 elif i == 1:
1781 response = self.handle.before + self.handle.after
1782 self.handle.expect( "mininet>" )
1783 response += self.handle.before + self.handle.after
1784 main.log.warn( "Error sending arping, output was: " +
1785 response )
1786 return main.FALSE
1787 except pexpect.TIMEOUT:
1788 main.log.error( self.name + ": TIMEOUT exception found" )
1789 main.log.warn( self.handle.before )
1790 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001791 except pexpect.EOF:
1792 main.log.error( self.name + ": EOF exception found" )
1793 main.log.error( self.name + ": " + self.handle.before )
1794 main.cleanup()
1795 main.exit()
admin07529932013-11-22 14:58:28 -08001796
Jon Hall7eb38402015-01-08 17:19:54 -08001797 def decToHex( self, num ):
1798 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001799
Jon Hall7eb38402015-01-08 17:19:54 -08001800 def getSwitchFlowCount( self, switch ):
1801 """
1802 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001803 if self.handle:
1804 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1805 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001806 response = self.execute(
1807 cmd=cmd,
1808 prompt="mininet>",
1809 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001810 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001811 main.log.error( self.name + ": EOF exception found" )
1812 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001813 main.cleanup()
1814 main.exit()
1815 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001816 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001817 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001818 main.log.info(
1819 "Couldn't find flows on switch %s, found: %s" %
1820 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001821 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001822 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001823 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001824 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001825
kelvin-onlabd3b64892015-01-20 13:26:24 -08001826 def checkFlows( self, sw, dumpFormat=None ):
1827 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001828 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001829 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001830 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001831 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001832 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001833 response = self.execute(
1834 cmd=command,
1835 prompt="mininet>",
1836 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001837 return response
1838 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001839 main.log.error( self.name + ": EOF exception found" )
1840 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001841 main.cleanup()
1842 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001843
Jon Hall9043c902015-07-30 14:23:44 -07001844 def getFlowTable( self, protoVersion, sw ):
1845 """
1846 Returns certain fields of an OVS flow table. Will force output to
1847 either OF 1.0 or 1.3 format for consistency.
1848
1849 TODO add option to look at cookies. ignoring them for now
1850
1851 NOTE: Use format to force consistent flow table output across
1852 versions
1853 """
1854 try:
1855 self.handle.sendline( "" )
1856 self.handle.expect( "mininet>" )
1857 command = "sh ovs-ofctl dump-flows " + sw
1858 if protoVersion == 1.0:
1859 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\
1860 " print $1 $3 $6 $7 $8}' | "
1861 elif protoVersion == 1.3:
1862 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\
1863 " print $1 $3 $6 $7}' | "
1864 else:
1865 main.log.error(
1866 "Unknown protoVersion in getFlowTable(). given: (" +
1867 str( type( protoVersion ) ) +
1868 ") '" + str( protoVersion ) + "'" )
1869 return None
1870 command += "cut -d ',' -f 2- | sort -n -k1 -r"
1871 self.handle.sendline( command )
1872 self.handle.expect( "sort" )
1873 self.handle.expect( "OFPST_FLOW" )
1874 response = self.handle.before
1875 return response
1876 except pexpect.EOF:
1877 main.log.error( self.name + ": EOF exception found" )
1878 main.log.error( self.name + ": " + self.handle.before )
1879 main.cleanup()
1880 main.exit()
1881 except pexpect.TIMEOUT:
1882 main.log.exception( self.name + ": Timeout exception: " )
1883 return None
1884
1885 def flowComp( self, flow1, flow2 ):
1886 if flow1 == flow2:
1887 return main.TRUE
1888 else:
1889 main.log.info( "Flow tables do not match, printing tables:" )
1890 main.log.info( "Flow Table 1:" )
1891 main.log.info( flow1 )
1892 main.log.info( "Flow Table 2:" )
1893 main.log.info( flow2 )
1894 return main.FALSE
1895
Charles Chan029be652015-08-24 01:46:10 +08001896 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001897 """
Jon Hallefbd9792015-03-05 16:11:36 -08001898 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001899 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001900 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001901 self.handle.sendline( "" )
1902 self.handle.expect( "mininet>" )
1903 self.handle.sendline(
1904 "sh sudo tcpdump -n -i " +
1905 intf +
1906 " " +
1907 port +
1908 " -w " +
1909 filename.strip() +
1910 " &" )
1911 self.handle.sendline( "" )
1912 i = self.handle.expect( [ 'No\ssuch\device',
1913 'listening\son',
1914 pexpect.TIMEOUT,
1915 "mininet>" ],
1916 timeout=10 )
1917 main.log.warn( self.handle.before + self.handle.after )
1918 self.handle.sendline( "" )
1919 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001920 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001921 main.log.error(
1922 self.name +
1923 ": tcpdump - No such device exists. " +
1924 "tcpdump attempted on: " +
1925 intf )
admin2a9548d2014-06-17 14:08:07 -07001926 return main.FALSE
1927 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001928 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001929 return main.TRUE
1930 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001931 main.log.error(
1932 self.name +
1933 ": tcpdump command timed out! Check interface name," +
1934 " given interface was: " +
1935 intf )
admin2a9548d2014-06-17 14:08:07 -07001936 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001937 elif i == 3:
1938 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001939 return main.TRUE
1940 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001941 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001942 return main.FALSE
1943 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001944 main.log.error( self.name + ": EOF exception found" )
1945 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001946 main.cleanup()
1947 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001948 except Exception:
1949 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001950 main.cleanup()
1951 main.exit()
1952
kelvin-onlabd3b64892015-01-20 13:26:24 -08001953 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001954 """
1955 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001956 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001957 self.handle.sendline( "sh sudo pkill tcpdump" )
1958 self.handle.expect( "mininet>" )
1959 self.handle.sendline( "" )
1960 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001961 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001962 main.log.error( self.name + ": EOF exception found" )
1963 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001964 main.cleanup()
1965 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001966 except Exception:
1967 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001968 main.cleanup()
1969 main.exit()
1970
Jon Halld80cc142015-07-06 13:36:05 -07001971 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001972 """
1973 Read ports from a Mininet switch.
1974
1975 Returns a json structure containing information about the
1976 ports of the given switch.
1977 """
1978 response = self.getInterfaces( nodeName )
1979 # TODO: Sanity check on response. log if no such switch exists
1980 ports = []
1981 for line in response.split( "\n" ):
1982 if not line.startswith( "name=" ):
1983 continue
1984 portVars = {}
1985 for var in line.split( "," ):
1986 key, value = var.split( "=" )
1987 portVars[ key ] = value
1988 isUp = portVars.pop( 'enabled', "True" )
1989 isUp = "True" in isUp
1990 if verbose:
1991 main.log.info( "Reading switch port %s(%s)" %
1992 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1993 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001994 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001995 mac = None
1996 ips = []
1997 ip = portVars[ 'ip' ]
1998 if ip == 'None':
1999 ip = None
2000 ips.append( ip )
2001 name = portVars[ 'name' ]
2002 if name == 'None':
2003 name = None
2004 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2005 if name == 'lo':
2006 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2007 else:
2008 portNo = re.search( portRe, name ).group( 'port' )
2009 ports.append( { 'of_port': portNo,
2010 'mac': str( mac ).replace( '\'', '' ),
2011 'name': name,
2012 'ips': ips,
2013 'enabled': isUp } )
2014 return ports
2015
Jon Halld80cc142015-07-06 13:36:05 -07002016 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002017 """
2018 Read switches from Mininet.
2019
2020 Returns a dictionary whose keys are the switch names and the value is
2021 a dictionary containing information about the switch.
2022 """
Jon Halla22481b2015-07-28 17:46:01 -07002023 # NOTE: To support new Mininet switch classes, just append the new
2024 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002025
Jon Halla22481b2015-07-28 17:46:01 -07002026 # Regex patterns to parse 'dump' output
2027 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002028 # <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 -07002029 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002030 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2031 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2032 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2033 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2034 swRE = r"<(?P<class>" + switchClasses + r")" +\
2035 r"(?P<options>\{.*\})?\s" +\
2036 r"(?P<name>[^:]+)\:\s" +\
2037 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2038 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002039 # Update mn port info
2040 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002041 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002042 dump = self.dump().split( "\n" )
2043 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002044 result = re.search( swRE, line, re.I )
2045 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002046 name = result.group( 'name' )
2047 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002048 pid = result.group( 'pid' )
2049 swClass = result.group( 'class' )
2050 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002051 if verbose:
2052 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2053 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002054 output[ name ] = { "dpid": dpid,
2055 "ports": ports,
2056 "swClass": swClass,
2057 "pid": pid,
2058 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002059 return output
2060
Jon Halld80cc142015-07-06 13:36:05 -07002061 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002062 """
2063 Read hosts from Mininet.
2064
2065 Returns a dictionary whose keys are the host names and the value is
2066 a dictionary containing information about the host.
2067 """
2068 # Regex patterns to parse dump output
2069 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002070 # <Host h1: pid=12725>
2071 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2072 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2073 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002074 # NOTE: Does not correctly match hosts with multi-links
2075 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2076 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002077 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002078 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002079 # update mn port info
2080 self.update()
2081 # Get mininet dump
2082 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002083 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002084 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002085 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002086 result = re.search( hostRE, line )
2087 name = result.group( 'name' )
2088 interfaces = []
2089 response = self.getInterfaces( name )
2090 # Populate interface info
2091 for line in response.split( "\n" ):
2092 if line.startswith( "name=" ):
2093 portVars = {}
2094 for var in line.split( "," ):
2095 key, value = var.split( "=" )
2096 portVars[ key ] = value
2097 isUp = portVars.pop( 'enabled', "True" )
2098 isUp = "True" in isUp
2099 if verbose:
2100 main.log.info( "Reading host port %s(%s)" %
2101 ( portVars[ 'name' ],
2102 portVars[ 'mac' ] ) )
2103 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002104 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002105 mac = None
2106 ips = []
2107 ip = portVars[ 'ip' ]
2108 if ip == 'None':
2109 ip = None
2110 ips.append( ip )
2111 intfName = portVars[ 'name' ]
2112 if name == 'None':
2113 name = None
2114 interfaces.append( {
2115 "name": intfName,
2116 "ips": ips,
2117 "mac": str( mac ),
2118 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002119 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002120 return hosts
2121
2122 def getLinks( self ):
2123 """
2124 Gathers information about current Mininet links. These links may not
2125 be up if one of the ports is down.
2126
2127 Returns a list of dictionaries with link endpoints.
2128
2129 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002130 { 'node1': str( node1 name )
2131 'node2': str( node2 name )
2132 'port1': str( port1 of_port )
2133 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002134 Note: The port number returned is the eth#, not necessarily the of_port
2135 number. In Mininet, for OVS switch, these should be the same. For
2136 hosts, this is just the eth#.
2137 """
2138 self.update()
2139 response = self.links().split( '\n' )
2140
2141 # Examples:
2142 # s1-eth3<->s2-eth1 (OK OK)
2143 # s13-eth3<->h27-eth0 (OK OK)
2144 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2145 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2146 links = []
2147 for line in response:
2148 match = re.search( linkRE, line )
2149 if match:
2150 node1 = match.group( 'node1' )
2151 node2 = match.group( 'node2' )
2152 port1 = match.group( 'port1' )
2153 port2 = match.group( 'port2' )
2154 links.append( { 'node1': node1,
2155 'node2': node2,
2156 'port1': port1,
2157 'port2': port2 } )
2158 return links
2159
2160 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002161 """
2162 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002163 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002164
Jon Hallafa8a472015-06-12 14:02:42 -07002165 Dependencies:
2166 1. numpy - "sudo pip install numpy"
2167 """
2168 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002169 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002170 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002171 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002172 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002173 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002174 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002175 main.log.error(
2176 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002177 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002178 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002179 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002180 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002181 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002182 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002183 onosDPIDs.append(
2184 switch[ 'id' ].replace(
2185 ":",
2186 '' ).replace(
2187 "of",
2188 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002189 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002190
Jon Hall7eb38402015-01-08 17:19:54 -08002191 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002192 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002193 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002194 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002195 main.log.error( str( list1 ) )
2196 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002197 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002198 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002199 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002200 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002201 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002202
Jon Hall7eb38402015-01-08 17:19:54 -08002203 # FIXME: this does not look for extra ports in ONOS, only checks that
2204 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002205 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002206
Jon Hall7eb38402015-01-08 17:19:54 -08002207 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002208 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002209 mnPorts = []
2210 onosPorts = []
2211 switchResult = main.TRUE
2212 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002213 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002214 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002215 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002216 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002217 if onosSwitch[ 'device' ][ 'id' ].replace(
2218 ':',
2219 '' ).replace(
2220 "of",
2221 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002222 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002223 if port[ 'isEnabled' ]:
2224 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002225 # onosPorts.append( 'local' )
2226 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002227 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002228 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002229 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002230 mnPorts.sort( key=float )
2231 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002232
kelvin-onlabd3b64892015-01-20 13:26:24 -08002233 mnPortsLog = mnPorts
2234 onosPortsLog = onosPorts
2235 mnPorts = [ x for x in mnPorts ]
2236 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002237
Jon Hall7eb38402015-01-08 17:19:54 -08002238 # TODO: handle other reserved port numbers besides LOCAL
2239 # NOTE: Reserved ports
2240 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2241 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002242 for mnPort in mnPortsLog:
2243 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002244 # don't set results to true here as this is just one of
2245 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002246 mnPorts.remove( mnPort )
2247 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002248
Jon Hall7eb38402015-01-08 17:19:54 -08002249 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002250 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002251 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002252 if 65534 in mnPorts:
2253 mnPorts.remove( 65534 )
2254 if long( uint64( -2 ) ) in onosPorts:
2255 onosPorts.remove( long( uint64( -2 ) ) )
2256 if len( mnPorts ): # the ports of this switch don't match
2257 switchResult = main.FALSE
2258 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2259 if len( onosPorts ): # the ports of this switch don't match
2260 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002261 main.log.warn(
2262 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002263 str( onosPorts ) )
2264 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002265 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002266 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002267 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002268 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2269 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2270 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002271 finalResults = finalResults and portsResults
2272 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002273
Jon Hallafa8a472015-06-12 14:02:42 -07002274 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002275 """
2276 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002277 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002278
Jon Hallafa8a472015-06-12 14:02:42 -07002279 """
Jon Hall7eb38402015-01-08 17:19:54 -08002280 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002281 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002282 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002283
Jon Halld80cc142015-07-06 13:36:05 -07002284 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002285 for l in links:
2286 try:
2287 node1 = switches[ l[ 'node1' ] ]
2288 node2 = switches[ l[ 'node2' ] ]
2289 enabled = True
2290 for port in node1[ 'ports' ]:
2291 if port[ 'of_port' ] == l[ 'port1' ]:
2292 enabled = enabled and port[ 'enabled' ]
2293 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002294 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002295 enabled = enabled and port[ 'enabled' ]
2296 if enabled:
2297 mnLinks.append( l )
2298 except KeyError:
2299 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002300 if 2 * len( mnLinks ) == len( onos ):
2301 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002302 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002303 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002304 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002305 "Mininet has " + str( len( mnLinks ) ) +
2306 " bidirectional links and ONOS has " +
2307 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002308
Jon Hall7eb38402015-01-08 17:19:54 -08002309 # iterate through MN links and check if an ONOS link exists in
2310 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002311 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002312 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002313 node1 = None
2314 port1 = None
2315 node2 = None
2316 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002317 firstDir = main.FALSE
2318 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002319 for swName, switch in switches.iteritems():
2320 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002321 node1 = switch[ 'dpid' ]
2322 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002323 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002324 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002325 if node1 is not None and node2 is not None:
2326 break
Jon Hallafa8a472015-06-12 14:02:42 -07002327 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002328 node2 = switch[ 'dpid' ]
2329 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002330 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002331 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002332 if node1 is not None and node2 is not None:
2333 break
2334
kelvin-onlabd3b64892015-01-20 13:26:24 -08002335 for onosLink in onos:
2336 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002337 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002338 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002339 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002340 onosPort1 = onosLink[ 'src' ][ 'port' ]
2341 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002342
Jon Hall72cf1dc2014-10-20 21:04:50 -04002343 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002344 if str( onosNode1 ) == str( node1 ) and str(
2345 onosNode2 ) == str( node2 ):
2346 if int( onosPort1 ) == int( port1 ) and int(
2347 onosPort2 ) == int( port2 ):
2348 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002349 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002350 main.log.warn(
2351 'The port numbers do not match for ' +
2352 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002353 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002354 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002355 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002356 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002357 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002358
2359 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002360 elif ( str( onosNode1 ) == str( node2 ) and
2361 str( onosNode2 ) == str( node1 ) ):
2362 if ( int( onosPort1 ) == int( port2 )
2363 and int( onosPort2 ) == int( port1 ) ):
2364 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002365 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002366 main.log.warn(
2367 'The port numbers do not match for ' +
2368 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002369 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002370 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002371 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002372 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002373 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002374 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002375 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002376 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002377 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002378 'ONOS does not have the link %s/%s -> %s/%s' %
2379 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002380 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002381 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002382 'ONOS does not have the link %s/%s -> %s/%s' %
2383 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002384 linkResults = linkResults and firstDir and secondDir
2385 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002386
Jon Hallafa8a472015-06-12 14:02:42 -07002387 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002388 """
Jon Hallafa8a472015-06-12 14:02:42 -07002389 Compare mn and onos Hosts.
2390 Since Mininet hosts are quiet, ONOS will only know of them when they
2391 speak. For this reason, we will only check that the hosts in ONOS
2392 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002393
Jon Hallafa8a472015-06-12 14:02:42 -07002394 Arguments:
2395 hostsJson: parsed json object from the onos hosts api
2396 Returns:
2397 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002398 import json
2399 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002400 for onosHost in hostsJson:
2401 onosMAC = onosHost[ 'mac' ].lower()
2402 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002403 for mnHost, info in hosts.iteritems():
2404 for mnIntf in info[ 'interfaces' ]:
2405 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002406 match = True
2407 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002408 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002409 pass # all is well
2410 else:
2411 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002412 main.log.error( "ONOS host " +
2413 onosHost[ 'id' ] +
2414 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002415 str( onosHost[ 'ipAddresses' ] ) +
2416 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002417 str( ip ) +
2418 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002419 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002420 onosHost,
2421 sort_keys=True,
2422 indent=4,
2423 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002424 main.log.info( output )
2425 hostResults = main.FALSE
2426 if not match:
2427 hostResults = main.FALSE
2428 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2429 "corresponding Mininet host." )
2430 output = json.dumps( onosHost,
2431 sort_keys=True,
2432 indent=4,
2433 separators=( ',', ': ' ) )
2434 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002435 return hostResults
2436
Jon Hallafa8a472015-06-12 14:02:42 -07002437 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002438 """
2439 Returns a list of all hosts
2440 Don't ask questions just use it"""
2441 self.handle.sendline( "" )
2442 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002443
Jon Hall7eb38402015-01-08 17:19:54 -08002444 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2445 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002446
kelvin-onlabd3b64892015-01-20 13:26:24 -08002447 handlePy = self.handle.before
2448 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2449 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002450
Jon Hall7eb38402015-01-08 17:19:54 -08002451 self.handle.sendline( "" )
2452 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002453
kelvin-onlabd3b64892015-01-20 13:26:24 -08002454 hostStr = handlePy.replace( "]", "" )
2455 hostStr = hostStr.replace( "'", "" )
2456 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002457 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002458 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002459
kelvin-onlabd3b64892015-01-20 13:26:24 -08002460 return hostList
adminbae64d82013-08-01 10:50:15 -07002461
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002462 def getSwitch( self ):
2463 """
2464 Returns a list of all switches
2465 Again, don't ask question just use it...
2466 """
2467 # get host list...
2468 hostList = self.getHosts()
2469 # Make host set
2470 hostSet = set( hostList )
2471
2472 # Getting all the nodes in mininet
2473 self.handle.sendline( "" )
2474 self.handle.expect( "mininet>" )
2475
2476 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2477 self.handle.expect( "mininet>" )
2478
2479 handlePy = self.handle.before
2480 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2481 handlePy = handlePy.rstrip()
2482
2483 self.handle.sendline( "" )
2484 self.handle.expect( "mininet>" )
2485
2486 nodesStr = handlePy.replace( "]", "" )
2487 nodesStr = nodesStr.replace( "'", "" )
2488 nodesStr = nodesStr.replace( "[", "" )
2489 nodesStr = nodesStr.replace( " ", "" )
2490 nodesList = nodesStr.split( "," )
2491
2492 nodesSet = set( nodesList )
2493 # discarding default controller(s) node
2494 nodesSet.discard( 'c0' )
2495 nodesSet.discard( 'c1' )
2496 nodesSet.discard( 'c2' )
2497
2498 switchSet = nodesSet - hostSet
2499 switchList = list( switchSet )
2500
2501 return switchList
2502
Jon Hall7eb38402015-01-08 17:19:54 -08002503 def update( self ):
2504 """
2505 updates the port address and status information for
2506 each port in mn"""
2507 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002508 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002509 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002510 self.handle.sendline( "" )
2511 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002512
Jon Hall7eb38402015-01-08 17:19:54 -08002513 self.handle.sendline( "update" )
2514 self.handle.expect( "update" )
2515 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002516
Jon Hall7eb38402015-01-08 17:19:54 -08002517 self.handle.sendline( "" )
2518 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002519
Jon Hallb1290e82014-11-18 16:17:48 -05002520 return main.TRUE
2521 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002522 main.log.error( self.name + ": EOF exception found" )
2523 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002524 main.cleanup()
2525 main.exit()
2526
Jon Halld80cc142015-07-06 13:36:05 -07002527 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002528 """
2529 Add vlan tag to a host.
2530 Dependencies:
2531 This class depends on the "vlan" package
2532 $ sudo apt-get install vlan
2533 Configuration:
2534 Load the 8021q module into the kernel
2535 $sudo modprobe 8021q
2536
2537 To make this setup permanent:
2538 $ sudo su -c 'echo "8021q" >> /etc/modules'
2539 """
2540 if self.handle:
2541 try:
Jon Halld80cc142015-07-06 13:36:05 -07002542 # get the ip address of the host
2543 main.log.info( "Get the ip address of the host" )
2544 ipaddr = self.getIPAddress( host )
2545 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002546
Jon Halld80cc142015-07-06 13:36:05 -07002547 # remove IP from interface intf
2548 # Ex: h1 ifconfig h1-eth0 inet 0
2549 main.log.info( "Remove IP from interface " )
2550 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2551 self.handle.sendline( cmd2 )
2552 self.handle.expect( "mininet>" )
2553 response = self.handle.before
2554 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002555
Jon Halld80cc142015-07-06 13:36:05 -07002556 # create VLAN interface
2557 # Ex: h1 vconfig add h1-eth0 100
2558 main.log.info( "Create Vlan" )
2559 cmd3 = host + " vconfig add " + intf + " " + vlan
2560 self.handle.sendline( cmd3 )
2561 self.handle.expect( "mininet>" )
2562 response = self.handle.before
2563 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002564
Jon Halld80cc142015-07-06 13:36:05 -07002565 # assign the host's IP to the VLAN interface
2566 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2567 main.log.info( "Assign the host IP to the vlan interface" )
2568 vintf = intf + "." + vlan
2569 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2570 self.handle.sendline( cmd4 )
2571 self.handle.expect( "mininet>" )
2572 response = self.handle.before
2573 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002574
2575 return main.TRUE
2576 except pexpect.EOF:
2577 main.log.error( self.name + ": EOF exception found" )
2578 main.log.error( self.name + ": " + self.handle.before )
2579 return main.FALSE
2580
adminbae64d82013-08-01 10:50:15 -07002581if __name__ != "__main__":
2582 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002583 sys.modules[ __name__ ] = MininetCliDriver()