blob: fdf305ab76142d55d71d7049417d6a6ea0dbca5a [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
Hari Krishna012a1c12015-08-25 14:23:58 -0700530 if re.search( ',\s0\%\spacket\sloss', response ):
531 main.log.info( self.name + ": no packets lost, host is reachable" )
532 return main.TRUE
533 else:
534 main.log.error(
535 self.name +
536 ": PACKET LOST, HOST IS NOT REACHABLE" )
537 return main.FALSE
538
Jon Hallfbc828e2015-01-06 17:30:19 -0800539 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800540 main.log.error( self.name + ": EOF exception found" )
541 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700542 main.cleanup()
543 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700544 except Exception:
545 main.log.exception( self.name + ": Uncaught exception!" )
546 main.cleanup()
547 main.exit()
548
549 def ping6pair( self, **pingParams ):
550 """
551 IPv6 Ping between a pair of mininet hosts
552 Currently the only supported Params are: SRC , TARGET
553 FLOWLABEL and -I (src interface) will be added later after running some tests.
554 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
555 """
556 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
557 command = args[ "SRC" ] + " ping6 " + \
558 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
559 try:
560 main.log.info( "Sending: " + command )
561 self.handle.sendline( command )
562 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
563 if i == 1:
564 main.log.error(
565 self.name +
566 ": timeout when waiting for response from mininet" )
567 main.log.error( "response: " + str( self.handle.before ) )
568 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
569 if i == 1:
570 main.log.error(
571 self.name +
572 ": timeout when waiting for response from mininet" )
573 main.log.error( "response: " + str( self.handle.before ) )
574 response = self.handle.before
575 main.log.info( self.name + ": Ping Response: " + response )
576 if re.search( ',\s0\%\spacket\sloss', response ):
577 main.log.info( self.name + ": no packets lost, host is reachable" )
578 return main.TRUE
579 else:
580 main.log.error(
581 self.name +
582 ": PACKET LOST, HOST IS NOT REACHABLE" )
583 return main.FALSE
584
585 except pexpect.EOF:
586 main.log.error( self.name + ": EOF exception found" )
587 main.log.error( self.name + ": " + self.handle.before )
588 main.cleanup()
589 main.exit()
590 except Exception:
591 main.log.exception( self.name + ": Uncaught exception!" )
592 main.cleanup()
593 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800594
Jon Hall7eb38402015-01-08 17:19:54 -0800595 def checkIP( self, host ):
596 """
597 Verifies the host's ip configured or not."""
598 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700599 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800600 response = self.execute(
601 cmd=host +
602 " ifconfig",
603 prompt="mininet>",
604 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800605 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800606 main.log.error( self.name + ": EOF exception found" )
607 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700608 main.cleanup()
609 main.exit()
adminbae64d82013-08-01 10:50:15 -0700610
Jon Hall7eb38402015-01-08 17:19:54 -0800611 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800612 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
613 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
614 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
615 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
616 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800617 # pattern = "inet addr:10.0.0.6"
618 if re.search( pattern, response ):
619 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700620 return main.TRUE
621 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800622 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700623 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800624 else:
625 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800626
Jon Hall7eb38402015-01-08 17:19:54 -0800627 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800628 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700629 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800630 response = self.execute(
631 cmd="h1 /usr/sbin/sshd -D&",
632 prompt="mininet>",
633 timeout=10 )
634 response = self.execute(
635 cmd="h4 /usr/sbin/sshd -D&",
636 prompt="mininet>",
637 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700638 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800639 vars( self )[ key ] = connectargs[ key ]
640 response = self.execute(
641 cmd="xterm h1 h4 ",
642 prompt="mininet>",
643 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800644 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800645 main.log.error( self.name + ": EOF exception found" )
646 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700647 main.cleanup()
648 main.exit()
adminbae64d82013-08-01 10:50:15 -0700649 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800650 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700651 if self.flag == 0:
652 self.flag = 1
653 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800654 else:
adminbae64d82013-08-01 10:50:15 -0700655 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800656
kelvin-onlaba1484582015-02-02 15:46:20 -0800657 def moveHost( self, host, oldSw, newSw, ):
658 """
659 Moves a host from one switch to another on the fly
660 Note: The intf between host and oldSw when detached
661 using detach(), will still show up in the 'net'
662 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700663 ( which is correct behavior since the interfaces
664 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800665 """
666 if self.handle:
667 try:
668 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700669 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800670 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800671 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800672 response = self.execute( cmd=cmd,
673 prompt="mininet>",
674 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700675
kelvin-onlaba1484582015-02-02 15:46:20 -0800676 # Determine hostintf and Oldswitchintf
677 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800678 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800679 print "cmd2= ", cmd
680 self.handle.sendline( cmd )
681 self.handle.expect( "mininet>" )
682
shahshreya73537862015-02-11 15:15:24 -0800683 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800684 cmd = "px ipaddr = hintf.IP()"
685 print "cmd3= ", cmd
686 self.handle.sendline( cmd )
687 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800688
689 cmd = "px macaddr = hintf.MAC()"
690 print "cmd3= ", cmd
691 self.handle.sendline( cmd )
692 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700693
kelvin-onlaba1484582015-02-02 15:46:20 -0800694 # Detach interface between oldSw-host
695 cmd = "px " + oldSw + ".detach( sintf )"
696 print "cmd4= ", cmd
697 self.handle.sendline( cmd )
698 self.handle.expect( "mininet>" )
699
700 # Add link between host-newSw
701 cmd = "py net.addLink(" + host + "," + newSw + ")"
702 print "cmd5= ", cmd
703 self.handle.sendline( cmd )
704 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700705
kelvin-onlaba1484582015-02-02 15:46:20 -0800706 # Determine hostintf and Newswitchintf
707 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800708 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800709 print "cmd6= ", cmd
710 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700711 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800712
713 # Attach interface between newSw-host
714 cmd = "px " + newSw + ".attach( sintf )"
715 print "cmd3= ", cmd
716 self.handle.sendline( cmd )
717 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700718
kelvin-onlaba1484582015-02-02 15:46:20 -0800719 # Set ipaddress of the host-newSw interface
720 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
721 print "cmd7 = ", cmd
722 self.handle.sendline( cmd )
723 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800724
725 # Set macaddress of the host-newSw interface
726 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
727 print "cmd8 = ", cmd
728 self.handle.sendline( cmd )
729 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700730
kelvin-onlaba1484582015-02-02 15:46:20 -0800731 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800732 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800733 self.handle.sendline( cmd )
734 self.handle.expect( "mininet>" )
735 print "output = ", self.handle.before
736
737 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800738 cmd = host + " ifconfig"
739 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800740 self.handle.sendline( cmd )
741 self.handle.expect( "mininet>" )
742 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700743
kelvin-onlaba1484582015-02-02 15:46:20 -0800744 return main.TRUE
745 except pexpect.EOF:
746 main.log.error( self.name + ": EOF exception found" )
747 main.log.error( self.name + ": " + self.handle.before )
748 return main.FALSE
749
Jon Hall7eb38402015-01-08 17:19:54 -0800750 def changeIP( self, host, intf, newIP, newNetmask ):
751 """
752 Changes the ip address of a host on the fly
753 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800754 if self.handle:
755 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800756 cmd = host + " ifconfig " + intf + " " + \
757 newIP + " " + 'netmask' + " " + newNetmask
758 self.handle.sendline( cmd )
759 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800760 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800761 main.log.info( "response = " + response )
762 main.log.info(
763 "Ip of host " +
764 host +
765 " changed to new IP " +
766 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800767 return main.TRUE
768 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800769 main.log.error( self.name + ": EOF exception found" )
770 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800771 return main.FALSE
772
Jon Hall7eb38402015-01-08 17:19:54 -0800773 def changeDefaultGateway( self, host, newGW ):
774 """
775 Changes the default gateway of a host
776 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800777 if self.handle:
778 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800779 cmd = host + " route add default gw " + newGW
780 self.handle.sendline( cmd )
781 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800782 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800783 main.log.info( "response = " + response )
784 main.log.info(
785 "Default gateway of host " +
786 host +
787 " changed to " +
788 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800789 return main.TRUE
790 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800791 main.log.error( self.name + ": EOF exception found" )
792 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800793 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800794
Jon Hall7eb38402015-01-08 17:19:54 -0800795 def addStaticMACAddress( self, host, GW, macaddr ):
796 """
Jon Hallefbd9792015-03-05 16:11:36 -0800797 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800798 if self.handle:
799 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800800 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
801 cmd = host + " arp -s " + GW + " " + macaddr
802 self.handle.sendline( cmd )
803 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800804 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800805 main.log.info( "response = " + response )
806 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800807 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800808 GW +
809 " changed to " +
810 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800811 return main.TRUE
812 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800813 main.log.error( self.name + ": EOF exception found" )
814 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800815 return main.FALSE
816
Jon Hall7eb38402015-01-08 17:19:54 -0800817 def verifyStaticGWandMAC( self, host ):
818 """
819 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800820 if self.handle:
821 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800822 # h1 arp -an
823 cmd = host + " arp -an "
824 self.handle.sendline( cmd )
825 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800826 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800827 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800828 return main.TRUE
829 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800830 main.log.error( self.name + ": EOF exception found" )
831 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800832 return main.FALSE
833
Jon Hall7eb38402015-01-08 17:19:54 -0800834 def getMacAddress( self, host ):
835 """
836 Verifies the host's ip configured or not."""
837 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700838 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800839 response = self.execute(
840 cmd=host +
841 " ifconfig",
842 prompt="mininet>",
843 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800844 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800845 main.log.error( self.name + ": EOF exception found" )
846 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700847 main.cleanup()
848 main.exit()
adminbae64d82013-08-01 10:50:15 -0700849
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700850 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800851 macAddressSearch = re.search( pattern, response, re.I )
852 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800853 main.log.info(
854 self.name +
855 ": Mac-Address of Host " +
856 host +
857 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800858 macAddress )
859 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700860 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800861 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700862
Jon Hall7eb38402015-01-08 17:19:54 -0800863 def getInterfaceMACAddress( self, host, interface ):
864 """
865 Return the IP address of the interface on the given host"""
866 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700867 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800868 response = self.execute( cmd=host + " ifconfig " + interface,
869 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800870 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800871 main.log.error( self.name + ": EOF exception found" )
872 main.log.error( self.name + ": " + self.handle.before )
873 main.cleanup()
874 main.exit()
875
876 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800877 macAddressSearch = re.search( pattern, response, re.I )
878 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800879 main.log.info( "No mac address found in %s" % response )
880 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800881 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800882 main.log.info(
883 "Mac-Address of " +
884 host +
885 ":" +
886 interface +
887 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800888 macAddress )
889 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800890 else:
891 main.log.error( "Connection failed to the host" )
892
893 def getIPAddress( self, host ):
894 """
895 Verifies the host's ip configured or not."""
896 if self.handle:
897 try:
898 response = self.execute(
899 cmd=host +
900 " ifconfig",
901 prompt="mininet>",
902 timeout=10 )
903 except pexpect.EOF:
904 main.log.error( self.name + ": EOF exception found" )
905 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700906 main.cleanup()
907 main.exit()
adminbae64d82013-08-01 10:50:15 -0700908
909 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800910 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800911 main.log.info(
912 self.name +
913 ": IP-Address of Host " +
914 host +
915 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800916 ipAddressSearch.group( 1 ) )
917 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800918 else:
919 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800920
Jon Hall7eb38402015-01-08 17:19:54 -0800921 def getSwitchDPID( self, switch ):
922 """
923 return the datapath ID of the switch"""
924 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700925 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700926 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800927 response = self.execute(
928 cmd=cmd,
929 prompt="mininet>",
930 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800931 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800932 main.log.error( self.name + ": EOF exception found" )
933 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700934 main.cleanup()
935 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800936 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800937 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700938 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800939 main.log.info(
940 "Couldn't find DPID for switch %s, found: %s" %
941 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700942 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800943 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700944 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800945 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700946
Jon Hall7eb38402015-01-08 17:19:54 -0800947 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700948 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800949 self.handle.sendline( "" )
950 self.expect( "mininet>" )
951 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700952 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800953 response = self.execute(
954 cmd=cmd,
955 prompt="mininet>",
956 timeout=10 )
957 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700958 response = self.handle.before
959 return response
960 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 )
admin2580a0e2014-07-29 11:24:34 -0700963 main.cleanup()
964 main.exit()
965
Jon Hall7eb38402015-01-08 17:19:54 -0800966 def getInterfaces( self, node ):
967 """
968 return information dict about interfaces connected to the node"""
969 if self.handle:
970 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800971 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700972 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700973 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800974 response = self.execute(
975 cmd=cmd,
976 prompt="mininet>",
977 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800978 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800979 main.log.error( self.name + ": EOF exception found" )
980 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700981 main.cleanup()
982 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700983 return response
984 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800985 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700986
Jon Hall7eb38402015-01-08 17:19:54 -0800987 def dump( self ):
988 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700989 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800990 response = self.execute(
991 cmd='dump',
992 prompt='mininet>',
993 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800994 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800995 main.log.error( self.name + ": EOF exception found" )
996 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700997 main.cleanup()
998 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700999 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001000
Jon Hall7eb38402015-01-08 17:19:54 -08001001 def intfs( self ):
1002 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001003 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001004 response = self.execute(
1005 cmd='intfs',
1006 prompt='mininet>',
1007 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001008 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001009 main.log.error( self.name + ": EOF exception found" )
1010 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001011 main.cleanup()
1012 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001013 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001014
Jon Hall7eb38402015-01-08 17:19:54 -08001015 def net( self ):
1016 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001017 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001018 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001019 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001020 main.log.error( self.name + ": EOF exception found" )
1021 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001022 main.cleanup()
1023 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001024 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001025
Jon Hallafa8a472015-06-12 14:02:42 -07001026 def links( self ):
1027 main.log.info( self.name + ": List network links" )
1028 try:
1029 response = self.execute( cmd='links', prompt='mininet>',
1030 timeout=10 )
1031 except pexpect.EOF:
1032 main.log.error( self.name + ": EOF exception found" )
1033 main.log.error( self.name + ": " + self.handle.before )
1034 main.cleanup()
1035 main.exit()
1036 return response
1037
GlennRC61321f22015-07-16 13:36:54 -07001038 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001039 '''
1040 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001041
kelvin-onlab7cce9382015-07-17 10:21:03 -07001042 @parm:
1043 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1044 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1045 '''
1046 for host1 in hosts:
1047 for host2 in hosts:
1048 if host1 != host2:
1049 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1050 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001051
1052 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001053 '''
1054 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1055 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001056
kelvin-onlab7cce9382015-07-17 10:21:03 -07001057 @parm:
1058 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1059 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1060 '''
1061 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1062 try:
1063 # Setup the mininet command
1064 cmd1 = 'iperf ' + host1 + " " + host2
1065 self.handle.sendline( cmd1 )
1066 outcome = self.handle.expect( "mininet>", timeout )
1067 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001068
kelvin-onlab7cce9382015-07-17 10:21:03 -07001069 # checks if there are results in the mininet response
1070 if "Results:" in response:
1071 main.log.report(self.name + ": iperf test completed")
1072 # parse the mn results
1073 response = response.split("\r\n")
1074 response = response[len(response)-2]
1075 response = response.split(": ")
1076 response = response[len(response)-1]
1077 response = response.replace("[", "")
1078 response = response.replace("]", "")
1079 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001080
kelvin-onlab7cce9382015-07-17 10:21:03 -07001081 # this is the bandwith two and from the two hosts
1082 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001083
kelvin-onlab7cce9382015-07-17 10:21:03 -07001084 # there should be two elements in the bandwidth list
1085 # ['host1 to host2', 'host2 to host1"]
1086 if len(bandwidth) == 2:
1087 main.log.report(self.name + ": iperf test successful")
1088 return main.TRUE
1089 else:
1090 main.log.error(self.name + ": invalid iperf results")
1091 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001092 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001093 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001094 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001095
GlennRC61321f22015-07-16 13:36:54 -07001096 except pexpect.TIMEOUT:
1097 main.log.error( self.name + ": TIMEOUT exception found")
1098 main.log.error( self.name + ": Exception: Cannot connect to iperf on port 5001" )
1099 return main.FALSE
1100
Jon Hallfbc828e2015-01-06 17:30:19 -08001101 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001102 main.log.error( self.name + ": EOF exception found" )
1103 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001104 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001105 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001106
1107 def iperfudpAll(self, hosts, bandwidth="10M"):
1108 '''
1109 Runs the iperfudp function with a given set of hosts and specified
1110 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001111
GlennRC61321f22015-07-16 13:36:54 -07001112 @param:
1113 bandwidth: the targeted bandwidth, in megabits ('M')
1114 '''
1115 for host1 in hosts:
1116 for host2 in hosts:
1117 if host1 != host2:
1118 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1119 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1120
1121 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1122
kelvin-onlab7cce9382015-07-17 10:21:03 -07001123 '''
1124 Creates an iperf UDP test with a specific bandwidth.
1125 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001126
kelvin-onlab7cce9382015-07-17 10:21:03 -07001127 @param:
1128 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1129 '''
1130 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1131 try:
1132 # setup the mininet command
1133 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1134 self.handle.sendline(cmd)
1135 self.handle.expect("mininet>")
1136 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001137
kelvin-onlab7cce9382015-07-17 10:21:03 -07001138 # check if there are in results in the mininet response
1139 if "Results:" in response:
1140 main.log.report(self.name + ": iperfudp test completed")
1141 # parse the results
1142 response = response.split("\r\n")
1143 response = response[len(response)-2]
1144 response = response.split(": ")
1145 response = response[len(response)-1]
1146 response = response.replace("[", "")
1147 response = response.replace("]", "")
1148 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001149
kelvin-onlab7cce9382015-07-17 10:21:03 -07001150 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001151
kelvin-onlab7cce9382015-07-17 10:21:03 -07001152 # check to see if there are at least three entries
1153 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1154 if len(mnBandwidth) == 3:
1155 # if one entry is blank then something is wrong
1156 for item in mnBandwidth:
1157 if item == "":
1158 main.log.error(self.name + ": Could not parse iperf output")
1159 main.log.error(self.name + ": invalid iperfudp results")
1160 return main.FALSE
1161 # otherwise results are vaild
1162 main.log.report(self.name + ": iperfudp test successful")
1163 return main.TRUE
1164 else:
1165 main.log.error(self.name + ": invalid iperfudp results")
1166 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001167
kelvin-onlab7cce9382015-07-17 10:21:03 -07001168 except pexpect.EOF:
1169 main.log.error( self.name + ": EOF exception found" )
1170 main.log.error( self.name + ": " + self.handle.before )
1171 main.cleanup()
1172 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001173
Jon Hall7eb38402015-01-08 17:19:54 -08001174 def nodes( self ):
1175 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001176 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001177 response = self.execute(
1178 cmd='nodes',
1179 prompt='mininet>',
1180 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001181 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001182 main.log.error( self.name + ": EOF exception found" )
1183 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001184 main.cleanup()
1185 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001186 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001187
Jon Hall7eb38402015-01-08 17:19:54 -08001188 def pingpair( self ):
1189 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001190 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001191 response = self.execute(
1192 cmd='pingpair',
1193 prompt='mininet>',
1194 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001195 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001196 main.log.error( self.name + ": EOF exception found" )
1197 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001198 main.cleanup()
1199 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001200
Jon Hall7eb38402015-01-08 17:19:54 -08001201 if re.search( ',\s0\%\spacket\sloss', response ):
1202 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001203 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001204 else:
1205 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001206 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001207
Jon Hall7eb38402015-01-08 17:19:54 -08001208 def link( self, **linkargs ):
1209 """
1210 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001211 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001212 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1213 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1214 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1215 main.log.info(
1216 "Bring link between '" +
1217 end1 +
1218 "' and '" +
1219 end2 +
1220 "' '" +
1221 option +
1222 "'" )
1223 command = "link " + \
1224 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001225 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001226 self.handle.sendline( command )
1227 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001228 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001229 main.log.error( self.name + ": EOF exception found" )
1230 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001231 main.cleanup()
1232 main.exit()
adminbae64d82013-08-01 10:50:15 -07001233 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001234
Jon Hall7eb38402015-01-08 17:19:54 -08001235 def yank( self, **yankargs ):
1236 """
1237 yank a mininet switch interface to a host"""
1238 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001239 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001240 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1241 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1242 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001243 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001244 response = self.execute(
1245 cmd=command,
1246 prompt="mininet>",
1247 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001248 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001249 main.log.error( self.name + ": EOF exception found" )
1250 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001251 main.cleanup()
1252 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001253 return main.TRUE
1254
Jon Hall7eb38402015-01-08 17:19:54 -08001255 def plug( self, **plugargs ):
1256 """
1257 plug the yanked mininet switch interface to a switch"""
1258 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001259 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001260 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1261 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1262 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001263 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001264 response = self.execute(
1265 cmd=command,
1266 prompt="mininet>",
1267 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001268 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001269 main.log.error( self.name + ": EOF exception found" )
1270 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001271 main.cleanup()
1272 main.exit()
adminbae64d82013-08-01 10:50:15 -07001273 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001274
Jon Hall7eb38402015-01-08 17:19:54 -08001275 def dpctl( self, **dpctlargs ):
1276 """
1277 Run dpctl command on all switches."""
1278 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001279 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001280 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1281 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1282 command = "dpctl " + cmd + " " + str( cmdargs )
1283 try:
1284 response = self.execute(
1285 cmd=command,
1286 prompt="mininet>",
1287 timeout=10 )
1288 except pexpect.EOF:
1289 main.log.error( self.name + ": EOF exception found" )
1290 main.log.error( self.name + ": " + self.handle.before )
1291 main.cleanup()
1292 main.exit()
1293 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001294
kelvin-onlabd3b64892015-01-20 13:26:24 -08001295 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001296 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001297 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001298 fileInput = path + '/lib/Mininet/INSTALL'
1299 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001300 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001301 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001302 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001303 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001304 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001305 return version
adminbae64d82013-08-01 10:50:15 -07001306
kelvin-onlabd3b64892015-01-20 13:26:24 -08001307 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001308 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001309 Parameters:
1310 sw: The name of an OVS switch. Example "s1"
1311 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001312 The output of the command from the mininet cli
1313 or main.FALSE on timeout"""
1314 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001315 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001316 response = self.execute(
1317 cmd=command,
1318 prompt="mininet>",
1319 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001320 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001321 return response
admin2a9548d2014-06-17 14:08:07 -07001322 else:
1323 return main.FALSE
1324 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001325 main.log.error( self.name + ": EOF exception found" )
1326 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001327 main.cleanup()
1328 main.exit()
adminbae64d82013-08-01 10:50:15 -07001329
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001330 def assignSwController( self, sw, ip, port="6633", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001331 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001332 Description:
1333 Assign switches to the controllers ( for ovs use only )
1334 Required:
1335 sw - Name of the switch. This can be a list or a string.
1336 ip - Ip addresses of controllers. This can be a list or a string.
1337 Optional:
1338 port - ONOS use port 6633, if no list of ports is passed, then
1339 the all the controller will use 6633 as their port number
1340 ptcp - ptcp number, This can be a string or a list that has
1341 the same length as switch. This is optional and not required
1342 when using ovs switches.
1343 NOTE: If switches and ptcp are given in a list type they should have the
1344 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1345 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001346
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001347 Return:
1348 Returns main.TRUE if mininet correctly assigned switches to
1349 controllers, otherwise it will return main.FALSE or an appropriate
1350 exception(s)
1351 """
1352 assignResult = main.TRUE
1353 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001354 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001355 command = "sh ovs-vsctl set-controller "
1356 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001357 try:
1358 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001359 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001360 if isinstance( port, types.StringType ) or \
1361 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001362 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001363 elif isinstance( port, types.ListType ):
1364 main.log.error( self.name + ": Only one controller " +
1365 "assigned and a list of ports has" +
1366 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001367 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001368 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001369 main.log.error( self.name + ": Invalid controller port " +
1370 "number. Please specify correct " +
1371 "controller port" )
1372 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001373
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001374 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001375 if isinstance( port, types.StringType ) or \
1376 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001377 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001378 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1379 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001380 elif isinstance( port, types.ListType ):
1381 if ( len( ip ) != len( port ) ):
1382 main.log.error( self.name + ": Port list = " +
1383 str( len( port ) ) +
1384 "should be the same as controller" +
1385 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001386 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001387 else:
1388 onosIp = ""
1389 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001390 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1391 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001392 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001393 main.log.error( self.name + ": Invalid controller port " +
1394 "number. Please specify correct " +
1395 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001396 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001397 else:
1398 main.log.error( self.name + ": Invalid ip address" )
1399 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001400
1401 if isinstance( sw, types.StringType ):
1402 command += sw + " "
1403 if ptcp:
1404 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001405 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001406 elif isinstance( ptcp, types.ListType ):
1407 main.log.error( self.name + ": Only one switch is " +
1408 "being set and multiple PTCP is " +
1409 "being passed " )
1410 else:
1411 main.log.error( self.name + ": Invalid PTCP" )
1412 ptcp = ""
1413 command += onosIp
1414 commandList.append( command )
1415
1416 elif isinstance( sw, types.ListType ):
1417 if ptcp:
1418 if isinstance( ptcp, types.ListType ):
1419 if len( ptcp ) != len( sw ):
1420 main.log.error( self.name + ": PTCP length = " +
1421 str( len( ptcp ) ) +
1422 " is not the same as switch" +
1423 " length = " +
1424 str( len( sw ) ) )
1425 return main.FALSE
1426 else:
1427 for switch, ptcpNum in zip( sw, ptcp ):
1428 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001429 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001430 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001431 tempCmd += onosIp
1432 commandList.append( tempCmd )
1433 else:
1434 main.log.error( self.name + ": Invalid PTCP" )
1435 return main.FALSE
1436 else:
1437 for switch in sw:
1438 tempCmd = "sh ovs-vsctl set-controller "
1439 tempCmd += switch + " " + onosIp
1440 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001441 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001442 main.log.error( self.name + ": Invalid switch type " )
1443 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001444
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001445 for cmd in commandList:
1446 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001447 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001448 except pexpect.TIMEOUT:
1449 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1450 return main.FALSE
1451 except pexpect.EOF:
1452 main.log.error( self.name + ": EOF exception found" )
1453 main.log.error( self.name + ": " + self.handle.before )
1454 main.cleanup()
1455 main.exit()
1456 return main.TRUE
1457 except Exception:
1458 main.log.exception( self.name + ": Uncaught exception!" )
1459 main.cleanup()
1460 main.exit()
adminbae64d82013-08-01 10:50:15 -07001461
kelvin-onlabd3b64892015-01-20 13:26:24 -08001462 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001463 """
1464 Removes the controller target from sw"""
1465 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001466 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001467 response = self.execute(
1468 cmd=command,
1469 prompt="mininet>",
1470 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001471 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001472 main.log.error( self.name + ": EOF exception found" )
1473 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001474 main.cleanup()
1475 main.exit()
1476 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001477 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001478
kelvin-onlabd3b64892015-01-20 13:26:24 -08001479 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001480 """
Jon Hallb1290e82014-11-18 16:17:48 -05001481 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001482 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001483 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001484 NOTE: cannot currently specify what type of switch
1485 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001486 sw = name of the new switch as a string
1487 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001488 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001489 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001490 """
1491 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001492 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001493 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001494 response = self.execute(
1495 cmd=command,
1496 prompt="mininet>",
1497 timeout=10 )
1498 if re.search( "already exists!", response ):
1499 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001500 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001501 elif re.search( "Error", response ):
1502 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001503 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001504 elif re.search( "usage:", response ):
1505 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001506 return main.FALSE
1507 else:
1508 return main.TRUE
1509 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001510 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001511 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001512 main.cleanup()
1513 main.exit()
1514
kelvin-onlabd3b64892015-01-20 13:26:24 -08001515 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001516 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001517 delete a switch from the mininet topology
1518 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001519 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001520 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001521 sw = name of the switch as a string
1522 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001523 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001524 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001525 response = self.execute(
1526 cmd=command,
1527 prompt="mininet>",
1528 timeout=10 )
1529 if re.search( "no switch named", response ):
1530 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001531 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001532 elif re.search( "Error", response ):
1533 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001534 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001535 elif re.search( "usage:", response ):
1536 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001537 return main.FALSE
1538 else:
1539 return main.TRUE
1540 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001541 main.log.error( self.name + ": EOF exception found" )
1542 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001543 main.cleanup()
1544 main.exit()
1545
kelvin-onlabd3b64892015-01-20 13:26:24 -08001546 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001547 """
1548 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001549 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001550 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001551 NOTE: cannot currently specify what type of link
1552 required params:
1553 node1 = the string node name of the first endpoint of the link
1554 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001555 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001556 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001557 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001558 response = self.execute(
1559 cmd=command,
1560 prompt="mininet>",
1561 timeout=10 )
1562 if re.search( "doesnt exist!", response ):
1563 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001564 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001565 elif re.search( "Error", response ):
1566 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001567 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001568 elif re.search( "usage:", response ):
1569 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001570 return main.FALSE
1571 else:
1572 return main.TRUE
1573 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001574 main.log.error( self.name + ": EOF exception found" )
1575 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001576 main.cleanup()
1577 main.exit()
1578
kelvin-onlabd3b64892015-01-20 13:26:24 -08001579 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001580 """
1581 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001582 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001583 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001584 required params:
1585 node1 = the string node name of the first endpoint of the link
1586 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001587 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001588 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001589 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001590 response = self.execute(
1591 cmd=command,
1592 prompt="mininet>",
1593 timeout=10 )
1594 if re.search( "no node named", response ):
1595 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001596 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001597 elif re.search( "Error", response ):
1598 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001599 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001600 elif re.search( "usage:", response ):
1601 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001602 return main.FALSE
1603 else:
1604 return main.TRUE
1605 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001606 main.log.error( self.name + ": EOF exception found" )
1607 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001608 main.cleanup()
1609 main.exit()
1610
kelvin-onlabd3b64892015-01-20 13:26:24 -08001611 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001612 """
Jon Hallb1290e82014-11-18 16:17:48 -05001613 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001614 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001615 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001616 NOTE: cannot currently specify what type of host
1617 required params:
1618 hostname = the string hostname
1619 optional key-value params
1620 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001621 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001622 """
1623 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001624 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001625 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001626 response = self.execute(
1627 cmd=command,
1628 prompt="mininet>",
1629 timeout=10 )
1630 if re.search( "already exists!", response ):
1631 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001632 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001633 elif re.search( "doesnt exists!", response ):
1634 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001635 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001636 elif re.search( "Error", response ):
1637 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001638 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001639 elif re.search( "usage:", response ):
1640 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001641 return main.FALSE
1642 else:
1643 return main.TRUE
1644 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001645 main.log.error( self.name + ": EOF exception found" )
1646 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001647 main.cleanup()
1648 main.exit()
1649
kelvin-onlabd3b64892015-01-20 13:26:24 -08001650 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001651 """
1652 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001653 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001654 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001655 NOTE: this uses a custom mn function
1656 required params:
1657 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001658 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001659 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001660 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001661 response = self.execute(
1662 cmd=command,
1663 prompt="mininet>",
1664 timeout=10 )
1665 if re.search( "no host named", response ):
1666 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001667 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001668 elif re.search( "Error", response ):
1669 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001670 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001671 elif re.search( "usage:", response ):
1672 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001673 return main.FALSE
1674 else:
1675 return main.TRUE
1676 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001677 main.log.error( self.name + ": EOF exception found" )
1678 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001679 main.cleanup()
1680 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001681
Jon Hall7eb38402015-01-08 17:19:54 -08001682 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001683 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001684 Called at the end of the test to stop the mininet and
1685 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001686 """
Jon Halld80cc142015-07-06 13:36:05 -07001687 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001688 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001689 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001690 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001691 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001692 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001693 elif i == 1:
1694 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001695 # print "Disconnecting Mininet"
1696 if self.handle:
1697 self.handle.sendline( "exit" )
1698 self.handle.expect( "exit" )
1699 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001700 else:
1701 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001702 return response
1703
Jon Halld80cc142015-07-06 13:36:05 -07001704 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001705 """
Jon Hall21270ac2015-02-16 17:59:55 -08001706 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001707 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001708 main.FALSE if the pexpect handle does not exist.
1709
Jon Halld61331b2015-02-17 16:35:47 -08001710 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001711 """
Jon Halld61331b2015-02-17 16:35:47 -08001712 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001713 response = ''
1714 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001715 try:
Jon Halld80cc142015-07-06 13:36:05 -07001716 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001717 i = self.handle.expect( [ 'mininet>',
1718 '\$',
1719 pexpect.EOF,
1720 pexpect.TIMEOUT ],
1721 timeout )
1722 if i == 0:
1723 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001724 response = self.execute(
1725 cmd="exit",
1726 prompt="(.*)",
1727 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001728 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001729 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001730 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001731
kelvin-onlab56a3f462015-02-06 14:04:43 -08001732 if i == 1:
1733 main.log.info( " Mininet trying to exit while not " +
1734 "in the mininet prompt" )
1735 elif i == 2:
1736 main.log.error( "Something went wrong exiting mininet" )
1737 elif i == 3: # timeout
1738 main.log.error( "Something went wrong exiting mininet " +
1739 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001740
Hari Krishnab35c6d02015-03-18 11:13:51 -07001741 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001742 self.handle.sendline( "" )
1743 self.handle.expect( '\$' )
1744 self.handle.sendline(
1745 "sudo kill -9 \`ps -ef | grep \"" +
1746 fileName +
1747 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001748 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001749 main.log.error( self.name + ": EOF exception found" )
1750 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001751 main.cleanup()
1752 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001753 else:
1754 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001755 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001756 return response
1757
Jon Halla5cb3412015-08-18 14:08:22 -07001758 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001759 """
1760 Description:
1761 Sends arp message from mininet host for hosts discovery
1762 Required:
1763 host - hosts name
1764 Optional:
1765 ip - ip address that does not exist in the network so there would
1766 be no reply.
1767 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001768 if ethDevice:
1769 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001770 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001771 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001772 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001773 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001774 i = self.handle.expect( [ "mininet>", "arping: " ] )
1775 if i == 0:
1776 return main.TRUE
1777 elif i == 1:
1778 response = self.handle.before + self.handle.after
1779 self.handle.expect( "mininet>" )
1780 response += self.handle.before + self.handle.after
1781 main.log.warn( "Error sending arping, output was: " +
1782 response )
1783 return main.FALSE
1784 except pexpect.TIMEOUT:
1785 main.log.error( self.name + ": TIMEOUT exception found" )
1786 main.log.warn( self.handle.before )
1787 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001788 except pexpect.EOF:
1789 main.log.error( self.name + ": EOF exception found" )
1790 main.log.error( self.name + ": " + self.handle.before )
1791 main.cleanup()
1792 main.exit()
admin07529932013-11-22 14:58:28 -08001793
Jon Hall7eb38402015-01-08 17:19:54 -08001794 def decToHex( self, num ):
1795 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001796
Jon Hall7eb38402015-01-08 17:19:54 -08001797 def getSwitchFlowCount( self, switch ):
1798 """
1799 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001800 if self.handle:
1801 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1802 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001803 response = self.execute(
1804 cmd=cmd,
1805 prompt="mininet>",
1806 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001807 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001808 main.log.error( self.name + ": EOF exception found" )
1809 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001810 main.cleanup()
1811 main.exit()
1812 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001813 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001814 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001815 main.log.info(
1816 "Couldn't find flows on switch %s, found: %s" %
1817 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001818 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001819 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001820 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001821 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001822
kelvin-onlabd3b64892015-01-20 13:26:24 -08001823 def checkFlows( self, sw, dumpFormat=None ):
1824 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001825 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001826 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001827 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001828 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001829 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001830 response = self.execute(
1831 cmd=command,
1832 prompt="mininet>",
1833 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001834 return response
1835 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001836 main.log.error( self.name + ": EOF exception found" )
1837 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001838 main.cleanup()
1839 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001840
Jon Hall9043c902015-07-30 14:23:44 -07001841 def getFlowTable( self, protoVersion, sw ):
1842 """
1843 Returns certain fields of an OVS flow table. Will force output to
1844 either OF 1.0 or 1.3 format for consistency.
1845
1846 TODO add option to look at cookies. ignoring them for now
1847
1848 NOTE: Use format to force consistent flow table output across
1849 versions
1850 """
1851 try:
1852 self.handle.sendline( "" )
1853 self.handle.expect( "mininet>" )
1854 command = "sh ovs-ofctl dump-flows " + sw
1855 if protoVersion == 1.0:
1856 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\
1857 " print $1 $3 $6 $7 $8}' | "
1858 elif protoVersion == 1.3:
1859 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\
1860 " print $1 $3 $6 $7}' | "
1861 else:
1862 main.log.error(
1863 "Unknown protoVersion in getFlowTable(). given: (" +
1864 str( type( protoVersion ) ) +
1865 ") '" + str( protoVersion ) + "'" )
1866 return None
1867 command += "cut -d ',' -f 2- | sort -n -k1 -r"
1868 self.handle.sendline( command )
1869 self.handle.expect( "sort" )
1870 self.handle.expect( "OFPST_FLOW" )
1871 response = self.handle.before
1872 return response
1873 except pexpect.EOF:
1874 main.log.error( self.name + ": EOF exception found" )
1875 main.log.error( self.name + ": " + self.handle.before )
1876 main.cleanup()
1877 main.exit()
1878 except pexpect.TIMEOUT:
1879 main.log.exception( self.name + ": Timeout exception: " )
1880 return None
1881
1882 def flowComp( self, flow1, flow2 ):
1883 if flow1 == flow2:
1884 return main.TRUE
1885 else:
1886 main.log.info( "Flow tables do not match, printing tables:" )
1887 main.log.info( "Flow Table 1:" )
1888 main.log.info( flow1 )
1889 main.log.info( "Flow Table 2:" )
1890 main.log.info( flow2 )
1891 return main.FALSE
1892
kelvin-onlabd3b64892015-01-20 13:26:24 -08001893 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001894 """
Jon Hallefbd9792015-03-05 16:11:36 -08001895 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001896 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001897 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001898 self.handle.sendline( "" )
1899 self.handle.expect( "mininet>" )
1900 self.handle.sendline(
1901 "sh sudo tcpdump -n -i " +
1902 intf +
1903 " " +
1904 port +
1905 " -w " +
1906 filename.strip() +
1907 " &" )
1908 self.handle.sendline( "" )
1909 i = self.handle.expect( [ 'No\ssuch\device',
1910 'listening\son',
1911 pexpect.TIMEOUT,
1912 "mininet>" ],
1913 timeout=10 )
1914 main.log.warn( self.handle.before + self.handle.after )
1915 self.handle.sendline( "" )
1916 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001917 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001918 main.log.error(
1919 self.name +
1920 ": tcpdump - No such device exists. " +
1921 "tcpdump attempted on: " +
1922 intf )
admin2a9548d2014-06-17 14:08:07 -07001923 return main.FALSE
1924 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001925 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001926 return main.TRUE
1927 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001928 main.log.error(
1929 self.name +
1930 ": tcpdump command timed out! Check interface name," +
1931 " given interface was: " +
1932 intf )
admin2a9548d2014-06-17 14:08:07 -07001933 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001934 elif i == 3:
1935 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001936 return main.TRUE
1937 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001938 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001939 return main.FALSE
1940 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001941 main.log.error( self.name + ": EOF exception found" )
1942 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001943 main.cleanup()
1944 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001945 except Exception:
1946 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001947 main.cleanup()
1948 main.exit()
1949
kelvin-onlabd3b64892015-01-20 13:26:24 -08001950 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001951 """
1952 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001953 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001954 self.handle.sendline( "sh sudo pkill tcpdump" )
1955 self.handle.expect( "mininet>" )
1956 self.handle.sendline( "" )
1957 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001958 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001959 main.log.error( self.name + ": EOF exception found" )
1960 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001961 main.cleanup()
1962 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001963 except Exception:
1964 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001965 main.cleanup()
1966 main.exit()
1967
Jon Halld80cc142015-07-06 13:36:05 -07001968 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001969 """
1970 Read ports from a Mininet switch.
1971
1972 Returns a json structure containing information about the
1973 ports of the given switch.
1974 """
1975 response = self.getInterfaces( nodeName )
1976 # TODO: Sanity check on response. log if no such switch exists
1977 ports = []
1978 for line in response.split( "\n" ):
1979 if not line.startswith( "name=" ):
1980 continue
1981 portVars = {}
1982 for var in line.split( "," ):
1983 key, value = var.split( "=" )
1984 portVars[ key ] = value
1985 isUp = portVars.pop( 'enabled', "True" )
1986 isUp = "True" in isUp
1987 if verbose:
1988 main.log.info( "Reading switch port %s(%s)" %
1989 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1990 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001991 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001992 mac = None
1993 ips = []
1994 ip = portVars[ 'ip' ]
1995 if ip == 'None':
1996 ip = None
1997 ips.append( ip )
1998 name = portVars[ 'name' ]
1999 if name == 'None':
2000 name = None
2001 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2002 if name == 'lo':
2003 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2004 else:
2005 portNo = re.search( portRe, name ).group( 'port' )
2006 ports.append( { 'of_port': portNo,
2007 'mac': str( mac ).replace( '\'', '' ),
2008 'name': name,
2009 'ips': ips,
2010 'enabled': isUp } )
2011 return ports
2012
Jon Halld80cc142015-07-06 13:36:05 -07002013 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002014 """
2015 Read switches from Mininet.
2016
2017 Returns a dictionary whose keys are the switch names and the value is
2018 a dictionary containing information about the switch.
2019 """
Jon Halla22481b2015-07-28 17:46:01 -07002020 # NOTE: To support new Mininet switch classes, just append the new
2021 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002022
Jon Halla22481b2015-07-28 17:46:01 -07002023 # Regex patterns to parse 'dump' output
2024 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002025 # <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 -07002026 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002027 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2028 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2029 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2030 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2031 swRE = r"<(?P<class>" + switchClasses + r")" +\
2032 r"(?P<options>\{.*\})?\s" +\
2033 r"(?P<name>[^:]+)\:\s" +\
2034 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2035 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002036 # Update mn port info
2037 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002038 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002039 dump = self.dump().split( "\n" )
2040 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002041 result = re.search( swRE, line, re.I )
2042 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002043 name = result.group( 'name' )
2044 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002045 pid = result.group( 'pid' )
2046 swClass = result.group( 'class' )
2047 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002048 if verbose:
2049 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2050 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002051 output[ name ] = { "dpid": dpid,
2052 "ports": ports,
2053 "swClass": swClass,
2054 "pid": pid,
2055 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002056 return output
2057
Jon Halld80cc142015-07-06 13:36:05 -07002058 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002059 """
2060 Read hosts from Mininet.
2061
2062 Returns a dictionary whose keys are the host names and the value is
2063 a dictionary containing information about the host.
2064 """
2065 # Regex patterns to parse dump output
2066 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002067 # <Host h1: pid=12725>
2068 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2069 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2070 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002071 # NOTE: Does not correctly match hosts with multi-links
2072 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2073 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002074 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002075 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002076 # update mn port info
2077 self.update()
2078 # Get mininet dump
2079 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002080 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002081 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002082 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002083 result = re.search( hostRE, line )
2084 name = result.group( 'name' )
2085 interfaces = []
2086 response = self.getInterfaces( name )
2087 # Populate interface info
2088 for line in response.split( "\n" ):
2089 if line.startswith( "name=" ):
2090 portVars = {}
2091 for var in line.split( "," ):
2092 key, value = var.split( "=" )
2093 portVars[ key ] = value
2094 isUp = portVars.pop( 'enabled', "True" )
2095 isUp = "True" in isUp
2096 if verbose:
2097 main.log.info( "Reading host port %s(%s)" %
2098 ( portVars[ 'name' ],
2099 portVars[ 'mac' ] ) )
2100 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002101 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002102 mac = None
2103 ips = []
2104 ip = portVars[ 'ip' ]
2105 if ip == 'None':
2106 ip = None
2107 ips.append( ip )
2108 intfName = portVars[ 'name' ]
2109 if name == 'None':
2110 name = None
2111 interfaces.append( {
2112 "name": intfName,
2113 "ips": ips,
2114 "mac": str( mac ),
2115 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002116 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002117 return hosts
2118
2119 def getLinks( self ):
2120 """
2121 Gathers information about current Mininet links. These links may not
2122 be up if one of the ports is down.
2123
2124 Returns a list of dictionaries with link endpoints.
2125
2126 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002127 { 'node1': str( node1 name )
2128 'node2': str( node2 name )
2129 'port1': str( port1 of_port )
2130 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002131 Note: The port number returned is the eth#, not necessarily the of_port
2132 number. In Mininet, for OVS switch, these should be the same. For
2133 hosts, this is just the eth#.
2134 """
2135 self.update()
2136 response = self.links().split( '\n' )
2137
2138 # Examples:
2139 # s1-eth3<->s2-eth1 (OK OK)
2140 # s13-eth3<->h27-eth0 (OK OK)
2141 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2142 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2143 links = []
2144 for line in response:
2145 match = re.search( linkRE, line )
2146 if match:
2147 node1 = match.group( 'node1' )
2148 node2 = match.group( 'node2' )
2149 port1 = match.group( 'port1' )
2150 port2 = match.group( 'port2' )
2151 links.append( { 'node1': node1,
2152 'node2': node2,
2153 'port1': port1,
2154 'port2': port2 } )
2155 return links
2156
2157 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002158 """
2159 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002160 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002161
Jon Hallafa8a472015-06-12 14:02:42 -07002162 Dependencies:
2163 1. numpy - "sudo pip install numpy"
2164 """
2165 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002166 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002167 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002168 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002169 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002170 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002171 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002172 main.log.error(
2173 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002174 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002175 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002176 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002177 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002178 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002179 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002180 onosDPIDs.append(
2181 switch[ 'id' ].replace(
2182 ":",
2183 '' ).replace(
2184 "of",
2185 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002186 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002187
Jon Hall7eb38402015-01-08 17:19:54 -08002188 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002189 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002190 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002191 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002192 main.log.error( str( list1 ) )
2193 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002194 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002195 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002196 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002197 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002198 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002199
Jon Hall7eb38402015-01-08 17:19:54 -08002200 # FIXME: this does not look for extra ports in ONOS, only checks that
2201 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002202 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002203
Jon Hall7eb38402015-01-08 17:19:54 -08002204 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002205 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002206 mnPorts = []
2207 onosPorts = []
2208 switchResult = main.TRUE
2209 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002210 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002211 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002212 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002213 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002214 if onosSwitch[ 'device' ][ 'id' ].replace(
2215 ':',
2216 '' ).replace(
2217 "of",
2218 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002219 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002220 if port[ 'isEnabled' ]:
2221 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002222 # onosPorts.append( 'local' )
2223 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002224 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002225 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002226 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002227 mnPorts.sort( key=float )
2228 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002229
kelvin-onlabd3b64892015-01-20 13:26:24 -08002230 mnPortsLog = mnPorts
2231 onosPortsLog = onosPorts
2232 mnPorts = [ x for x in mnPorts ]
2233 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002234
Jon Hall7eb38402015-01-08 17:19:54 -08002235 # TODO: handle other reserved port numbers besides LOCAL
2236 # NOTE: Reserved ports
2237 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2238 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002239 for mnPort in mnPortsLog:
2240 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002241 # don't set results to true here as this is just one of
2242 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002243 mnPorts.remove( mnPort )
2244 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002245
Jon Hall7eb38402015-01-08 17:19:54 -08002246 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002247 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002248 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002249 if 65534 in mnPorts:
2250 mnPorts.remove( 65534 )
2251 if long( uint64( -2 ) ) in onosPorts:
2252 onosPorts.remove( long( uint64( -2 ) ) )
2253 if len( mnPorts ): # the ports of this switch don't match
2254 switchResult = main.FALSE
2255 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2256 if len( onosPorts ): # the ports of this switch don't match
2257 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002258 main.log.warn(
2259 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002260 str( onosPorts ) )
2261 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002262 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002263 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002264 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002265 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2266 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2267 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002268 finalResults = finalResults and portsResults
2269 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002270
Jon Hallafa8a472015-06-12 14:02:42 -07002271 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002272 """
2273 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002274 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002275
Jon Hallafa8a472015-06-12 14:02:42 -07002276 """
Jon Hall7eb38402015-01-08 17:19:54 -08002277 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002278 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002279 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002280
Jon Halld80cc142015-07-06 13:36:05 -07002281 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002282 for l in links:
2283 try:
2284 node1 = switches[ l[ 'node1' ] ]
2285 node2 = switches[ l[ 'node2' ] ]
2286 enabled = True
2287 for port in node1[ 'ports' ]:
2288 if port[ 'of_port' ] == l[ 'port1' ]:
2289 enabled = enabled and port[ 'enabled' ]
2290 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002291 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002292 enabled = enabled and port[ 'enabled' ]
2293 if enabled:
2294 mnLinks.append( l )
2295 except KeyError:
2296 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002297 if 2 * len( mnLinks ) == len( onos ):
2298 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002299 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002300 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002301 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002302 "Mininet has " + str( len( mnLinks ) ) +
2303 " bidirectional links and ONOS has " +
2304 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002305
Jon Hall7eb38402015-01-08 17:19:54 -08002306 # iterate through MN links and check if an ONOS link exists in
2307 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002308 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002309 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002310 node1 = None
2311 port1 = None
2312 node2 = None
2313 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002314 firstDir = main.FALSE
2315 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002316 for swName, switch in switches.iteritems():
2317 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002318 node1 = switch[ 'dpid' ]
2319 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002320 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002321 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002322 if node1 is not None and node2 is not None:
2323 break
Jon Hallafa8a472015-06-12 14:02:42 -07002324 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002325 node2 = switch[ 'dpid' ]
2326 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002327 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002328 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002329 if node1 is not None and node2 is not None:
2330 break
2331
kelvin-onlabd3b64892015-01-20 13:26:24 -08002332 for onosLink in onos:
2333 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002334 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002335 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002336 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002337 onosPort1 = onosLink[ 'src' ][ 'port' ]
2338 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002339
Jon Hall72cf1dc2014-10-20 21:04:50 -04002340 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002341 if str( onosNode1 ) == str( node1 ) and str(
2342 onosNode2 ) == str( node2 ):
2343 if int( onosPort1 ) == int( port1 ) and int(
2344 onosPort2 ) == int( port2 ):
2345 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002346 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002347 main.log.warn(
2348 'The port numbers do not match for ' +
2349 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002350 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002351 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002352 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002353 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002354 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002355
2356 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002357 elif ( str( onosNode1 ) == str( node2 ) and
2358 str( onosNode2 ) == str( node1 ) ):
2359 if ( int( onosPort1 ) == int( port2 )
2360 and int( onosPort2 ) == int( port1 ) ):
2361 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002362 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002363 main.log.warn(
2364 'The port numbers do not match for ' +
2365 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002366 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002367 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002368 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002369 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002370 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002371 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002372 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002373 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002374 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002375 'ONOS does not have the link %s/%s -> %s/%s' %
2376 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002377 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002378 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002379 'ONOS does not have the link %s/%s -> %s/%s' %
2380 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002381 linkResults = linkResults and firstDir and secondDir
2382 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002383
Jon Hallafa8a472015-06-12 14:02:42 -07002384 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002385 """
Jon Hallafa8a472015-06-12 14:02:42 -07002386 Compare mn and onos Hosts.
2387 Since Mininet hosts are quiet, ONOS will only know of them when they
2388 speak. For this reason, we will only check that the hosts in ONOS
2389 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002390
Jon Hallafa8a472015-06-12 14:02:42 -07002391 Arguments:
2392 hostsJson: parsed json object from the onos hosts api
2393 Returns:
2394 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002395 import json
2396 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002397 for onosHost in hostsJson:
2398 onosMAC = onosHost[ 'mac' ].lower()
2399 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002400 for mnHost, info in hosts.iteritems():
2401 for mnIntf in info[ 'interfaces' ]:
2402 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002403 match = True
2404 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002405 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002406 pass # all is well
2407 else:
2408 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002409 main.log.error( "ONOS host " +
2410 onosHost[ 'id' ] +
2411 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002412 str( onosHost[ 'ipAddresses' ] ) +
2413 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002414 str( ip ) +
2415 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002416 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002417 onosHost,
2418 sort_keys=True,
2419 indent=4,
2420 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002421 main.log.info( output )
2422 hostResults = main.FALSE
2423 if not match:
2424 hostResults = main.FALSE
2425 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2426 "corresponding Mininet host." )
2427 output = json.dumps( onosHost,
2428 sort_keys=True,
2429 indent=4,
2430 separators=( ',', ': ' ) )
2431 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002432 return hostResults
2433
Jon Hallafa8a472015-06-12 14:02:42 -07002434 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002435 """
2436 Returns a list of all hosts
2437 Don't ask questions just use it"""
2438 self.handle.sendline( "" )
2439 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002440
Jon Hall7eb38402015-01-08 17:19:54 -08002441 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2442 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002443
kelvin-onlabd3b64892015-01-20 13:26:24 -08002444 handlePy = self.handle.before
2445 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2446 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002447
Jon Hall7eb38402015-01-08 17:19:54 -08002448 self.handle.sendline( "" )
2449 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002450
kelvin-onlabd3b64892015-01-20 13:26:24 -08002451 hostStr = handlePy.replace( "]", "" )
2452 hostStr = hostStr.replace( "'", "" )
2453 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002454 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002455 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002456
kelvin-onlabd3b64892015-01-20 13:26:24 -08002457 return hostList
adminbae64d82013-08-01 10:50:15 -07002458
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002459 def getSwitch( self ):
2460 """
2461 Returns a list of all switches
2462 Again, don't ask question just use it...
2463 """
2464 # get host list...
2465 hostList = self.getHosts()
2466 # Make host set
2467 hostSet = set( hostList )
2468
2469 # Getting all the nodes in mininet
2470 self.handle.sendline( "" )
2471 self.handle.expect( "mininet>" )
2472
2473 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2474 self.handle.expect( "mininet>" )
2475
2476 handlePy = self.handle.before
2477 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2478 handlePy = handlePy.rstrip()
2479
2480 self.handle.sendline( "" )
2481 self.handle.expect( "mininet>" )
2482
2483 nodesStr = handlePy.replace( "]", "" )
2484 nodesStr = nodesStr.replace( "'", "" )
2485 nodesStr = nodesStr.replace( "[", "" )
2486 nodesStr = nodesStr.replace( " ", "" )
2487 nodesList = nodesStr.split( "," )
2488
2489 nodesSet = set( nodesList )
2490 # discarding default controller(s) node
2491 nodesSet.discard( 'c0' )
2492 nodesSet.discard( 'c1' )
2493 nodesSet.discard( 'c2' )
2494
2495 switchSet = nodesSet - hostSet
2496 switchList = list( switchSet )
2497
2498 return switchList
2499
Jon Hall7eb38402015-01-08 17:19:54 -08002500 def update( self ):
2501 """
2502 updates the port address and status information for
2503 each port in mn"""
2504 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002505 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002506 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002507 self.handle.sendline( "" )
2508 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002509
Jon Hall7eb38402015-01-08 17:19:54 -08002510 self.handle.sendline( "update" )
2511 self.handle.expect( "update" )
2512 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002513
Jon Hall7eb38402015-01-08 17:19:54 -08002514 self.handle.sendline( "" )
2515 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002516
Jon Hallb1290e82014-11-18 16:17:48 -05002517 return main.TRUE
2518 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002519 main.log.error( self.name + ": EOF exception found" )
2520 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002521 main.cleanup()
2522 main.exit()
2523
Jon Halld80cc142015-07-06 13:36:05 -07002524 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002525 """
2526 Add vlan tag to a host.
2527 Dependencies:
2528 This class depends on the "vlan" package
2529 $ sudo apt-get install vlan
2530 Configuration:
2531 Load the 8021q module into the kernel
2532 $sudo modprobe 8021q
2533
2534 To make this setup permanent:
2535 $ sudo su -c 'echo "8021q" >> /etc/modules'
2536 """
2537 if self.handle:
2538 try:
Jon Halld80cc142015-07-06 13:36:05 -07002539 # get the ip address of the host
2540 main.log.info( "Get the ip address of the host" )
2541 ipaddr = self.getIPAddress( host )
2542 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002543
Jon Halld80cc142015-07-06 13:36:05 -07002544 # remove IP from interface intf
2545 # Ex: h1 ifconfig h1-eth0 inet 0
2546 main.log.info( "Remove IP from interface " )
2547 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2548 self.handle.sendline( cmd2 )
2549 self.handle.expect( "mininet>" )
2550 response = self.handle.before
2551 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002552
Jon Halld80cc142015-07-06 13:36:05 -07002553 # create VLAN interface
2554 # Ex: h1 vconfig add h1-eth0 100
2555 main.log.info( "Create Vlan" )
2556 cmd3 = host + " vconfig add " + intf + " " + vlan
2557 self.handle.sendline( cmd3 )
2558 self.handle.expect( "mininet>" )
2559 response = self.handle.before
2560 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002561
Jon Halld80cc142015-07-06 13:36:05 -07002562 # assign the host's IP to the VLAN interface
2563 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2564 main.log.info( "Assign the host IP to the vlan interface" )
2565 vintf = intf + "." + vlan
2566 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2567 self.handle.sendline( cmd4 )
2568 self.handle.expect( "mininet>" )
2569 response = self.handle.before
2570 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002571
2572 return main.TRUE
2573 except pexpect.EOF:
2574 main.log.error( self.name + ": EOF exception found" )
2575 main.log.error( self.name + ": " + self.handle.before )
2576 return main.FALSE
2577
adminbae64d82013-08-01 10:50:15 -07002578if __name__ != "__main__":
2579 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002580 sys.modules[ __name__ ] = MininetCliDriver()