blob: a3ddc2a54ac93595482746e4c53ec48b19da90ab [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
465 Returns main.FALSE if one or more of hosts specified cannot reach each other
466 """
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 "
471 for host in hostList:
472 listIndex = hostList.index( host )
473 # List of hosts to ping other than itself
474 pingList = hostList[ :listIndex ] + \
475 hostList[ ( listIndex + 1 ): ]
476
477 for temp in pingList:
478 # Current host pings all other hosts specified
479 pingCmd = str( host ) + cmd + prefix + str( temp[1:] )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700480 self.handle.sendline( pingCmd )
481 self.handle.expect( "mininet>" )
Hari Krishna9592fc82015-07-31 15:11:15 -0700482 response = self.handle.before
483 if re.search( ',\s0\%\spacket\sloss', response ):
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700484 main.log.info( str( host ) + " -> " + prefix + str( temp[1:] ) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700485 else:
486 main.log.info(
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700487 str( host ) + " -> X (" + prefix + str( temp[1:] ) + ") "
Hari Krishna9592fc82015-07-31 15:11:15 -0700488 " Destination Unreachable" )
489 main.log.error( "Response from Mininet: " + str( response ) )
490 # One of the host to host pair is unreachable
491 isReachable = main.FALSE
492 return isReachable
493
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700494 except pexpect.TIMEOUT:
495 main.log.exception( self.name + ": TIMEOUT exception" )
496 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700497 except pexpect.EOF:
498 main.log.error( self.name + ": EOF exception found" )
499 main.log.error( self.name + ": " + self.handle.before )
500 main.cleanup()
501 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700502 except Exception:
503 main.log.exception( self.name + ": Uncaught exception!" )
504 main.cleanup()
505 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700506
Jon Hall7eb38402015-01-08 17:19:54 -0800507 def pingHost( self, **pingParams ):
508 """
509 Ping from one mininet host to another
510 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800511 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800512 command = args[ "SRC" ] + " ping " + \
513 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700514 try:
Jon Hall61282e32015-03-19 11:34:11 -0700515 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800516 self.handle.sendline( command )
517 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700518 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800519 main.log.error(
520 self.name +
521 ": timeout when waiting for response from mininet" )
522 main.log.error( "response: " + str( self.handle.before ) )
523 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700524 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800525 main.log.error(
526 self.name +
527 ": timeout when waiting for response from mininet" )
528 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700529 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800530 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800531 main.log.error( self.name + ": EOF exception found" )
532 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700533 main.cleanup()
534 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800535 main.log.info( self.name + ": Ping Response: " + response )
536 if re.search( ',\s0\%\spacket\sloss', response ):
537 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800538 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700539 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800540 else:
541 main.log.error(
542 self.name +
543 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800544 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700545 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800546
Jon Hall7eb38402015-01-08 17:19:54 -0800547 def checkIP( self, host ):
548 """
549 Verifies the host's ip configured or not."""
550 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700551 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800552 response = self.execute(
553 cmd=host +
554 " ifconfig",
555 prompt="mininet>",
556 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800557 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800558 main.log.error( self.name + ": EOF exception found" )
559 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700560 main.cleanup()
561 main.exit()
adminbae64d82013-08-01 10:50:15 -0700562
Jon Hall7eb38402015-01-08 17:19:54 -0800563 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800564 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
565 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
566 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
567 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
568 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800569 # pattern = "inet addr:10.0.0.6"
570 if re.search( pattern, response ):
571 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700572 return main.TRUE
573 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800574 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700575 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800576 else:
577 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800578
Jon Hall7eb38402015-01-08 17:19:54 -0800579 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800580 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700581 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800582 response = self.execute(
583 cmd="h1 /usr/sbin/sshd -D&",
584 prompt="mininet>",
585 timeout=10 )
586 response = self.execute(
587 cmd="h4 /usr/sbin/sshd -D&",
588 prompt="mininet>",
589 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700590 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800591 vars( self )[ key ] = connectargs[ key ]
592 response = self.execute(
593 cmd="xterm h1 h4 ",
594 prompt="mininet>",
595 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800596 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800597 main.log.error( self.name + ": EOF exception found" )
598 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700599 main.cleanup()
600 main.exit()
adminbae64d82013-08-01 10:50:15 -0700601 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800602 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700603 if self.flag == 0:
604 self.flag = 1
605 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800606 else:
adminbae64d82013-08-01 10:50:15 -0700607 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800608
kelvin-onlaba1484582015-02-02 15:46:20 -0800609 def moveHost( self, host, oldSw, newSw, ):
610 """
611 Moves a host from one switch to another on the fly
612 Note: The intf between host and oldSw when detached
613 using detach(), will still show up in the 'net'
614 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700615 ( which is correct behavior since the interfaces
616 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800617 """
618 if self.handle:
619 try:
620 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700621 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800622 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800623 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800624 response = self.execute( cmd=cmd,
625 prompt="mininet>",
626 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700627
kelvin-onlaba1484582015-02-02 15:46:20 -0800628 # Determine hostintf and Oldswitchintf
629 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800630 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800631 print "cmd2= ", cmd
632 self.handle.sendline( cmd )
633 self.handle.expect( "mininet>" )
634
shahshreya73537862015-02-11 15:15:24 -0800635 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800636 cmd = "px ipaddr = hintf.IP()"
637 print "cmd3= ", cmd
638 self.handle.sendline( cmd )
639 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800640
641 cmd = "px macaddr = hintf.MAC()"
642 print "cmd3= ", cmd
643 self.handle.sendline( cmd )
644 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700645
kelvin-onlaba1484582015-02-02 15:46:20 -0800646 # Detach interface between oldSw-host
647 cmd = "px " + oldSw + ".detach( sintf )"
648 print "cmd4= ", cmd
649 self.handle.sendline( cmd )
650 self.handle.expect( "mininet>" )
651
652 # Add link between host-newSw
653 cmd = "py net.addLink(" + host + "," + newSw + ")"
654 print "cmd5= ", cmd
655 self.handle.sendline( cmd )
656 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700657
kelvin-onlaba1484582015-02-02 15:46:20 -0800658 # Determine hostintf and Newswitchintf
659 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800660 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800661 print "cmd6= ", cmd
662 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700663 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800664
665 # Attach interface between newSw-host
666 cmd = "px " + newSw + ".attach( sintf )"
667 print "cmd3= ", cmd
668 self.handle.sendline( cmd )
669 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700670
kelvin-onlaba1484582015-02-02 15:46:20 -0800671 # Set ipaddress of the host-newSw interface
672 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
673 print "cmd7 = ", cmd
674 self.handle.sendline( cmd )
675 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800676
677 # Set macaddress of the host-newSw interface
678 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
679 print "cmd8 = ", cmd
680 self.handle.sendline( cmd )
681 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700682
kelvin-onlaba1484582015-02-02 15:46:20 -0800683 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800684 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800685 self.handle.sendline( cmd )
686 self.handle.expect( "mininet>" )
687 print "output = ", self.handle.before
688
689 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800690 cmd = host + " ifconfig"
691 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800692 self.handle.sendline( cmd )
693 self.handle.expect( "mininet>" )
694 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700695
kelvin-onlaba1484582015-02-02 15:46:20 -0800696 return main.TRUE
697 except pexpect.EOF:
698 main.log.error( self.name + ": EOF exception found" )
699 main.log.error( self.name + ": " + self.handle.before )
700 return main.FALSE
701
Jon Hall7eb38402015-01-08 17:19:54 -0800702 def changeIP( self, host, intf, newIP, newNetmask ):
703 """
704 Changes the ip address of a host on the fly
705 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800706 if self.handle:
707 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800708 cmd = host + " ifconfig " + intf + " " + \
709 newIP + " " + 'netmask' + " " + newNetmask
710 self.handle.sendline( cmd )
711 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800712 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800713 main.log.info( "response = " + response )
714 main.log.info(
715 "Ip of host " +
716 host +
717 " changed to new IP " +
718 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800719 return main.TRUE
720 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800721 main.log.error( self.name + ": EOF exception found" )
722 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800723 return main.FALSE
724
Jon Hall7eb38402015-01-08 17:19:54 -0800725 def changeDefaultGateway( self, host, newGW ):
726 """
727 Changes the default gateway of a host
728 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800729 if self.handle:
730 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800731 cmd = host + " route add default gw " + newGW
732 self.handle.sendline( cmd )
733 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800734 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800735 main.log.info( "response = " + response )
736 main.log.info(
737 "Default gateway of host " +
738 host +
739 " changed to " +
740 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800741 return main.TRUE
742 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800743 main.log.error( self.name + ": EOF exception found" )
744 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800745 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800746
Jon Hall7eb38402015-01-08 17:19:54 -0800747 def addStaticMACAddress( self, host, GW, macaddr ):
748 """
Jon Hallefbd9792015-03-05 16:11:36 -0800749 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800750 if self.handle:
751 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800752 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
753 cmd = host + " arp -s " + GW + " " + macaddr
754 self.handle.sendline( cmd )
755 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800756 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800757 main.log.info( "response = " + response )
758 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800759 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800760 GW +
761 " changed to " +
762 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800763 return main.TRUE
764 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800765 main.log.error( self.name + ": EOF exception found" )
766 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800767 return main.FALSE
768
Jon Hall7eb38402015-01-08 17:19:54 -0800769 def verifyStaticGWandMAC( self, host ):
770 """
771 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800772 if self.handle:
773 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800774 # h1 arp -an
775 cmd = host + " arp -an "
776 self.handle.sendline( cmd )
777 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800778 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800779 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800780 return main.TRUE
781 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800782 main.log.error( self.name + ": EOF exception found" )
783 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800784 return main.FALSE
785
Jon Hall7eb38402015-01-08 17:19:54 -0800786 def getMacAddress( self, host ):
787 """
788 Verifies the host's ip configured or not."""
789 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700790 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800791 response = self.execute(
792 cmd=host +
793 " ifconfig",
794 prompt="mininet>",
795 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800796 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800797 main.log.error( self.name + ": EOF exception found" )
798 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700799 main.cleanup()
800 main.exit()
adminbae64d82013-08-01 10:50:15 -0700801
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700802 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800803 macAddressSearch = re.search( pattern, response, re.I )
804 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800805 main.log.info(
806 self.name +
807 ": Mac-Address of Host " +
808 host +
809 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800810 macAddress )
811 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700812 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800813 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700814
Jon Hall7eb38402015-01-08 17:19:54 -0800815 def getInterfaceMACAddress( self, host, interface ):
816 """
817 Return the IP address of the interface on the given host"""
818 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700819 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800820 response = self.execute( cmd=host + " ifconfig " + interface,
821 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800822 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800823 main.log.error( self.name + ": EOF exception found" )
824 main.log.error( self.name + ": " + self.handle.before )
825 main.cleanup()
826 main.exit()
827
828 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800829 macAddressSearch = re.search( pattern, response, re.I )
830 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800831 main.log.info( "No mac address found in %s" % response )
832 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800833 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800834 main.log.info(
835 "Mac-Address of " +
836 host +
837 ":" +
838 interface +
839 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800840 macAddress )
841 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800842 else:
843 main.log.error( "Connection failed to the host" )
844
845 def getIPAddress( self, host ):
846 """
847 Verifies the host's ip configured or not."""
848 if self.handle:
849 try:
850 response = self.execute(
851 cmd=host +
852 " ifconfig",
853 prompt="mininet>",
854 timeout=10 )
855 except pexpect.EOF:
856 main.log.error( self.name + ": EOF exception found" )
857 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700858 main.cleanup()
859 main.exit()
adminbae64d82013-08-01 10:50:15 -0700860
861 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800862 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800863 main.log.info(
864 self.name +
865 ": IP-Address of Host " +
866 host +
867 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800868 ipAddressSearch.group( 1 ) )
869 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800870 else:
871 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800872
Jon Hall7eb38402015-01-08 17:19:54 -0800873 def getSwitchDPID( self, switch ):
874 """
875 return the datapath ID of the switch"""
876 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700877 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700878 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800879 response = self.execute(
880 cmd=cmd,
881 prompt="mininet>",
882 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800883 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800884 main.log.error( self.name + ": EOF exception found" )
885 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700886 main.cleanup()
887 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800888 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800889 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700890 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800891 main.log.info(
892 "Couldn't find DPID for switch %s, found: %s" %
893 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700894 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800895 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700896 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800897 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700898
Jon Hall7eb38402015-01-08 17:19:54 -0800899 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700900 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800901 self.handle.sendline( "" )
902 self.expect( "mininet>" )
903 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700904 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800905 response = self.execute(
906 cmd=cmd,
907 prompt="mininet>",
908 timeout=10 )
909 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700910 response = self.handle.before
911 return response
912 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800913 main.log.error( self.name + ": EOF exception found" )
914 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700915 main.cleanup()
916 main.exit()
917
Jon Hall7eb38402015-01-08 17:19:54 -0800918 def getInterfaces( self, node ):
919 """
920 return information dict about interfaces connected to the node"""
921 if self.handle:
922 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800923 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700924 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700925 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800926 response = self.execute(
927 cmd=cmd,
928 prompt="mininet>",
929 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800930 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800931 main.log.error( self.name + ": EOF exception found" )
932 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700933 main.cleanup()
934 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700935 return response
936 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800937 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700938
Jon Hall7eb38402015-01-08 17:19:54 -0800939 def dump( self ):
940 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700941 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800942 response = self.execute(
943 cmd='dump',
944 prompt='mininet>',
945 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800946 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800947 main.log.error( self.name + ": EOF exception found" )
948 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700949 main.cleanup()
950 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700951 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800952
Jon Hall7eb38402015-01-08 17:19:54 -0800953 def intfs( self ):
954 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700955 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800956 response = self.execute(
957 cmd='intfs',
958 prompt='mininet>',
959 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800960 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800961 main.log.error( self.name + ": EOF exception found" )
962 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700963 main.cleanup()
964 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700965 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800966
Jon Hall7eb38402015-01-08 17:19:54 -0800967 def net( self ):
968 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700969 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800970 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800971 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800972 main.log.error( self.name + ": EOF exception found" )
973 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700974 main.cleanup()
975 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700976 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800977
Jon Hallafa8a472015-06-12 14:02:42 -0700978 def links( self ):
979 main.log.info( self.name + ": List network links" )
980 try:
981 response = self.execute( cmd='links', prompt='mininet>',
982 timeout=10 )
983 except pexpect.EOF:
984 main.log.error( self.name + ": EOF exception found" )
985 main.log.error( self.name + ": " + self.handle.before )
986 main.cleanup()
987 main.exit()
988 return response
989
GlennRC61321f22015-07-16 13:36:54 -0700990 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -0700991 '''
992 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -0700993
kelvin-onlab7cce9382015-07-17 10:21:03 -0700994 @parm:
995 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
996 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
997 '''
998 for host1 in hosts:
999 for host2 in hosts:
1000 if host1 != host2:
1001 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1002 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001003
1004 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001005 '''
1006 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1007 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001008
kelvin-onlab7cce9382015-07-17 10:21:03 -07001009 @parm:
1010 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1011 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1012 '''
1013 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1014 try:
1015 # Setup the mininet command
1016 cmd1 = 'iperf ' + host1 + " " + host2
1017 self.handle.sendline( cmd1 )
1018 outcome = self.handle.expect( "mininet>", timeout )
1019 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001020
kelvin-onlab7cce9382015-07-17 10:21:03 -07001021 # checks if there are results in the mininet response
1022 if "Results:" in response:
1023 main.log.report(self.name + ": iperf test completed")
1024 # parse the mn results
1025 response = response.split("\r\n")
1026 response = response[len(response)-2]
1027 response = response.split(": ")
1028 response = response[len(response)-1]
1029 response = response.replace("[", "")
1030 response = response.replace("]", "")
1031 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001032
kelvin-onlab7cce9382015-07-17 10:21:03 -07001033 # this is the bandwith two and from the two hosts
1034 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001035
kelvin-onlab7cce9382015-07-17 10:21:03 -07001036 # there should be two elements in the bandwidth list
1037 # ['host1 to host2', 'host2 to host1"]
1038 if len(bandwidth) == 2:
1039 main.log.report(self.name + ": iperf test successful")
1040 return main.TRUE
1041 else:
1042 main.log.error(self.name + ": invalid iperf results")
1043 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001044 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001045 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001046 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001047
GlennRC61321f22015-07-16 13:36:54 -07001048 except pexpect.TIMEOUT:
1049 main.log.error( self.name + ": TIMEOUT exception found")
1050 main.log.error( self.name + ": Exception: Cannot connect to iperf on port 5001" )
1051 return main.FALSE
1052
Jon Hallfbc828e2015-01-06 17:30:19 -08001053 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001054 main.log.error( self.name + ": EOF exception found" )
1055 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001056 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001057 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001058
1059 def iperfudpAll(self, hosts, bandwidth="10M"):
1060 '''
1061 Runs the iperfudp function with a given set of hosts and specified
1062 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001063
GlennRC61321f22015-07-16 13:36:54 -07001064 @param:
1065 bandwidth: the targeted bandwidth, in megabits ('M')
1066 '''
1067 for host1 in hosts:
1068 for host2 in hosts:
1069 if host1 != host2:
1070 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1071 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1072
1073 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1074
kelvin-onlab7cce9382015-07-17 10:21:03 -07001075 '''
1076 Creates an iperf UDP test with a specific bandwidth.
1077 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001078
kelvin-onlab7cce9382015-07-17 10:21:03 -07001079 @param:
1080 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1081 '''
1082 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1083 try:
1084 # setup the mininet command
1085 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1086 self.handle.sendline(cmd)
1087 self.handle.expect("mininet>")
1088 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001089
kelvin-onlab7cce9382015-07-17 10:21:03 -07001090 # check if there are in results in the mininet response
1091 if "Results:" in response:
1092 main.log.report(self.name + ": iperfudp test completed")
1093 # parse the results
1094 response = response.split("\r\n")
1095 response = response[len(response)-2]
1096 response = response.split(": ")
1097 response = response[len(response)-1]
1098 response = response.replace("[", "")
1099 response = response.replace("]", "")
1100 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001101
kelvin-onlab7cce9382015-07-17 10:21:03 -07001102 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001103
kelvin-onlab7cce9382015-07-17 10:21:03 -07001104 # check to see if there are at least three entries
1105 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1106 if len(mnBandwidth) == 3:
1107 # if one entry is blank then something is wrong
1108 for item in mnBandwidth:
1109 if item == "":
1110 main.log.error(self.name + ": Could not parse iperf output")
1111 main.log.error(self.name + ": invalid iperfudp results")
1112 return main.FALSE
1113 # otherwise results are vaild
1114 main.log.report(self.name + ": iperfudp test successful")
1115 return main.TRUE
1116 else:
1117 main.log.error(self.name + ": invalid iperfudp results")
1118 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001119
kelvin-onlab7cce9382015-07-17 10:21:03 -07001120 except pexpect.EOF:
1121 main.log.error( self.name + ": EOF exception found" )
1122 main.log.error( self.name + ": " + self.handle.before )
1123 main.cleanup()
1124 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001125
Jon Hall7eb38402015-01-08 17:19:54 -08001126 def nodes( self ):
1127 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001128 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001129 response = self.execute(
1130 cmd='nodes',
1131 prompt='mininet>',
1132 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001133 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001134 main.log.error( self.name + ": EOF exception found" )
1135 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001136 main.cleanup()
1137 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001138 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001139
Jon Hall7eb38402015-01-08 17:19:54 -08001140 def pingpair( self ):
1141 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001142 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001143 response = self.execute(
1144 cmd='pingpair',
1145 prompt='mininet>',
1146 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001147 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001148 main.log.error( self.name + ": EOF exception found" )
1149 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001150 main.cleanup()
1151 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001152
Jon Hall7eb38402015-01-08 17:19:54 -08001153 if re.search( ',\s0\%\spacket\sloss', response ):
1154 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001155 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -07001156 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001157 else:
1158 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001159 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -07001160 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001161
Jon Hall7eb38402015-01-08 17:19:54 -08001162 def link( self, **linkargs ):
1163 """
1164 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001165 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001166 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1167 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1168 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1169 main.log.info(
1170 "Bring link between '" +
1171 end1 +
1172 "' and '" +
1173 end2 +
1174 "' '" +
1175 option +
1176 "'" )
1177 command = "link " + \
1178 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001179 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001180 self.handle.sendline( command )
1181 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001182 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001183 main.log.error( self.name + ": EOF exception found" )
1184 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001185 main.cleanup()
1186 main.exit()
adminbae64d82013-08-01 10:50:15 -07001187 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001188
Jon Hall7eb38402015-01-08 17:19:54 -08001189 def yank( self, **yankargs ):
1190 """
1191 yank a mininet switch interface to a host"""
1192 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001193 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001194 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1195 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1196 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001197 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001198 response = self.execute(
1199 cmd=command,
1200 prompt="mininet>",
1201 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001202 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001203 main.log.error( self.name + ": EOF exception found" )
1204 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001205 main.cleanup()
1206 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001207 return main.TRUE
1208
Jon Hall7eb38402015-01-08 17:19:54 -08001209 def plug( self, **plugargs ):
1210 """
1211 plug the yanked mininet switch interface to a switch"""
1212 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001213 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001214 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1215 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1216 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001217 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001218 response = self.execute(
1219 cmd=command,
1220 prompt="mininet>",
1221 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001222 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001223 main.log.error( self.name + ": EOF exception found" )
1224 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001225 main.cleanup()
1226 main.exit()
adminbae64d82013-08-01 10:50:15 -07001227 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001228
Jon Hall7eb38402015-01-08 17:19:54 -08001229 def dpctl( self, **dpctlargs ):
1230 """
1231 Run dpctl command on all switches."""
1232 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001233 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001234 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1235 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1236 command = "dpctl " + cmd + " " + str( cmdargs )
1237 try:
1238 response = self.execute(
1239 cmd=command,
1240 prompt="mininet>",
1241 timeout=10 )
1242 except pexpect.EOF:
1243 main.log.error( self.name + ": EOF exception found" )
1244 main.log.error( self.name + ": " + self.handle.before )
1245 main.cleanup()
1246 main.exit()
1247 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001248
kelvin-onlabd3b64892015-01-20 13:26:24 -08001249 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001250 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001251 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001252 fileInput = path + '/lib/Mininet/INSTALL'
1253 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001254 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001255 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001256 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001257 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001258 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001259 return version
adminbae64d82013-08-01 10:50:15 -07001260
kelvin-onlabd3b64892015-01-20 13:26:24 -08001261 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001262 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001263 Parameters:
1264 sw: The name of an OVS switch. Example "s1"
1265 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001266 The output of the command from the mininet cli
1267 or main.FALSE on timeout"""
1268 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001269 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001270 response = self.execute(
1271 cmd=command,
1272 prompt="mininet>",
1273 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001274 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001275 return response
admin2a9548d2014-06-17 14:08:07 -07001276 else:
1277 return main.FALSE
1278 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001279 main.log.error( self.name + ": EOF exception found" )
1280 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001281 main.cleanup()
1282 main.exit()
adminbae64d82013-08-01 10:50:15 -07001283
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001284 def assignSwController( self, sw, ip, port="6633", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001285 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001286 Description:
1287 Assign switches to the controllers ( for ovs use only )
1288 Required:
1289 sw - Name of the switch. This can be a list or a string.
1290 ip - Ip addresses of controllers. This can be a list or a string.
1291 Optional:
1292 port - ONOS use port 6633, if no list of ports is passed, then
1293 the all the controller will use 6633 as their port number
1294 ptcp - ptcp number, This can be a string or a list that has
1295 the same length as switch. This is optional and not required
1296 when using ovs switches.
1297 NOTE: If switches and ptcp are given in a list type they should have the
1298 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1299 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001300
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001301 Return:
1302 Returns main.TRUE if mininet correctly assigned switches to
1303 controllers, otherwise it will return main.FALSE or an appropriate
1304 exception(s)
1305 """
1306 assignResult = main.TRUE
1307 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001308 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001309 command = "sh ovs-vsctl set-controller "
1310 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001311 try:
1312 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001313 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001314 if isinstance( port, types.StringType ) or \
1315 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001316 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001317 elif isinstance( port, types.ListType ):
1318 main.log.error( self.name + ": Only one controller " +
1319 "assigned and a list of ports has" +
1320 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001321 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001322 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001323 main.log.error( self.name + ": Invalid controller port " +
1324 "number. Please specify correct " +
1325 "controller port" )
1326 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001327
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001328 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001329 if isinstance( port, types.StringType ) or \
1330 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001331 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001332 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1333 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001334 elif isinstance( port, types.ListType ):
1335 if ( len( ip ) != len( port ) ):
1336 main.log.error( self.name + ": Port list = " +
1337 str( len( port ) ) +
1338 "should be the same as controller" +
1339 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001340 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001341 else:
1342 onosIp = ""
1343 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001344 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1345 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001346 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001347 main.log.error( self.name + ": Invalid controller port " +
1348 "number. Please specify correct " +
1349 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001350 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001351 else:
1352 main.log.error( self.name + ": Invalid ip address" )
1353 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001354
1355 if isinstance( sw, types.StringType ):
1356 command += sw + " "
1357 if ptcp:
1358 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001359 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001360 elif isinstance( ptcp, types.ListType ):
1361 main.log.error( self.name + ": Only one switch is " +
1362 "being set and multiple PTCP is " +
1363 "being passed " )
1364 else:
1365 main.log.error( self.name + ": Invalid PTCP" )
1366 ptcp = ""
1367 command += onosIp
1368 commandList.append( command )
1369
1370 elif isinstance( sw, types.ListType ):
1371 if ptcp:
1372 if isinstance( ptcp, types.ListType ):
1373 if len( ptcp ) != len( sw ):
1374 main.log.error( self.name + ": PTCP length = " +
1375 str( len( ptcp ) ) +
1376 " is not the same as switch" +
1377 " length = " +
1378 str( len( sw ) ) )
1379 return main.FALSE
1380 else:
1381 for switch, ptcpNum in zip( sw, ptcp ):
1382 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001383 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001384 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001385 tempCmd += onosIp
1386 commandList.append( tempCmd )
1387 else:
1388 main.log.error( self.name + ": Invalid PTCP" )
1389 return main.FALSE
1390 else:
1391 for switch in sw:
1392 tempCmd = "sh ovs-vsctl set-controller "
1393 tempCmd += switch + " " + onosIp
1394 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001395 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001396 main.log.error( self.name + ": Invalid switch type " )
1397 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001398
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001399 for cmd in commandList:
1400 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001401 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001402 except pexpect.TIMEOUT:
1403 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1404 return main.FALSE
1405 except pexpect.EOF:
1406 main.log.error( self.name + ": EOF exception found" )
1407 main.log.error( self.name + ": " + self.handle.before )
1408 main.cleanup()
1409 main.exit()
1410 return main.TRUE
1411 except Exception:
1412 main.log.exception( self.name + ": Uncaught exception!" )
1413 main.cleanup()
1414 main.exit()
adminbae64d82013-08-01 10:50:15 -07001415
kelvin-onlabd3b64892015-01-20 13:26:24 -08001416 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001417 """
1418 Removes the controller target from sw"""
1419 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001420 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001421 response = self.execute(
1422 cmd=command,
1423 prompt="mininet>",
1424 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001425 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001426 main.log.error( self.name + ": EOF exception found" )
1427 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001428 main.cleanup()
1429 main.exit()
1430 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001431 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001432
kelvin-onlabd3b64892015-01-20 13:26:24 -08001433 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001434 """
Jon Hallb1290e82014-11-18 16:17:48 -05001435 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001436 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001437 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001438 NOTE: cannot currently specify what type of switch
1439 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001440 sw = name of the new switch as a string
1441 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001442 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001443 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001444 """
1445 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001446 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001447 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001448 response = self.execute(
1449 cmd=command,
1450 prompt="mininet>",
1451 timeout=10 )
1452 if re.search( "already exists!", response ):
1453 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001454 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001455 elif re.search( "Error", response ):
1456 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001457 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001458 elif re.search( "usage:", response ):
1459 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001460 return main.FALSE
1461 else:
1462 return main.TRUE
1463 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001464 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001465 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001466 main.cleanup()
1467 main.exit()
1468
kelvin-onlabd3b64892015-01-20 13:26:24 -08001469 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001470 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001471 delete a switch from the mininet topology
1472 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001473 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001474 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001475 sw = name of the switch as a string
1476 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001477 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001478 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001479 response = self.execute(
1480 cmd=command,
1481 prompt="mininet>",
1482 timeout=10 )
1483 if re.search( "no switch named", response ):
1484 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001485 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001486 elif re.search( "Error", response ):
1487 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001488 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001489 elif re.search( "usage:", response ):
1490 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001491 return main.FALSE
1492 else:
1493 return main.TRUE
1494 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001495 main.log.error( self.name + ": EOF exception found" )
1496 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001497 main.cleanup()
1498 main.exit()
1499
kelvin-onlabd3b64892015-01-20 13:26:24 -08001500 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001501 """
1502 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001503 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001504 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001505 NOTE: cannot currently specify what type of link
1506 required params:
1507 node1 = the string node name of the first endpoint of the link
1508 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001509 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001510 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001511 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001512 response = self.execute(
1513 cmd=command,
1514 prompt="mininet>",
1515 timeout=10 )
1516 if re.search( "doesnt exist!", response ):
1517 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001518 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001519 elif re.search( "Error", response ):
1520 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001521 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001522 elif re.search( "usage:", response ):
1523 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001524 return main.FALSE
1525 else:
1526 return main.TRUE
1527 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001528 main.log.error( self.name + ": EOF exception found" )
1529 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001530 main.cleanup()
1531 main.exit()
1532
kelvin-onlabd3b64892015-01-20 13:26:24 -08001533 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001534 """
1535 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001536 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001537 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001538 required params:
1539 node1 = the string node name of the first endpoint of the link
1540 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001541 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001542 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001543 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001544 response = self.execute(
1545 cmd=command,
1546 prompt="mininet>",
1547 timeout=10 )
1548 if re.search( "no node named", response ):
1549 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001550 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001551 elif re.search( "Error", response ):
1552 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001553 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001554 elif re.search( "usage:", response ):
1555 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001556 return main.FALSE
1557 else:
1558 return main.TRUE
1559 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001560 main.log.error( self.name + ": EOF exception found" )
1561 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001562 main.cleanup()
1563 main.exit()
1564
kelvin-onlabd3b64892015-01-20 13:26:24 -08001565 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001566 """
Jon Hallb1290e82014-11-18 16:17:48 -05001567 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001568 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001569 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001570 NOTE: cannot currently specify what type of host
1571 required params:
1572 hostname = the string hostname
1573 optional key-value params
1574 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001575 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001576 """
1577 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001578 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001579 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001580 response = self.execute(
1581 cmd=command,
1582 prompt="mininet>",
1583 timeout=10 )
1584 if re.search( "already exists!", response ):
1585 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001586 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001587 elif re.search( "doesnt exists!", response ):
1588 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001589 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001590 elif re.search( "Error", response ):
1591 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001592 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001593 elif re.search( "usage:", response ):
1594 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001595 return main.FALSE
1596 else:
1597 return main.TRUE
1598 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001599 main.log.error( self.name + ": EOF exception found" )
1600 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001601 main.cleanup()
1602 main.exit()
1603
kelvin-onlabd3b64892015-01-20 13:26:24 -08001604 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001605 """
1606 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001607 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001608 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001609 NOTE: this uses a custom mn function
1610 required params:
1611 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001612 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001613 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001614 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001615 response = self.execute(
1616 cmd=command,
1617 prompt="mininet>",
1618 timeout=10 )
1619 if re.search( "no host named", response ):
1620 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001621 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001622 elif re.search( "Error", response ):
1623 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001624 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001625 elif re.search( "usage:", response ):
1626 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001627 return main.FALSE
1628 else:
1629 return main.TRUE
1630 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001631 main.log.error( self.name + ": EOF exception found" )
1632 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001633 main.cleanup()
1634 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001635
Jon Hall7eb38402015-01-08 17:19:54 -08001636 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001637 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001638 Called at the end of the test to stop the mininet and
1639 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001640 """
Jon Halld80cc142015-07-06 13:36:05 -07001641 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001642 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001643 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001644 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001645 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001646 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001647 elif i == 1:
1648 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001649 # print "Disconnecting Mininet"
1650 if self.handle:
1651 self.handle.sendline( "exit" )
1652 self.handle.expect( "exit" )
1653 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001654 else:
1655 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001656 return response
1657
Jon Halld80cc142015-07-06 13:36:05 -07001658 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001659 """
Jon Hall21270ac2015-02-16 17:59:55 -08001660 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001661 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001662 main.FALSE if the pexpect handle does not exist.
1663
Jon Halld61331b2015-02-17 16:35:47 -08001664 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001665 """
Jon Halld61331b2015-02-17 16:35:47 -08001666 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001667 response = ''
1668 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001669 try:
Jon Halld80cc142015-07-06 13:36:05 -07001670 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001671 i = self.handle.expect( [ 'mininet>',
1672 '\$',
1673 pexpect.EOF,
1674 pexpect.TIMEOUT ],
1675 timeout )
1676 if i == 0:
1677 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001678 response = self.execute(
1679 cmd="exit",
1680 prompt="(.*)",
1681 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001682 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001683 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001684 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001685
kelvin-onlab56a3f462015-02-06 14:04:43 -08001686 if i == 1:
1687 main.log.info( " Mininet trying to exit while not " +
1688 "in the mininet prompt" )
1689 elif i == 2:
1690 main.log.error( "Something went wrong exiting mininet" )
1691 elif i == 3: # timeout
1692 main.log.error( "Something went wrong exiting mininet " +
1693 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001694
Hari Krishnab35c6d02015-03-18 11:13:51 -07001695 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001696 self.handle.sendline( "" )
1697 self.handle.expect( '\$' )
1698 self.handle.sendline(
1699 "sudo kill -9 \`ps -ef | grep \"" +
1700 fileName +
1701 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001702 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 Hall6094a362014-04-11 14:46:56 -07001705 main.cleanup()
1706 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001707 else:
1708 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001709 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001710 return response
1711
Jon Halla5cb3412015-08-18 14:08:22 -07001712 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001713 """
1714 Description:
1715 Sends arp message from mininet host for hosts discovery
1716 Required:
1717 host - hosts name
1718 Optional:
1719 ip - ip address that does not exist in the network so there would
1720 be no reply.
1721 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001722 if ethDevice:
1723 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001724 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001725 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001726 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001727 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001728 i = self.handle.expect( [ "mininet>", "arping: " ] )
1729 if i == 0:
1730 return main.TRUE
1731 elif i == 1:
1732 response = self.handle.before + self.handle.after
1733 self.handle.expect( "mininet>" )
1734 response += self.handle.before + self.handle.after
1735 main.log.warn( "Error sending arping, output was: " +
1736 response )
1737 return main.FALSE
1738 except pexpect.TIMEOUT:
1739 main.log.error( self.name + ": TIMEOUT exception found" )
1740 main.log.warn( self.handle.before )
1741 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001742 except pexpect.EOF:
1743 main.log.error( self.name + ": EOF exception found" )
1744 main.log.error( self.name + ": " + self.handle.before )
1745 main.cleanup()
1746 main.exit()
admin07529932013-11-22 14:58:28 -08001747
Jon Hall7eb38402015-01-08 17:19:54 -08001748 def decToHex( self, num ):
1749 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001750
Jon Hall7eb38402015-01-08 17:19:54 -08001751 def getSwitchFlowCount( self, switch ):
1752 """
1753 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001754 if self.handle:
1755 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1756 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001757 response = self.execute(
1758 cmd=cmd,
1759 prompt="mininet>",
1760 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001761 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001762 main.log.error( self.name + ": EOF exception found" )
1763 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001764 main.cleanup()
1765 main.exit()
1766 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001767 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001768 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001769 main.log.info(
1770 "Couldn't find flows on switch %s, found: %s" %
1771 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001772 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001773 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001774 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001775 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001776
kelvin-onlabd3b64892015-01-20 13:26:24 -08001777 def checkFlows( self, sw, dumpFormat=None ):
1778 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001779 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001780 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001781 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001782 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001783 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001784 response = self.execute(
1785 cmd=command,
1786 prompt="mininet>",
1787 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001788 return response
1789 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001790 main.log.error( self.name + ": EOF exception found" )
1791 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001792 main.cleanup()
1793 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001794
Jon Hall9043c902015-07-30 14:23:44 -07001795 def getFlowTable( self, protoVersion, sw ):
1796 """
1797 Returns certain fields of an OVS flow table. Will force output to
1798 either OF 1.0 or 1.3 format for consistency.
1799
1800 TODO add option to look at cookies. ignoring them for now
1801
1802 NOTE: Use format to force consistent flow table output across
1803 versions
1804 """
1805 try:
1806 self.handle.sendline( "" )
1807 self.handle.expect( "mininet>" )
1808 command = "sh ovs-ofctl dump-flows " + sw
1809 if protoVersion == 1.0:
1810 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\
1811 " print $1 $3 $6 $7 $8}' | "
1812 elif protoVersion == 1.3:
1813 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\
1814 " print $1 $3 $6 $7}' | "
1815 else:
1816 main.log.error(
1817 "Unknown protoVersion in getFlowTable(). given: (" +
1818 str( type( protoVersion ) ) +
1819 ") '" + str( protoVersion ) + "'" )
1820 return None
1821 command += "cut -d ',' -f 2- | sort -n -k1 -r"
1822 self.handle.sendline( command )
1823 self.handle.expect( "sort" )
1824 self.handle.expect( "OFPST_FLOW" )
1825 response = self.handle.before
1826 return response
1827 except pexpect.EOF:
1828 main.log.error( self.name + ": EOF exception found" )
1829 main.log.error( self.name + ": " + self.handle.before )
1830 main.cleanup()
1831 main.exit()
1832 except pexpect.TIMEOUT:
1833 main.log.exception( self.name + ": Timeout exception: " )
1834 return None
1835
1836 def flowComp( self, flow1, flow2 ):
1837 if flow1 == flow2:
1838 return main.TRUE
1839 else:
1840 main.log.info( "Flow tables do not match, printing tables:" )
1841 main.log.info( "Flow Table 1:" )
1842 main.log.info( flow1 )
1843 main.log.info( "Flow Table 2:" )
1844 main.log.info( flow2 )
1845 return main.FALSE
1846
kelvin-onlabd3b64892015-01-20 13:26:24 -08001847 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001848 """
Jon Hallefbd9792015-03-05 16:11:36 -08001849 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001850 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001851 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001852 self.handle.sendline( "" )
1853 self.handle.expect( "mininet>" )
1854 self.handle.sendline(
1855 "sh sudo tcpdump -n -i " +
1856 intf +
1857 " " +
1858 port +
1859 " -w " +
1860 filename.strip() +
1861 " &" )
1862 self.handle.sendline( "" )
1863 i = self.handle.expect( [ 'No\ssuch\device',
1864 'listening\son',
1865 pexpect.TIMEOUT,
1866 "mininet>" ],
1867 timeout=10 )
1868 main.log.warn( self.handle.before + self.handle.after )
1869 self.handle.sendline( "" )
1870 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001871 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001872 main.log.error(
1873 self.name +
1874 ": tcpdump - No such device exists. " +
1875 "tcpdump attempted on: " +
1876 intf )
admin2a9548d2014-06-17 14:08:07 -07001877 return main.FALSE
1878 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001879 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001880 return main.TRUE
1881 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001882 main.log.error(
1883 self.name +
1884 ": tcpdump command timed out! Check interface name," +
1885 " given interface was: " +
1886 intf )
admin2a9548d2014-06-17 14:08:07 -07001887 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001888 elif i == 3:
1889 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001890 return main.TRUE
1891 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001892 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001893 return main.FALSE
1894 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001895 main.log.error( self.name + ": EOF exception found" )
1896 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001897 main.cleanup()
1898 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001899 except Exception:
1900 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001901 main.cleanup()
1902 main.exit()
1903
kelvin-onlabd3b64892015-01-20 13:26:24 -08001904 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001905 """
1906 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001907 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001908 self.handle.sendline( "sh sudo pkill tcpdump" )
1909 self.handle.expect( "mininet>" )
1910 self.handle.sendline( "" )
1911 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001912 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001913 main.log.error( self.name + ": EOF exception found" )
1914 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001915 main.cleanup()
1916 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001917 except Exception:
1918 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001919 main.cleanup()
1920 main.exit()
1921
Jon Halld80cc142015-07-06 13:36:05 -07001922 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001923 """
1924 Read ports from a Mininet switch.
1925
1926 Returns a json structure containing information about the
1927 ports of the given switch.
1928 """
1929 response = self.getInterfaces( nodeName )
1930 # TODO: Sanity check on response. log if no such switch exists
1931 ports = []
1932 for line in response.split( "\n" ):
1933 if not line.startswith( "name=" ):
1934 continue
1935 portVars = {}
1936 for var in line.split( "," ):
1937 key, value = var.split( "=" )
1938 portVars[ key ] = value
1939 isUp = portVars.pop( 'enabled', "True" )
1940 isUp = "True" in isUp
1941 if verbose:
1942 main.log.info( "Reading switch port %s(%s)" %
1943 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1944 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001945 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001946 mac = None
1947 ips = []
1948 ip = portVars[ 'ip' ]
1949 if ip == 'None':
1950 ip = None
1951 ips.append( ip )
1952 name = portVars[ 'name' ]
1953 if name == 'None':
1954 name = None
1955 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
1956 if name == 'lo':
1957 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
1958 else:
1959 portNo = re.search( portRe, name ).group( 'port' )
1960 ports.append( { 'of_port': portNo,
1961 'mac': str( mac ).replace( '\'', '' ),
1962 'name': name,
1963 'ips': ips,
1964 'enabled': isUp } )
1965 return ports
1966
Jon Halld80cc142015-07-06 13:36:05 -07001967 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001968 """
1969 Read switches from Mininet.
1970
1971 Returns a dictionary whose keys are the switch names and the value is
1972 a dictionary containing information about the switch.
1973 """
Jon Halla22481b2015-07-28 17:46:01 -07001974 # NOTE: To support new Mininet switch classes, just append the new
1975 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07001976
Jon Halla22481b2015-07-28 17:46:01 -07001977 # Regex patterns to parse 'dump' output
1978 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07001979 # <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 -07001980 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07001981 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
1982 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
1983 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
1984 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
1985 swRE = r"<(?P<class>" + switchClasses + r")" +\
1986 r"(?P<options>\{.*\})?\s" +\
1987 r"(?P<name>[^:]+)\:\s" +\
1988 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
1989 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07001990 # Update mn port info
1991 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07001992 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001993 dump = self.dump().split( "\n" )
1994 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07001995 result = re.search( swRE, line, re.I )
1996 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07001997 name = result.group( 'name' )
1998 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07001999 pid = result.group( 'pid' )
2000 swClass = result.group( 'class' )
2001 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002002 if verbose:
2003 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2004 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002005 output[ name ] = { "dpid": dpid,
2006 "ports": ports,
2007 "swClass": swClass,
2008 "pid": pid,
2009 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002010 return output
2011
Jon Halld80cc142015-07-06 13:36:05 -07002012 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002013 """
2014 Read hosts from Mininet.
2015
2016 Returns a dictionary whose keys are the host names and the value is
2017 a dictionary containing information about the host.
2018 """
2019 # Regex patterns to parse dump output
2020 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002021 # <Host h1: pid=12725>
2022 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2023 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2024 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002025 # NOTE: Does not correctly match hosts with multi-links
2026 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2027 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002028 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002029 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002030 # update mn port info
2031 self.update()
2032 # Get mininet dump
2033 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002034 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002035 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002036 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002037 result = re.search( hostRE, line )
2038 name = result.group( 'name' )
2039 interfaces = []
2040 response = self.getInterfaces( name )
2041 # Populate interface info
2042 for line in response.split( "\n" ):
2043 if line.startswith( "name=" ):
2044 portVars = {}
2045 for var in line.split( "," ):
2046 key, value = var.split( "=" )
2047 portVars[ key ] = value
2048 isUp = portVars.pop( 'enabled', "True" )
2049 isUp = "True" in isUp
2050 if verbose:
2051 main.log.info( "Reading host port %s(%s)" %
2052 ( portVars[ 'name' ],
2053 portVars[ 'mac' ] ) )
2054 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002055 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002056 mac = None
2057 ips = []
2058 ip = portVars[ 'ip' ]
2059 if ip == 'None':
2060 ip = None
2061 ips.append( ip )
2062 intfName = portVars[ 'name' ]
2063 if name == 'None':
2064 name = None
2065 interfaces.append( {
2066 "name": intfName,
2067 "ips": ips,
2068 "mac": str( mac ),
2069 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002070 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002071 return hosts
2072
2073 def getLinks( self ):
2074 """
2075 Gathers information about current Mininet links. These links may not
2076 be up if one of the ports is down.
2077
2078 Returns a list of dictionaries with link endpoints.
2079
2080 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002081 { 'node1': str( node1 name )
2082 'node2': str( node2 name )
2083 'port1': str( port1 of_port )
2084 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002085 Note: The port number returned is the eth#, not necessarily the of_port
2086 number. In Mininet, for OVS switch, these should be the same. For
2087 hosts, this is just the eth#.
2088 """
2089 self.update()
2090 response = self.links().split( '\n' )
2091
2092 # Examples:
2093 # s1-eth3<->s2-eth1 (OK OK)
2094 # s13-eth3<->h27-eth0 (OK OK)
2095 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2096 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2097 links = []
2098 for line in response:
2099 match = re.search( linkRE, line )
2100 if match:
2101 node1 = match.group( 'node1' )
2102 node2 = match.group( 'node2' )
2103 port1 = match.group( 'port1' )
2104 port2 = match.group( 'port2' )
2105 links.append( { 'node1': node1,
2106 'node2': node2,
2107 'port1': port1,
2108 'port2': port2 } )
2109 return links
2110
2111 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002112 """
2113 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002114 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002115
Jon Hallafa8a472015-06-12 14:02:42 -07002116 Dependencies:
2117 1. numpy - "sudo pip install numpy"
2118 """
2119 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002120 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002121 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002122 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002123 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002124 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002125 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002126 main.log.error(
2127 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002128 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002129 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002130 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002131 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002132 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002133 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002134 onosDPIDs.append(
2135 switch[ 'id' ].replace(
2136 ":",
2137 '' ).replace(
2138 "of",
2139 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002140 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002141
Jon Hall7eb38402015-01-08 17:19:54 -08002142 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002143 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002144 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002145 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002146 main.log.error( str( list1 ) )
2147 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002148 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002149 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002150 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002151 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002152 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002153
Jon Hall7eb38402015-01-08 17:19:54 -08002154 # FIXME: this does not look for extra ports in ONOS, only checks that
2155 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002156 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002157
Jon Hall7eb38402015-01-08 17:19:54 -08002158 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002159 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002160 mnPorts = []
2161 onosPorts = []
2162 switchResult = main.TRUE
2163 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002164 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002165 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002166 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002167 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002168 if onosSwitch[ 'device' ][ 'id' ].replace(
2169 ':',
2170 '' ).replace(
2171 "of",
2172 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002173 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002174 if port[ 'isEnabled' ]:
2175 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002176 # onosPorts.append( 'local' )
2177 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002178 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002179 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002180 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002181 mnPorts.sort( key=float )
2182 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002183
kelvin-onlabd3b64892015-01-20 13:26:24 -08002184 mnPortsLog = mnPorts
2185 onosPortsLog = onosPorts
2186 mnPorts = [ x for x in mnPorts ]
2187 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002188
Jon Hall7eb38402015-01-08 17:19:54 -08002189 # TODO: handle other reserved port numbers besides LOCAL
2190 # NOTE: Reserved ports
2191 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2192 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002193 for mnPort in mnPortsLog:
2194 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002195 # don't set results to true here as this is just one of
2196 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002197 mnPorts.remove( mnPort )
2198 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002199
Jon Hall7eb38402015-01-08 17:19:54 -08002200 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002201 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002202 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002203 if 65534 in mnPorts:
2204 mnPorts.remove( 65534 )
2205 if long( uint64( -2 ) ) in onosPorts:
2206 onosPorts.remove( long( uint64( -2 ) ) )
2207 if len( mnPorts ): # the ports of this switch don't match
2208 switchResult = main.FALSE
2209 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2210 if len( onosPorts ): # the ports of this switch don't match
2211 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002212 main.log.warn(
2213 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002214 str( onosPorts ) )
2215 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002216 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002217 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002218 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002219 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2220 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2221 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002222 finalResults = finalResults and portsResults
2223 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002224
Jon Hallafa8a472015-06-12 14:02:42 -07002225 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002226 """
2227 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002228 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002229
Jon Hallafa8a472015-06-12 14:02:42 -07002230 """
Jon Hall7eb38402015-01-08 17:19:54 -08002231 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002232 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002233 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002234
Jon Halld80cc142015-07-06 13:36:05 -07002235 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002236 for l in links:
2237 try:
2238 node1 = switches[ l[ 'node1' ] ]
2239 node2 = switches[ l[ 'node2' ] ]
2240 enabled = True
2241 for port in node1[ 'ports' ]:
2242 if port[ 'of_port' ] == l[ 'port1' ]:
2243 enabled = enabled and port[ 'enabled' ]
2244 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002245 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002246 enabled = enabled and port[ 'enabled' ]
2247 if enabled:
2248 mnLinks.append( l )
2249 except KeyError:
2250 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002251 if 2 * len( mnLinks ) == len( onos ):
2252 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002253 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002254 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002255 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002256 "Mininet has " + str( len( mnLinks ) ) +
2257 " bidirectional links and ONOS has " +
2258 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002259
Jon Hall7eb38402015-01-08 17:19:54 -08002260 # iterate through MN links and check if an ONOS link exists in
2261 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002262 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002263 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002264 node1 = None
2265 port1 = None
2266 node2 = None
2267 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002268 firstDir = main.FALSE
2269 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002270 for swName, switch in switches.iteritems():
2271 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002272 node1 = switch[ 'dpid' ]
2273 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002274 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002275 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002276 if node1 is not None and node2 is not None:
2277 break
Jon Hallafa8a472015-06-12 14:02:42 -07002278 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002279 node2 = switch[ 'dpid' ]
2280 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002281 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002282 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002283 if node1 is not None and node2 is not None:
2284 break
2285
kelvin-onlabd3b64892015-01-20 13:26:24 -08002286 for onosLink in onos:
2287 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002288 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002289 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002290 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002291 onosPort1 = onosLink[ 'src' ][ 'port' ]
2292 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002293
Jon Hall72cf1dc2014-10-20 21:04:50 -04002294 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002295 if str( onosNode1 ) == str( node1 ) and str(
2296 onosNode2 ) == str( node2 ):
2297 if int( onosPort1 ) == int( port1 ) and int(
2298 onosPort2 ) == int( port2 ):
2299 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002300 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002301 main.log.warn(
2302 'The port numbers do not match for ' +
2303 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002304 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002305 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002306 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002307 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002308 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002309
2310 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002311 elif ( str( onosNode1 ) == str( node2 ) and
2312 str( onosNode2 ) == str( node1 ) ):
2313 if ( int( onosPort1 ) == int( port2 )
2314 and int( onosPort2 ) == int( port1 ) ):
2315 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002316 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002317 main.log.warn(
2318 'The port numbers do not match for ' +
2319 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002320 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002321 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002322 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002323 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002324 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002325 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002326 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002327 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002328 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002329 'ONOS does not have the link %s/%s -> %s/%s' %
2330 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002331 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002332 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002333 'ONOS does not have the link %s/%s -> %s/%s' %
2334 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002335 linkResults = linkResults and firstDir and secondDir
2336 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002337
Jon Hallafa8a472015-06-12 14:02:42 -07002338 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002339 """
Jon Hallafa8a472015-06-12 14:02:42 -07002340 Compare mn and onos Hosts.
2341 Since Mininet hosts are quiet, ONOS will only know of them when they
2342 speak. For this reason, we will only check that the hosts in ONOS
2343 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002344
Jon Hallafa8a472015-06-12 14:02:42 -07002345 Arguments:
2346 hostsJson: parsed json object from the onos hosts api
2347 Returns:
2348 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002349 import json
2350 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002351 for onosHost in hostsJson:
2352 onosMAC = onosHost[ 'mac' ].lower()
2353 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002354 for mnHost, info in hosts.iteritems():
2355 for mnIntf in info[ 'interfaces' ]:
2356 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002357 match = True
2358 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002359 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002360 pass # all is well
2361 else:
2362 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002363 main.log.error( "ONOS host " +
2364 onosHost[ 'id' ] +
2365 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002366 str( onosHost[ 'ipAddresses' ] ) +
2367 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002368 str( ip ) +
2369 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002370 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002371 onosHost,
2372 sort_keys=True,
2373 indent=4,
2374 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002375 main.log.info( output )
2376 hostResults = main.FALSE
2377 if not match:
2378 hostResults = main.FALSE
2379 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2380 "corresponding Mininet host." )
2381 output = json.dumps( onosHost,
2382 sort_keys=True,
2383 indent=4,
2384 separators=( ',', ': ' ) )
2385 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002386 return hostResults
2387
Jon Hallafa8a472015-06-12 14:02:42 -07002388 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002389 """
2390 Returns a list of all hosts
2391 Don't ask questions just use it"""
2392 self.handle.sendline( "" )
2393 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002394
Jon Hall7eb38402015-01-08 17:19:54 -08002395 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2396 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002397
kelvin-onlabd3b64892015-01-20 13:26:24 -08002398 handlePy = self.handle.before
2399 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2400 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002401
Jon Hall7eb38402015-01-08 17:19:54 -08002402 self.handle.sendline( "" )
2403 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002404
kelvin-onlabd3b64892015-01-20 13:26:24 -08002405 hostStr = handlePy.replace( "]", "" )
2406 hostStr = hostStr.replace( "'", "" )
2407 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002408 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002409 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002410
kelvin-onlabd3b64892015-01-20 13:26:24 -08002411 return hostList
adminbae64d82013-08-01 10:50:15 -07002412
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002413 def getSwitch( self ):
2414 """
2415 Returns a list of all switches
2416 Again, don't ask question just use it...
2417 """
2418 # get host list...
2419 hostList = self.getHosts()
2420 # Make host set
2421 hostSet = set( hostList )
2422
2423 # Getting all the nodes in mininet
2424 self.handle.sendline( "" )
2425 self.handle.expect( "mininet>" )
2426
2427 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2428 self.handle.expect( "mininet>" )
2429
2430 handlePy = self.handle.before
2431 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2432 handlePy = handlePy.rstrip()
2433
2434 self.handle.sendline( "" )
2435 self.handle.expect( "mininet>" )
2436
2437 nodesStr = handlePy.replace( "]", "" )
2438 nodesStr = nodesStr.replace( "'", "" )
2439 nodesStr = nodesStr.replace( "[", "" )
2440 nodesStr = nodesStr.replace( " ", "" )
2441 nodesList = nodesStr.split( "," )
2442
2443 nodesSet = set( nodesList )
2444 # discarding default controller(s) node
2445 nodesSet.discard( 'c0' )
2446 nodesSet.discard( 'c1' )
2447 nodesSet.discard( 'c2' )
2448
2449 switchSet = nodesSet - hostSet
2450 switchList = list( switchSet )
2451
2452 return switchList
2453
Jon Hall7eb38402015-01-08 17:19:54 -08002454 def update( self ):
2455 """
2456 updates the port address and status information for
2457 each port in mn"""
2458 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002459 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002460 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002461 self.handle.sendline( "" )
2462 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002463
Jon Hall7eb38402015-01-08 17:19:54 -08002464 self.handle.sendline( "update" )
2465 self.handle.expect( "update" )
2466 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002467
Jon Hall7eb38402015-01-08 17:19:54 -08002468 self.handle.sendline( "" )
2469 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002470
Jon Hallb1290e82014-11-18 16:17:48 -05002471 return main.TRUE
2472 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002473 main.log.error( self.name + ": EOF exception found" )
2474 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002475 main.cleanup()
2476 main.exit()
2477
Jon Halld80cc142015-07-06 13:36:05 -07002478 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002479 """
2480 Add vlan tag to a host.
2481 Dependencies:
2482 This class depends on the "vlan" package
2483 $ sudo apt-get install vlan
2484 Configuration:
2485 Load the 8021q module into the kernel
2486 $sudo modprobe 8021q
2487
2488 To make this setup permanent:
2489 $ sudo su -c 'echo "8021q" >> /etc/modules'
2490 """
2491 if self.handle:
2492 try:
Jon Halld80cc142015-07-06 13:36:05 -07002493 # get the ip address of the host
2494 main.log.info( "Get the ip address of the host" )
2495 ipaddr = self.getIPAddress( host )
2496 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002497
Jon Halld80cc142015-07-06 13:36:05 -07002498 # remove IP from interface intf
2499 # Ex: h1 ifconfig h1-eth0 inet 0
2500 main.log.info( "Remove IP from interface " )
2501 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2502 self.handle.sendline( cmd2 )
2503 self.handle.expect( "mininet>" )
2504 response = self.handle.before
2505 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002506
Jon Halld80cc142015-07-06 13:36:05 -07002507 # create VLAN interface
2508 # Ex: h1 vconfig add h1-eth0 100
2509 main.log.info( "Create Vlan" )
2510 cmd3 = host + " vconfig add " + intf + " " + vlan
2511 self.handle.sendline( cmd3 )
2512 self.handle.expect( "mininet>" )
2513 response = self.handle.before
2514 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002515
Jon Halld80cc142015-07-06 13:36:05 -07002516 # assign the host's IP to the VLAN interface
2517 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2518 main.log.info( "Assign the host IP to the vlan interface" )
2519 vintf = intf + "." + vlan
2520 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2521 self.handle.sendline( cmd4 )
2522 self.handle.expect( "mininet>" )
2523 response = self.handle.before
2524 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002525
2526 return main.TRUE
2527 except pexpect.EOF:
2528 main.log.error( self.name + ": EOF exception found" )
2529 main.log.error( self.name + ": " + self.handle.before )
2530 return main.FALSE
2531
adminbae64d82013-08-01 10:50:15 -07002532if __name__ != "__main__":
2533 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002534 sys.modules[ __name__ ] = MininetCliDriver()