blob: 1e22267add56aebca74b8aeb0536cbec026d5a36 [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
pingping-lin8244a3b2015-09-16 13:36:56 -07001238 def switch( self, **switchargs ):
1239 """
1240 start/stop a switch
1241 """
1242 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1243 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1244 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1245 command = "switch " + str( sw ) + " " + str( option )
1246 main.log.info( command )
1247 try:
1248 self.handle.sendline( command )
1249 self.handle.expect( "mininet>" )
1250 except pexpect.TIMEOUT:
1251 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1252 main.cleanup()
1253 main.exit()
1254 except pexpect.EOF:
1255 main.log.error( self.name + ": EOF exception found" )
1256 main.log.error( self.name + ": " + self.handle.before )
1257 main.cleanup()
1258 main.exit()
1259 return main.TRUE
1260
Jon Hall7eb38402015-01-08 17:19:54 -08001261 def yank( self, **yankargs ):
1262 """
1263 yank a mininet switch interface to a host"""
1264 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001265 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001266 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1267 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1268 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001269 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001270 response = self.execute(
1271 cmd=command,
1272 prompt="mininet>",
1273 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001274 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001275 main.log.error( self.name + ": EOF exception found" )
1276 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001277 main.cleanup()
1278 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001279 return main.TRUE
1280
Jon Hall7eb38402015-01-08 17:19:54 -08001281 def plug( self, **plugargs ):
1282 """
1283 plug the yanked mininet switch interface to a switch"""
1284 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001285 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001286 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1287 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1288 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001289 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001290 response = self.execute(
1291 cmd=command,
1292 prompt="mininet>",
1293 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001294 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001295 main.log.error( self.name + ": EOF exception found" )
1296 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001297 main.cleanup()
1298 main.exit()
adminbae64d82013-08-01 10:50:15 -07001299 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001300
Jon Hall7eb38402015-01-08 17:19:54 -08001301 def dpctl( self, **dpctlargs ):
1302 """
1303 Run dpctl command on all switches."""
1304 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001305 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001306 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1307 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1308 command = "dpctl " + cmd + " " + str( cmdargs )
1309 try:
1310 response = self.execute(
1311 cmd=command,
1312 prompt="mininet>",
1313 timeout=10 )
1314 except pexpect.EOF:
1315 main.log.error( self.name + ": EOF exception found" )
1316 main.log.error( self.name + ": " + self.handle.before )
1317 main.cleanup()
1318 main.exit()
1319 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001320
kelvin-onlabd3b64892015-01-20 13:26:24 -08001321 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001322 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001323 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001324 fileInput = path + '/lib/Mininet/INSTALL'
1325 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001326 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001327 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001328 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001329 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001330 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001331 return version
adminbae64d82013-08-01 10:50:15 -07001332
kelvin-onlabd3b64892015-01-20 13:26:24 -08001333 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001334 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001335 Parameters:
1336 sw: The name of an OVS switch. Example "s1"
1337 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001338 The output of the command from the mininet cli
1339 or main.FALSE on timeout"""
1340 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001341 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001342 response = self.execute(
1343 cmd=command,
1344 prompt="mininet>",
1345 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001346 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001347 return response
admin2a9548d2014-06-17 14:08:07 -07001348 else:
1349 return main.FALSE
1350 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001351 main.log.error( self.name + ": EOF exception found" )
1352 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001353 main.cleanup()
1354 main.exit()
adminbae64d82013-08-01 10:50:15 -07001355
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001356 def assignSwController( self, sw, ip, port="6633", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001357 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001358 Description:
1359 Assign switches to the controllers ( for ovs use only )
1360 Required:
1361 sw - Name of the switch. This can be a list or a string.
1362 ip - Ip addresses of controllers. This can be a list or a string.
1363 Optional:
1364 port - ONOS use port 6633, if no list of ports is passed, then
1365 the all the controller will use 6633 as their port number
1366 ptcp - ptcp number, This can be a string or a list that has
1367 the same length as switch. This is optional and not required
1368 when using ovs switches.
1369 NOTE: If switches and ptcp are given in a list type they should have the
1370 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1371 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001372
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001373 Return:
1374 Returns main.TRUE if mininet correctly assigned switches to
1375 controllers, otherwise it will return main.FALSE or an appropriate
1376 exception(s)
1377 """
1378 assignResult = main.TRUE
1379 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001380 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001381 command = "sh ovs-vsctl set-controller "
1382 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001383 try:
1384 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001385 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001386 if isinstance( port, types.StringType ) or \
1387 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001388 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001389 elif isinstance( port, types.ListType ):
1390 main.log.error( self.name + ": Only one controller " +
1391 "assigned and a list of ports has" +
1392 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001393 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001394 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001395 main.log.error( self.name + ": Invalid controller port " +
1396 "number. Please specify correct " +
1397 "controller port" )
1398 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001399
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001400 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001401 if isinstance( port, types.StringType ) or \
1402 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001403 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001404 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1405 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001406 elif isinstance( port, types.ListType ):
1407 if ( len( ip ) != len( port ) ):
1408 main.log.error( self.name + ": Port list = " +
1409 str( len( port ) ) +
1410 "should be the same as controller" +
1411 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001412 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001413 else:
1414 onosIp = ""
1415 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001416 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1417 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001418 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001419 main.log.error( self.name + ": Invalid controller port " +
1420 "number. Please specify correct " +
1421 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001422 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001423 else:
1424 main.log.error( self.name + ": Invalid ip address" )
1425 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001426
1427 if isinstance( sw, types.StringType ):
1428 command += sw + " "
1429 if ptcp:
1430 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001431 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001432 elif isinstance( ptcp, types.ListType ):
1433 main.log.error( self.name + ": Only one switch is " +
1434 "being set and multiple PTCP is " +
1435 "being passed " )
1436 else:
1437 main.log.error( self.name + ": Invalid PTCP" )
1438 ptcp = ""
1439 command += onosIp
1440 commandList.append( command )
1441
1442 elif isinstance( sw, types.ListType ):
1443 if ptcp:
1444 if isinstance( ptcp, types.ListType ):
1445 if len( ptcp ) != len( sw ):
1446 main.log.error( self.name + ": PTCP length = " +
1447 str( len( ptcp ) ) +
1448 " is not the same as switch" +
1449 " length = " +
1450 str( len( sw ) ) )
1451 return main.FALSE
1452 else:
1453 for switch, ptcpNum in zip( sw, ptcp ):
1454 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001455 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001456 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001457 tempCmd += onosIp
1458 commandList.append( tempCmd )
1459 else:
1460 main.log.error( self.name + ": Invalid PTCP" )
1461 return main.FALSE
1462 else:
1463 for switch in sw:
1464 tempCmd = "sh ovs-vsctl set-controller "
1465 tempCmd += switch + " " + onosIp
1466 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001467 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001468 main.log.error( self.name + ": Invalid switch type " )
1469 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001470
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001471 for cmd in commandList:
1472 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001473 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001474 except pexpect.TIMEOUT:
1475 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1476 return main.FALSE
1477 except pexpect.EOF:
1478 main.log.error( self.name + ": EOF exception found" )
1479 main.log.error( self.name + ": " + self.handle.before )
1480 main.cleanup()
1481 main.exit()
1482 return main.TRUE
1483 except Exception:
1484 main.log.exception( self.name + ": Uncaught exception!" )
1485 main.cleanup()
1486 main.exit()
adminbae64d82013-08-01 10:50:15 -07001487
kelvin-onlabd3b64892015-01-20 13:26:24 -08001488 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001489 """
1490 Removes the controller target from sw"""
1491 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001492 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001493 response = self.execute(
1494 cmd=command,
1495 prompt="mininet>",
1496 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001497 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001498 main.log.error( self.name + ": EOF exception found" )
1499 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001500 main.cleanup()
1501 main.exit()
1502 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001503 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001504
kelvin-onlabd3b64892015-01-20 13:26:24 -08001505 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001506 """
Jon Hallb1290e82014-11-18 16:17:48 -05001507 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001508 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001509 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001510 NOTE: cannot currently specify what type of switch
1511 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001512 sw = name of the new switch as a string
1513 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001514 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001515 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001516 """
1517 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001518 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001519 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001520 response = self.execute(
1521 cmd=command,
1522 prompt="mininet>",
1523 timeout=10 )
1524 if re.search( "already exists!", response ):
1525 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001526 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001527 elif re.search( "Error", response ):
1528 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001529 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001530 elif re.search( "usage:", response ):
1531 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001532 return main.FALSE
1533 else:
1534 return main.TRUE
1535 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001536 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001537 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001538 main.cleanup()
1539 main.exit()
1540
kelvin-onlabd3b64892015-01-20 13:26:24 -08001541 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001542 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001543 delete a switch from the mininet topology
1544 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001545 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001546 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001547 sw = name of the switch as a string
1548 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001549 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001550 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001551 response = self.execute(
1552 cmd=command,
1553 prompt="mininet>",
1554 timeout=10 )
1555 if re.search( "no switch named", response ):
1556 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001557 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001558 elif re.search( "Error", response ):
1559 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001560 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001561 elif re.search( "usage:", response ):
1562 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001563 return main.FALSE
1564 else:
1565 return main.TRUE
1566 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001567 main.log.error( self.name + ": EOF exception found" )
1568 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001569 main.cleanup()
1570 main.exit()
1571
kelvin-onlabd3b64892015-01-20 13:26:24 -08001572 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001573 """
1574 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001575 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001576 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001577 NOTE: cannot currently specify what type of link
1578 required params:
1579 node1 = the string node name of the first endpoint of the link
1580 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001581 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001582 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001583 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001584 response = self.execute(
1585 cmd=command,
1586 prompt="mininet>",
1587 timeout=10 )
1588 if re.search( "doesnt exist!", response ):
1589 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001590 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001591 elif re.search( "Error", response ):
1592 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001593 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001594 elif re.search( "usage:", response ):
1595 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001596 return main.FALSE
1597 else:
1598 return main.TRUE
1599 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001600 main.log.error( self.name + ": EOF exception found" )
1601 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001602 main.cleanup()
1603 main.exit()
1604
kelvin-onlabd3b64892015-01-20 13:26:24 -08001605 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001606 """
1607 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001608 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001609 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001610 required params:
1611 node1 = the string node name of the first endpoint of the link
1612 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001613 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001614 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001615 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001616 response = self.execute(
1617 cmd=command,
1618 prompt="mininet>",
1619 timeout=10 )
1620 if re.search( "no node named", response ):
1621 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001622 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001623 elif re.search( "Error", response ):
1624 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001625 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001626 elif re.search( "usage:", response ):
1627 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001628 return main.FALSE
1629 else:
1630 return main.TRUE
1631 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001632 main.log.error( self.name + ": EOF exception found" )
1633 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001634 main.cleanup()
1635 main.exit()
1636
kelvin-onlabd3b64892015-01-20 13:26:24 -08001637 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001638 """
Jon Hallb1290e82014-11-18 16:17:48 -05001639 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001640 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001641 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001642 NOTE: cannot currently specify what type of host
1643 required params:
1644 hostname = the string hostname
1645 optional key-value params
1646 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001647 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001648 """
1649 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001650 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001651 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001652 response = self.execute(
1653 cmd=command,
1654 prompt="mininet>",
1655 timeout=10 )
1656 if re.search( "already exists!", response ):
1657 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001658 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001659 elif re.search( "doesnt exists!", response ):
1660 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001661 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001662 elif re.search( "Error", response ):
1663 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001664 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001665 elif re.search( "usage:", response ):
1666 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001667 return main.FALSE
1668 else:
1669 return main.TRUE
1670 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001671 main.log.error( self.name + ": EOF exception found" )
1672 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001673 main.cleanup()
1674 main.exit()
1675
kelvin-onlabd3b64892015-01-20 13:26:24 -08001676 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001677 """
1678 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001679 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001680 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001681 NOTE: this uses a custom mn function
1682 required params:
1683 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001684 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001685 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001686 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001687 response = self.execute(
1688 cmd=command,
1689 prompt="mininet>",
1690 timeout=10 )
1691 if re.search( "no host named", response ):
1692 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001693 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001694 elif re.search( "Error", response ):
1695 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001696 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001697 elif re.search( "usage:", response ):
1698 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001699 return main.FALSE
1700 else:
1701 return main.TRUE
1702 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001703 main.log.error( self.name + ": EOF exception found" )
1704 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001705 main.cleanup()
1706 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001707
Jon Hall7eb38402015-01-08 17:19:54 -08001708 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001709 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001710 Called at the end of the test to stop the mininet and
1711 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001712 """
Jon Halld80cc142015-07-06 13:36:05 -07001713 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001714 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001715 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001716 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001717 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001718 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001719 elif i == 1:
1720 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001721 # print "Disconnecting Mininet"
1722 if self.handle:
1723 self.handle.sendline( "exit" )
1724 self.handle.expect( "exit" )
1725 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001726 else:
1727 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001728 return response
1729
Jon Halld80cc142015-07-06 13:36:05 -07001730 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001731 """
Jon Hall21270ac2015-02-16 17:59:55 -08001732 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001733 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001734 main.FALSE if the pexpect handle does not exist.
1735
Jon Halld61331b2015-02-17 16:35:47 -08001736 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001737 """
Jon Halld61331b2015-02-17 16:35:47 -08001738 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001739 response = ''
1740 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001741 try:
Jon Halld80cc142015-07-06 13:36:05 -07001742 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001743 i = self.handle.expect( [ 'mininet>',
1744 '\$',
1745 pexpect.EOF,
1746 pexpect.TIMEOUT ],
1747 timeout )
1748 if i == 0:
1749 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001750 response = self.execute(
1751 cmd="exit",
1752 prompt="(.*)",
1753 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001754 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001755 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001756 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001757
kelvin-onlab56a3f462015-02-06 14:04:43 -08001758 if i == 1:
1759 main.log.info( " Mininet trying to exit while not " +
1760 "in the mininet prompt" )
1761 elif i == 2:
1762 main.log.error( "Something went wrong exiting mininet" )
1763 elif i == 3: # timeout
1764 main.log.error( "Something went wrong exiting mininet " +
1765 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001766
Hari Krishnab35c6d02015-03-18 11:13:51 -07001767 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001768 self.handle.sendline( "" )
1769 self.handle.expect( '\$' )
1770 self.handle.sendline(
1771 "sudo kill -9 \`ps -ef | grep \"" +
1772 fileName +
1773 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001774 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001775 main.log.error( self.name + ": EOF exception found" )
1776 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001777 main.cleanup()
1778 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001779 else:
1780 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001781 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001782 return response
1783
Jon Halla5cb3412015-08-18 14:08:22 -07001784 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001785 """
1786 Description:
1787 Sends arp message from mininet host for hosts discovery
1788 Required:
1789 host - hosts name
1790 Optional:
1791 ip - ip address that does not exist in the network so there would
1792 be no reply.
1793 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001794 if ethDevice:
1795 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001796 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001797 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001798 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001799 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001800 i = self.handle.expect( [ "mininet>", "arping: " ] )
1801 if i == 0:
1802 return main.TRUE
1803 elif i == 1:
1804 response = self.handle.before + self.handle.after
1805 self.handle.expect( "mininet>" )
1806 response += self.handle.before + self.handle.after
1807 main.log.warn( "Error sending arping, output was: " +
1808 response )
1809 return main.FALSE
1810 except pexpect.TIMEOUT:
1811 main.log.error( self.name + ": TIMEOUT exception found" )
1812 main.log.warn( self.handle.before )
1813 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001814 except pexpect.EOF:
1815 main.log.error( self.name + ": EOF exception found" )
1816 main.log.error( self.name + ": " + self.handle.before )
1817 main.cleanup()
1818 main.exit()
admin07529932013-11-22 14:58:28 -08001819
Jon Hall7eb38402015-01-08 17:19:54 -08001820 def decToHex( self, num ):
1821 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001822
Jon Hall7eb38402015-01-08 17:19:54 -08001823 def getSwitchFlowCount( self, switch ):
1824 """
1825 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001826 if self.handle:
1827 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1828 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001829 response = self.execute(
1830 cmd=cmd,
1831 prompt="mininet>",
1832 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001833 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001834 main.log.error( self.name + ": EOF exception found" )
1835 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001836 main.cleanup()
1837 main.exit()
1838 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001839 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001840 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001841 main.log.info(
1842 "Couldn't find flows on switch %s, found: %s" %
1843 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001844 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001845 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001846 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001847 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001848
kelvin-onlabd3b64892015-01-20 13:26:24 -08001849 def checkFlows( self, sw, dumpFormat=None ):
1850 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001851 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001852 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001853 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001854 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001855 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001856 response = self.execute(
1857 cmd=command,
1858 prompt="mininet>",
1859 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001860 return response
1861 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001862 main.log.error( self.name + ": EOF exception found" )
1863 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001864 main.cleanup()
1865 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001866
Jon Hall9043c902015-07-30 14:23:44 -07001867 def getFlowTable( self, protoVersion, sw ):
1868 """
1869 Returns certain fields of an OVS flow table. Will force output to
1870 either OF 1.0 or 1.3 format for consistency.
1871
1872 TODO add option to look at cookies. ignoring them for now
1873
1874 NOTE: Use format to force consistent flow table output across
1875 versions
1876 """
1877 try:
1878 self.handle.sendline( "" )
1879 self.handle.expect( "mininet>" )
1880 command = "sh ovs-ofctl dump-flows " + sw
1881 if protoVersion == 1.0:
1882 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\
1883 " print $1 $3 $6 $7 $8}' | "
1884 elif protoVersion == 1.3:
1885 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\
1886 " print $1 $3 $6 $7}' | "
1887 else:
1888 main.log.error(
1889 "Unknown protoVersion in getFlowTable(). given: (" +
1890 str( type( protoVersion ) ) +
1891 ") '" + str( protoVersion ) + "'" )
1892 return None
1893 command += "cut -d ',' -f 2- | sort -n -k1 -r"
1894 self.handle.sendline( command )
1895 self.handle.expect( "sort" )
1896 self.handle.expect( "OFPST_FLOW" )
1897 response = self.handle.before
1898 return response
1899 except pexpect.EOF:
1900 main.log.error( self.name + ": EOF exception found" )
1901 main.log.error( self.name + ": " + self.handle.before )
1902 main.cleanup()
1903 main.exit()
1904 except pexpect.TIMEOUT:
1905 main.log.exception( self.name + ": Timeout exception: " )
1906 return None
1907
1908 def flowComp( self, flow1, flow2 ):
1909 if flow1 == flow2:
1910 return main.TRUE
1911 else:
1912 main.log.info( "Flow tables do not match, printing tables:" )
1913 main.log.info( "Flow Table 1:" )
1914 main.log.info( flow1 )
1915 main.log.info( "Flow Table 2:" )
1916 main.log.info( flow2 )
1917 return main.FALSE
1918
kelvin-onlabd3b64892015-01-20 13:26:24 -08001919 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001920 """
Jon Hallefbd9792015-03-05 16:11:36 -08001921 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001922 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001923 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001924 self.handle.sendline( "" )
1925 self.handle.expect( "mininet>" )
1926 self.handle.sendline(
1927 "sh sudo tcpdump -n -i " +
1928 intf +
1929 " " +
1930 port +
1931 " -w " +
1932 filename.strip() +
1933 " &" )
1934 self.handle.sendline( "" )
1935 i = self.handle.expect( [ 'No\ssuch\device',
1936 'listening\son',
1937 pexpect.TIMEOUT,
1938 "mininet>" ],
1939 timeout=10 )
1940 main.log.warn( self.handle.before + self.handle.after )
1941 self.handle.sendline( "" )
1942 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001943 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001944 main.log.error(
1945 self.name +
1946 ": tcpdump - No such device exists. " +
1947 "tcpdump attempted on: " +
1948 intf )
admin2a9548d2014-06-17 14:08:07 -07001949 return main.FALSE
1950 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001951 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001952 return main.TRUE
1953 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001954 main.log.error(
1955 self.name +
1956 ": tcpdump command timed out! Check interface name," +
1957 " given interface was: " +
1958 intf )
admin2a9548d2014-06-17 14:08:07 -07001959 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001960 elif i == 3:
1961 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001962 return main.TRUE
1963 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001964 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001965 return main.FALSE
1966 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001967 main.log.error( self.name + ": EOF exception found" )
1968 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001969 main.cleanup()
1970 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001971 except Exception:
1972 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001973 main.cleanup()
1974 main.exit()
1975
kelvin-onlabd3b64892015-01-20 13:26:24 -08001976 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001977 """
1978 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001979 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001980 self.handle.sendline( "sh sudo pkill tcpdump" )
1981 self.handle.expect( "mininet>" )
1982 self.handle.sendline( "" )
1983 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001984 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001985 main.log.error( self.name + ": EOF exception found" )
1986 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001987 main.cleanup()
1988 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001989 except Exception:
1990 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001991 main.cleanup()
1992 main.exit()
1993
Jon Halld80cc142015-07-06 13:36:05 -07001994 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001995 """
1996 Read ports from a Mininet switch.
1997
1998 Returns a json structure containing information about the
1999 ports of the given switch.
2000 """
2001 response = self.getInterfaces( nodeName )
2002 # TODO: Sanity check on response. log if no such switch exists
2003 ports = []
2004 for line in response.split( "\n" ):
2005 if not line.startswith( "name=" ):
2006 continue
2007 portVars = {}
2008 for var in line.split( "," ):
2009 key, value = var.split( "=" )
2010 portVars[ key ] = value
2011 isUp = portVars.pop( 'enabled', "True" )
2012 isUp = "True" in isUp
2013 if verbose:
2014 main.log.info( "Reading switch port %s(%s)" %
2015 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2016 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002017 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002018 mac = None
2019 ips = []
2020 ip = portVars[ 'ip' ]
2021 if ip == 'None':
2022 ip = None
2023 ips.append( ip )
2024 name = portVars[ 'name' ]
2025 if name == 'None':
2026 name = None
2027 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2028 if name == 'lo':
2029 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2030 else:
2031 portNo = re.search( portRe, name ).group( 'port' )
2032 ports.append( { 'of_port': portNo,
2033 'mac': str( mac ).replace( '\'', '' ),
2034 'name': name,
2035 'ips': ips,
2036 'enabled': isUp } )
2037 return ports
2038
Jon Halld80cc142015-07-06 13:36:05 -07002039 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002040 """
2041 Read switches from Mininet.
2042
2043 Returns a dictionary whose keys are the switch names and the value is
2044 a dictionary containing information about the switch.
2045 """
Jon Halla22481b2015-07-28 17:46:01 -07002046 # NOTE: To support new Mininet switch classes, just append the new
2047 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002048
Jon Halla22481b2015-07-28 17:46:01 -07002049 # Regex patterns to parse 'dump' output
2050 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002051 # <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 -07002052 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002053 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2054 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2055 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2056 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2057 swRE = r"<(?P<class>" + switchClasses + r")" +\
2058 r"(?P<options>\{.*\})?\s" +\
2059 r"(?P<name>[^:]+)\:\s" +\
2060 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2061 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002062 # Update mn port info
2063 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002064 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002065 dump = self.dump().split( "\n" )
2066 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002067 result = re.search( swRE, line, re.I )
2068 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002069 name = result.group( 'name' )
2070 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002071 pid = result.group( 'pid' )
2072 swClass = result.group( 'class' )
2073 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002074 if verbose:
2075 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2076 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002077 output[ name ] = { "dpid": dpid,
2078 "ports": ports,
2079 "swClass": swClass,
2080 "pid": pid,
2081 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002082 return output
2083
Jon Halld80cc142015-07-06 13:36:05 -07002084 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002085 """
2086 Read hosts from Mininet.
2087
2088 Returns a dictionary whose keys are the host names and the value is
2089 a dictionary containing information about the host.
2090 """
2091 # Regex patterns to parse dump output
2092 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002093 # <Host h1: pid=12725>
2094 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2095 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2096 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002097 # NOTE: Does not correctly match hosts with multi-links
2098 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2099 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002100 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002101 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002102 # update mn port info
2103 self.update()
2104 # Get mininet dump
2105 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002106 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002107 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002108 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002109 result = re.search( hostRE, line )
2110 name = result.group( 'name' )
2111 interfaces = []
2112 response = self.getInterfaces( name )
2113 # Populate interface info
2114 for line in response.split( "\n" ):
2115 if line.startswith( "name=" ):
2116 portVars = {}
2117 for var in line.split( "," ):
2118 key, value = var.split( "=" )
2119 portVars[ key ] = value
2120 isUp = portVars.pop( 'enabled', "True" )
2121 isUp = "True" in isUp
2122 if verbose:
2123 main.log.info( "Reading host port %s(%s)" %
2124 ( portVars[ 'name' ],
2125 portVars[ 'mac' ] ) )
2126 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002127 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002128 mac = None
2129 ips = []
2130 ip = portVars[ 'ip' ]
2131 if ip == 'None':
2132 ip = None
2133 ips.append( ip )
2134 intfName = portVars[ 'name' ]
2135 if name == 'None':
2136 name = None
2137 interfaces.append( {
2138 "name": intfName,
2139 "ips": ips,
2140 "mac": str( mac ),
2141 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002142 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002143 return hosts
2144
2145 def getLinks( self ):
2146 """
2147 Gathers information about current Mininet links. These links may not
2148 be up if one of the ports is down.
2149
2150 Returns a list of dictionaries with link endpoints.
2151
2152 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002153 { 'node1': str( node1 name )
2154 'node2': str( node2 name )
2155 'port1': str( port1 of_port )
2156 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002157 Note: The port number returned is the eth#, not necessarily the of_port
2158 number. In Mininet, for OVS switch, these should be the same. For
2159 hosts, this is just the eth#.
2160 """
2161 self.update()
2162 response = self.links().split( '\n' )
2163
2164 # Examples:
2165 # s1-eth3<->s2-eth1 (OK OK)
2166 # s13-eth3<->h27-eth0 (OK OK)
2167 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2168 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2169 links = []
2170 for line in response:
2171 match = re.search( linkRE, line )
2172 if match:
2173 node1 = match.group( 'node1' )
2174 node2 = match.group( 'node2' )
2175 port1 = match.group( 'port1' )
2176 port2 = match.group( 'port2' )
2177 links.append( { 'node1': node1,
2178 'node2': node2,
2179 'port1': port1,
2180 'port2': port2 } )
2181 return links
2182
2183 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002184 """
2185 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002186 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002187
Jon Hallafa8a472015-06-12 14:02:42 -07002188 Dependencies:
2189 1. numpy - "sudo pip install numpy"
2190 """
2191 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002192 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002193 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002194 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002195 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002196 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002197 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002198 main.log.error(
2199 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002200 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002201 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002202 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002203 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002204 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002205 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002206 onosDPIDs.append(
2207 switch[ 'id' ].replace(
2208 ":",
2209 '' ).replace(
2210 "of",
2211 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002212 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002213
Jon Hall7eb38402015-01-08 17:19:54 -08002214 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002215 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002216 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002217 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002218 main.log.error( str( list1 ) )
2219 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002220 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002221 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002222 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002223 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002224 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002225
Jon Hall7eb38402015-01-08 17:19:54 -08002226 # FIXME: this does not look for extra ports in ONOS, only checks that
2227 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002228 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002229
Jon Hall7eb38402015-01-08 17:19:54 -08002230 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002231 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002232 mnPorts = []
2233 onosPorts = []
2234 switchResult = main.TRUE
2235 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002236 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002237 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002238 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002239 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002240 if onosSwitch[ 'device' ][ 'id' ].replace(
2241 ':',
2242 '' ).replace(
2243 "of",
2244 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002245 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002246 if port[ 'isEnabled' ]:
2247 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002248 # onosPorts.append( 'local' )
2249 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002250 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002251 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002252 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002253 mnPorts.sort( key=float )
2254 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002255
kelvin-onlabd3b64892015-01-20 13:26:24 -08002256 mnPortsLog = mnPorts
2257 onosPortsLog = onosPorts
2258 mnPorts = [ x for x in mnPorts ]
2259 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002260
Jon Hall7eb38402015-01-08 17:19:54 -08002261 # TODO: handle other reserved port numbers besides LOCAL
2262 # NOTE: Reserved ports
2263 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2264 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002265 for mnPort in mnPortsLog:
2266 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002267 # don't set results to true here as this is just one of
2268 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002269 mnPorts.remove( mnPort )
2270 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002271
Jon Hall7eb38402015-01-08 17:19:54 -08002272 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002273 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002274 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002275 if 65534 in mnPorts:
2276 mnPorts.remove( 65534 )
2277 if long( uint64( -2 ) ) in onosPorts:
2278 onosPorts.remove( long( uint64( -2 ) ) )
2279 if len( mnPorts ): # the ports of this switch don't match
2280 switchResult = main.FALSE
2281 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2282 if len( onosPorts ): # the ports of this switch don't match
2283 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002284 main.log.warn(
2285 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002286 str( onosPorts ) )
2287 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002288 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002289 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002290 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002291 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2292 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2293 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002294 finalResults = finalResults and portsResults
2295 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002296
Jon Hallafa8a472015-06-12 14:02:42 -07002297 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002298 """
2299 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002300 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002301
Jon Hallafa8a472015-06-12 14:02:42 -07002302 """
Jon Hall7eb38402015-01-08 17:19:54 -08002303 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002304 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002305 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002306
Jon Halld80cc142015-07-06 13:36:05 -07002307 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002308 for l in links:
2309 try:
2310 node1 = switches[ l[ 'node1' ] ]
2311 node2 = switches[ l[ 'node2' ] ]
2312 enabled = True
2313 for port in node1[ 'ports' ]:
2314 if port[ 'of_port' ] == l[ 'port1' ]:
2315 enabled = enabled and port[ 'enabled' ]
2316 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002317 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002318 enabled = enabled and port[ 'enabled' ]
2319 if enabled:
2320 mnLinks.append( l )
2321 except KeyError:
2322 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002323 if 2 * len( mnLinks ) == len( onos ):
2324 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002325 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002326 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002327 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002328 "Mininet has " + str( len( mnLinks ) ) +
2329 " bidirectional links and ONOS has " +
2330 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002331
Jon Hall7eb38402015-01-08 17:19:54 -08002332 # iterate through MN links and check if an ONOS link exists in
2333 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002334 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002335 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002336 node1 = None
2337 port1 = None
2338 node2 = None
2339 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002340 firstDir = main.FALSE
2341 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002342 for swName, switch in switches.iteritems():
2343 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002344 node1 = switch[ 'dpid' ]
2345 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002346 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002347 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002348 if node1 is not None and node2 is not None:
2349 break
Jon Hallafa8a472015-06-12 14:02:42 -07002350 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002351 node2 = switch[ 'dpid' ]
2352 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002353 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002354 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002355 if node1 is not None and node2 is not None:
2356 break
2357
kelvin-onlabd3b64892015-01-20 13:26:24 -08002358 for onosLink in onos:
2359 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002360 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002361 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002362 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002363 onosPort1 = onosLink[ 'src' ][ 'port' ]
2364 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002365
Jon Hall72cf1dc2014-10-20 21:04:50 -04002366 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002367 if str( onosNode1 ) == str( node1 ) and str(
2368 onosNode2 ) == str( node2 ):
2369 if int( onosPort1 ) == int( port1 ) and int(
2370 onosPort2 ) == int( port2 ):
2371 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002372 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002373 main.log.warn(
2374 'The port numbers do not match for ' +
2375 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002376 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002377 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002378 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002379 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002380 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002381
2382 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002383 elif ( str( onosNode1 ) == str( node2 ) and
2384 str( onosNode2 ) == str( node1 ) ):
2385 if ( int( onosPort1 ) == int( port2 )
2386 and int( onosPort2 ) == int( port1 ) ):
2387 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002388 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002389 main.log.warn(
2390 'The port numbers do not match for ' +
2391 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002392 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002393 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002394 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002395 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002396 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002397 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002398 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002399 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002400 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002401 'ONOS does not have the link %s/%s -> %s/%s' %
2402 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002403 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002404 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002405 'ONOS does not have the link %s/%s -> %s/%s' %
2406 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002407 linkResults = linkResults and firstDir and secondDir
2408 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002409
Jon Hallafa8a472015-06-12 14:02:42 -07002410 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002411 """
Jon Hallafa8a472015-06-12 14:02:42 -07002412 Compare mn and onos Hosts.
2413 Since Mininet hosts are quiet, ONOS will only know of them when they
2414 speak. For this reason, we will only check that the hosts in ONOS
2415 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002416
Jon Hallafa8a472015-06-12 14:02:42 -07002417 Arguments:
2418 hostsJson: parsed json object from the onos hosts api
2419 Returns:
2420 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002421 import json
2422 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002423 for onosHost in hostsJson:
2424 onosMAC = onosHost[ 'mac' ].lower()
2425 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002426 for mnHost, info in hosts.iteritems():
2427 for mnIntf in info[ 'interfaces' ]:
2428 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002429 match = True
2430 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002431 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002432 pass # all is well
2433 else:
2434 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002435 main.log.error( "ONOS host " +
2436 onosHost[ 'id' ] +
2437 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002438 str( onosHost[ 'ipAddresses' ] ) +
2439 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002440 str( ip ) +
2441 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002442 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002443 onosHost,
2444 sort_keys=True,
2445 indent=4,
2446 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002447 main.log.info( output )
2448 hostResults = main.FALSE
2449 if not match:
2450 hostResults = main.FALSE
2451 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2452 "corresponding Mininet host." )
2453 output = json.dumps( onosHost,
2454 sort_keys=True,
2455 indent=4,
2456 separators=( ',', ': ' ) )
2457 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002458 return hostResults
2459
Jon Hallafa8a472015-06-12 14:02:42 -07002460 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002461 """
2462 Returns a list of all hosts
2463 Don't ask questions just use it"""
2464 self.handle.sendline( "" )
2465 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002466
Jon Hall7eb38402015-01-08 17:19:54 -08002467 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2468 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002469
kelvin-onlabd3b64892015-01-20 13:26:24 -08002470 handlePy = self.handle.before
2471 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2472 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002473
Jon Hall7eb38402015-01-08 17:19:54 -08002474 self.handle.sendline( "" )
2475 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002476
kelvin-onlabd3b64892015-01-20 13:26:24 -08002477 hostStr = handlePy.replace( "]", "" )
2478 hostStr = hostStr.replace( "'", "" )
2479 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002480 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002481 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002482
kelvin-onlabd3b64892015-01-20 13:26:24 -08002483 return hostList
adminbae64d82013-08-01 10:50:15 -07002484
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002485 def getSwitch( self ):
2486 """
2487 Returns a list of all switches
2488 Again, don't ask question just use it...
2489 """
2490 # get host list...
2491 hostList = self.getHosts()
2492 # Make host set
2493 hostSet = set( hostList )
2494
2495 # Getting all the nodes in mininet
2496 self.handle.sendline( "" )
2497 self.handle.expect( "mininet>" )
2498
2499 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2500 self.handle.expect( "mininet>" )
2501
2502 handlePy = self.handle.before
2503 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2504 handlePy = handlePy.rstrip()
2505
2506 self.handle.sendline( "" )
2507 self.handle.expect( "mininet>" )
2508
2509 nodesStr = handlePy.replace( "]", "" )
2510 nodesStr = nodesStr.replace( "'", "" )
2511 nodesStr = nodesStr.replace( "[", "" )
2512 nodesStr = nodesStr.replace( " ", "" )
2513 nodesList = nodesStr.split( "," )
2514
2515 nodesSet = set( nodesList )
2516 # discarding default controller(s) node
2517 nodesSet.discard( 'c0' )
2518 nodesSet.discard( 'c1' )
2519 nodesSet.discard( 'c2' )
2520
2521 switchSet = nodesSet - hostSet
2522 switchList = list( switchSet )
2523
2524 return switchList
2525
Jon Hall7eb38402015-01-08 17:19:54 -08002526 def update( self ):
2527 """
2528 updates the port address and status information for
2529 each port in mn"""
2530 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002531 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002532 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002533 self.handle.sendline( "" )
2534 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002535
Jon Hall7eb38402015-01-08 17:19:54 -08002536 self.handle.sendline( "update" )
2537 self.handle.expect( "update" )
2538 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002539
Jon Hall7eb38402015-01-08 17:19:54 -08002540 self.handle.sendline( "" )
2541 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002542
Jon Hallb1290e82014-11-18 16:17:48 -05002543 return main.TRUE
2544 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002545 main.log.error( self.name + ": EOF exception found" )
2546 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002547 main.cleanup()
2548 main.exit()
2549
Jon Halld80cc142015-07-06 13:36:05 -07002550 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002551 """
2552 Add vlan tag to a host.
2553 Dependencies:
2554 This class depends on the "vlan" package
2555 $ sudo apt-get install vlan
2556 Configuration:
2557 Load the 8021q module into the kernel
2558 $sudo modprobe 8021q
2559
2560 To make this setup permanent:
2561 $ sudo su -c 'echo "8021q" >> /etc/modules'
2562 """
2563 if self.handle:
2564 try:
Jon Halld80cc142015-07-06 13:36:05 -07002565 # get the ip address of the host
2566 main.log.info( "Get the ip address of the host" )
2567 ipaddr = self.getIPAddress( host )
2568 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002569
Jon Halld80cc142015-07-06 13:36:05 -07002570 # remove IP from interface intf
2571 # Ex: h1 ifconfig h1-eth0 inet 0
2572 main.log.info( "Remove IP from interface " )
2573 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2574 self.handle.sendline( cmd2 )
2575 self.handle.expect( "mininet>" )
2576 response = self.handle.before
2577 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002578
Jon Halld80cc142015-07-06 13:36:05 -07002579 # create VLAN interface
2580 # Ex: h1 vconfig add h1-eth0 100
2581 main.log.info( "Create Vlan" )
2582 cmd3 = host + " vconfig add " + intf + " " + vlan
2583 self.handle.sendline( cmd3 )
2584 self.handle.expect( "mininet>" )
2585 response = self.handle.before
2586 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002587
Jon Halld80cc142015-07-06 13:36:05 -07002588 # assign the host's IP to the VLAN interface
2589 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2590 main.log.info( "Assign the host IP to the vlan interface" )
2591 vintf = intf + "." + vlan
2592 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2593 self.handle.sendline( cmd4 )
2594 self.handle.expect( "mininet>" )
2595 response = self.handle.before
2596 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002597
2598 return main.TRUE
2599 except pexpect.EOF:
2600 main.log.error( self.name + ": EOF exception found" )
2601 main.log.error( self.name + ": " + self.handle.before )
2602 return main.FALSE
2603
adminbae64d82013-08-01 10:50:15 -07002604if __name__ != "__main__":
2605 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002606 sys.modules[ __name__ ] = MininetCliDriver()