blob: 659a7101c6515dff36c027c92f60a0c0774ae5e1 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
Jon Hallbe6dfc42015-01-12 17:37:25 -08005author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
Jon Hall7eb38402015-01-08 17:19:54 -08008TestON is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 2 of the License, or
11( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
Jon Hall7eb38402015-01-08 17:19:54 -080013TestON is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070017
Jon Hall7eb38402015-01-08 17:19:54 -080018You should have received a copy of the GNU General Public License
19along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
Jon Hallbe6dfc42015-01-12 17:37:25 -080021MininetCliDriver is the basic driver which will handle the Mininet functions
22
23Some functions rely on a modified version of Mininet. These functions
24should all be noted in the comments. To get this MN version run these commands
25from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080026 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080027 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080028 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080029 git pull
30
Jon Hall272a4db2015-01-12 17:43:48 -080031
32 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080033changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070034import pexpect
adminbae64d82013-08-01 10:50:15 -070035import re
36import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070037import types
kelvin-onlaba4074292015-07-09 15:19:49 -070038import os
Jon Hall1ccf82c2014-10-15 14:55:16 -040039from math import pow
adminbae64d82013-08-01 10:50:15 -070040from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070041
Jon Hall7eb38402015-01-08 17:19:54 -080042
kelvin-onlab50907142015-04-01 13:37:45 -070043class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080044
45 """
46 MininetCliDriver is the basic driver which will handle
47 the Mininet functions"""
48 def __init__( self ):
49 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070050 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080051 self.name = None
kelvin-onlabd9e23de2015-08-06 10:34:44 -070052 self.home = None
Jon Hall7eb38402015-01-08 17:19:54 -080053 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070054 self.flag = 0
55
Jon Hall7eb38402015-01-08 17:19:54 -080056 def connect( self, **connectargs ):
57 """
58 Here the main is the TestON instance after creating
59 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080060 try:
61 for key in connectargs:
62 vars( self )[ key ] = connectargs[ key ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070063 self.home = "~/mininet"
kelvin-onlaba1484582015-02-02 15:46:20 -080064 self.name = self.options[ 'name' ]
kelvin-onlabd9e23de2015-08-06 10:34:44 -070065 for key in self.options:
66 if key == "home":
67 self.home = self.options[ 'home' ]
68 break
69 if self.home is None or self.home == "":
70 self.home = "~/mininet"
kelvin-onlaba4074292015-07-09 15:19:49 -070071
72 try:
73 if os.getenv( str( self.ip_address ) ) != None:
74 self.ip_address = os.getenv( str( self.ip_address ) )
75 else:
76 main.log.info( self.name +
77 ": Trying to connect to " +
78 self.ip_address )
79
80 except KeyError:
81 main.log.info( "Invalid host name," +
82 " connecting to local host instead" )
83 self.ip_address = 'localhost'
84 except Exception as inst:
85 main.log.error( "Uncaught exception: " + str( inst ) )
86
kelvin-onlaba1484582015-02-02 15:46:20 -080087 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070088 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080089 self ).connect(
90 user_name=self.user_name,
91 ip_address=self.ip_address,
92 port=None,
93 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080094
kelvin-onlaba1484582015-02-02 15:46:20 -080095 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080096 main.log.info( "Connection successful to the host " +
97 self.user_name +
98 "@" +
99 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -0800100 return main.TRUE
101 else:
102 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -0800103 self.user_name +
104 "@" +
105 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800106 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800107 return main.FALSE
108 except pexpect.EOF:
109 main.log.error( self.name + ": EOF exception found" )
110 main.log.error( self.name + ": " + self.handle.before )
111 main.cleanup()
112 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800113 except Exception:
114 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800115 main.cleanup()
116 main.exit()
117
kelvin-onlab10e8d392015-06-03 13:53:45 -0700118 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800119 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700120 Description:
121 Starts Mininet accepts a topology(.py) file and/or an optional
122 argument, to start the mininet, as a parameter.
123 Can also send regular mininet command to load up desired topology.
124 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
125 Options:
126 topoFile = file path for topology file (.py)
127 args = extra option added when starting the topology from the file
128 mnCmd = Mininet command use to start topology
129 Returns:
130 main.TRUE if the mininet starts successfully, main.FALSE
131 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800132 """
Jon Hall7eb38402015-01-08 17:19:54 -0800133 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700134 # make sure old networks are cleaned up
135 main.log.info( self.name +
136 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800137 self.handle.sendline( "sudo mn -c" )
138 i = self.handle.expect( [ 'password\sfor\s',
139 'Cleanup\scomplete',
140 pexpect.EOF,
141 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800142 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800143 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700144 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800145 main.log.info( self.name + ": Sending sudo password" )
146 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800147 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800148 '\$',
149 pexpect.EOF,
150 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800151 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800152 if i == 1:
153 main.log.info( self.name + ": Clean" )
154 elif i == 2:
155 main.log.error( self.name + ": Connection terminated" )
156 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700157 main.log.error( self.name + ": Something while cleaning " +
158 "Mininet took too long... " )
159 # Craft the string to start mininet
160 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700161 if not mnCmd:
162 if topoFile is None or topoFile == '': # If no file is given
163 main.log.info( self.name + ": building fresh Mininet" )
164 cmdString += "mn "
165 if args is None or args == '':
166 # If no args given, use args from .topo file
167 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700168 " " + self.options[ 'arg2' ] +\
169 " --mac --controller " +\
170 self.options[ 'controller' ] + " " +\
171 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700172 else: # else only use given args
173 pass
174 # TODO: allow use of topo args and method args?
175 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700176 main.log.info(
177 "Starting Mininet from topo file " +
178 topoFile )
kelvin-onlab10e8d392015-06-03 13:53:45 -0700179 cmdString += topoFile + " "
180 if args is None:
181 args = ''
182 # TODO: allow use of args from .topo file?
183 cmdString += args
184 else:
185 main.log.info( "Starting Mininet topology using '" + mnCmd +
186 "' command" )
187 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700188 # Send the command and check if network started
189 self.handle.sendline( "" )
190 self.handle.expect( '\$' )
191 main.log.info( "Sending '" + cmdString + "' to " + self.name )
192 self.handle.sendline( cmdString )
193 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800194 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700195 'Exception',
196 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800197 pexpect.EOF,
198 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700199 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800200 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700201 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800202 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800203 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700204 response = str( self.handle.before +
205 self.handle.after )
206 self.handle.expect( '\$' )
207 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700208 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700209 main.log.error(
210 self.name +
211 ": Launching Mininet failed: " + response )
212 return main.FALSE
213 elif i == 2:
214 self.handle.expect( [ "\n",
215 pexpect.EOF,
216 pexpect.TIMEOUT ],
217 timeout )
218 main.log.info( self.handle.before )
219 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800220 main.log.error( self.name + ": Connection timeout" )
221 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700222 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800223 main.log.error(
224 self.name +
225 ": Something took too long... " )
226 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700227 # Why did we hit this part?
228 main.log.error( "startNet did not return correctly" )
229 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800230 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700231 main.log.error( self.name + ": Connection failed to the host " +
232 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800233 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700234 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800235
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800236 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400237 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800238 # In tree topology, if fanout arg is not given, by default it is 2
239 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400240 fanout = 2
241 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500242 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800243 while( k <= depth - 1 ):
244 count = count + pow( fanout, k )
245 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800246 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800247 while( k <= depth - 2 ):
248 # depth-2 gives you only core links and not considering
249 # edge links as seen by ONOS. If all the links including
250 # edge links are required, do depth-1
251 count = count + pow( fanout, k )
252 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800253 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800254 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800255 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800256
Jon Hall7eb38402015-01-08 17:19:54 -0800257 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800258 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800259 # by default it is 1
260 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400261 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800262 numSwitches = depth
263 numHostsPerSw = fanout
264 totalNumHosts = numSwitches * numHostsPerSw
265 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800266 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800267 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800268 topoDict = { "num_switches": int( numSwitches ),
269 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400270 return topoDict
271
kelvin-onlabd3b64892015-01-20 13:26:24 -0800272 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700273 """
274 Calculate the number of switches and links in a topo."""
275 # TODO: combine this function and numSwitchesNlinks
276 argList = self.options[ 'arg1' ].split( "," )
277 topoArgList = argList[ 0 ].split( " " )
278 argList = map( int, argList[ 1: ] )
279 topoArgList = topoArgList[ 1: ] + argList
280
281 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400282 return topoDict
283
GlennRCf07c44a2015-09-18 13:33:46 -0700284 def pingall( self, protocol="IPv4", timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800285 """
286 Verifies the reachability of the hosts using pingall command.
287 Optional parameter timeout allows you to specify how long to
288 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700289 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700290 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700291 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700292 ping
293 acceptableFailed - Set the number of acceptable failed pings for the
294 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800295 Returns:
296 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700297 otherwise main.FALSE
298 """
299 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700300 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700301 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700302 if self.handle:
303 main.log.info(
304 self.name +
305 ": Checking reachabilty to the hosts using pingall" )
306 response = ""
307 failedPings = 0
308 returnValue = main.TRUE
GlennRCf07c44a2015-09-18 13:33:46 -0700309 cmd = "pingall"
310 if protocol == "IPv6":
311 cmd = "py net.pingAll6()"
312 self.handle.sendline( cmd )
Jon Hall390696c2015-05-05 17:13:41 -0700313 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700314 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700315 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700316 pexpect.EOF,
317 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700318 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700319 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700320 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700321 response += self.handle.before
322 break
323 elif i == 1:
324 response += self.handle.before + self.handle.after
325 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700326 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700327 returnValue = main.FALSE
328 if shortCircuit:
329 main.log.error( self.name +
330 ": Aborting pingall - "
331 + str( failedPings ) +
332 " pings failed" )
333 break
Jon Hall390696c2015-05-05 17:13:41 -0700334 if ( time.time() - startTime ) > timeout:
335 returnValue = main.FALSE
336 main.log.error( self.name +
337 ": Aborting pingall - " +
338 "Function took too long " )
339 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700340 elif i == 2:
341 main.log.error( self.name +
342 ": EOF exception found" )
343 main.log.error( self.name + ": " +
344 self.handle.before )
345 main.cleanup()
346 main.exit()
347 elif i == 3:
348 response += self.handle.before
349 main.log.error( self.name +
350 ": TIMEOUT exception found" )
351 main.log.error( self.name +
352 ": " +
353 str( response ) )
354 # NOTE: Send ctrl-c to make sure pingall is done
355 self.handle.sendline( "\x03" )
356 self.handle.expect( "Interrupt" )
357 self.handle.expect( "mininet>" )
358 break
359 pattern = "Results\:"
360 main.log.info( "Pingall output: " + str( response ) )
361 if re.search( pattern, response ):
362 main.log.info( self.name + ": Pingall finished with "
363 + str( failedPings ) + " failed pings" )
364 return returnValue
365 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700366 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700367 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700368 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700369 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700370 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700371 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700372 main.log.error( self.name + ": Connection failed to the host" )
373 main.cleanup()
374 main.exit()
375 except pexpect.TIMEOUT:
376 if response:
377 main.log.info( "Pingall output: " + str( response ) )
378 main.log.error( self.name + ": pexpect.TIMEOUT found" )
379 return main.FALSE
380 except pexpect.EOF:
381 main.log.error( self.name + ": EOF exception found" )
382 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500383 main.cleanup()
384 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700385
Jon Hall7eb38402015-01-08 17:19:54 -0800386 def fpingHost( self, **pingParams ):
387 """
388 Uses the fping package for faster pinging...
389 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800390 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800391 command = args[ "SRC" ] + \
392 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
393 self.handle.sendline( command )
394 self.handle.expect(
395 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
396 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
397 response = self.handle.before
398 if re.search( ":\s-", response ):
399 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700400 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800401 elif re.search( ":\s\d{1,2}\.\d\d", response ):
402 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700403 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800404 main.log.info( self.name + ": Install fping on mininet machine... " )
405 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700406 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800407
Hari Krishna9592fc82015-07-31 15:11:15 -0700408 def pingallHosts( self, hostList ):
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400409 """
Hari Krishna9592fc82015-07-31 15:11:15 -0700410 Ping all specified IPv4 hosts
kelvin-onlab2ff57022015-05-29 10:48:51 -0700411
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400412 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700413 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700414
415 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400416 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700417
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400418 Returns main.FALSE if one or more of hosts specified
419 cannot reach each other"""
Hari Krishna9592fc82015-07-31 15:11:15 -0700420
421 cmd = " ping -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400422
423 try:
424 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700425
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400426 isReachable = main.TRUE
GlennRC6d506272015-09-25 11:36:07 -0700427 pingResponse = "IPv4 ping across specified hosts\n"
428 failedPings = 0
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400429 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700430 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400431 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700432 pingList = hostList[ :listIndex ] + \
433 hostList[ ( listIndex + 1 ): ]
GlennRCd10d3cc2015-09-24 12:47:16 -0700434
435 pingResponse += str(str(host) + " -> ")
436
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400437 for temp in pingList:
438 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700439 pingCmd = str( host ) + cmd + str( temp )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400440 self.handle.sendline( pingCmd )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700441 self.handle.expect( "mininet>" )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400442 response = self.handle.before
443 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRCd10d3cc2015-09-24 12:47:16 -0700444 pingResponse += str(" h" + str( temp[1:] ))
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400445 else:
GlennRCd10d3cc2015-09-24 12:47:16 -0700446 pingResponse += " X"
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400447 # One of the host to host pair is unreachable
448 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700449 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700450 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700451 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700452 return isReachable
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700453 except pexpect.TIMEOUT:
454 main.log.exception( self.name + ": TIMEOUT exception" )
Hari Krishna4223dbd2015-08-13 16:29:53 -0700455 return main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400456 except pexpect.EOF:
457 main.log.error( self.name + ": EOF exception found" )
458 main.log.error( self.name + ": " + self.handle.before )
459 main.cleanup()
460 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700461 except Exception:
462 main.log.exception( self.name + ": Uncaught exception!" )
463 main.cleanup()
464 main.exit()
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400465
kelvin-onlab9b42b0a2015-08-05 14:43:58 -0700466 def pingIpv6Hosts(self, hostList, prefix='1000::'):
Hari Krishna9592fc82015-07-31 15:11:15 -0700467 """
468 IPv6 ping all hosts in hostList. If no prefix passed this will use
469 default prefix of 1000::
470
471 Returns main.TRUE if all hosts specified can reach each other
472
GlennRC2cf7d952015-09-11 16:32:13 -0700473 Returns main.FALSE if one or more of hosts specified cannot reach each other
Hari Krishna9592fc82015-07-31 15:11:15 -0700474 """
475 try:
476 main.log.info( "Testing reachability between specified IPv6 hosts" )
477 isReachable = main.TRUE
478 cmd = " ping6 -c 1 -i 1 -W 8 "
GlennRC6d506272015-09-25 11:36:07 -0700479 pingResponse = "IPv6 Pingall output:\n"
480 failedPings = 0
Hari Krishna9592fc82015-07-31 15:11:15 -0700481 for host in hostList:
482 listIndex = hostList.index( host )
483 # List of hosts to ping other than itself
484 pingList = hostList[ :listIndex ] + \
485 hostList[ ( listIndex + 1 ): ]
486
GlennRC2cf7d952015-09-11 16:32:13 -0700487 pingResponse += str(str(host) + " -> ")
488
Hari Krishna9592fc82015-07-31 15:11:15 -0700489 for temp in pingList:
490 # Current host pings all other hosts specified
491 pingCmd = str( host ) + cmd + prefix + str( temp[1:] )
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700492 self.handle.sendline( pingCmd )
493 self.handle.expect( "mininet>" )
Hari Krishna9592fc82015-07-31 15:11:15 -0700494 response = self.handle.before
495 if re.search( ',\s0\%\spacket\sloss', response ):
GlennRC2cf7d952015-09-11 16:32:13 -0700496 pingResponse += str(" h" + str( temp[1:] ))
Hari Krishna9592fc82015-07-31 15:11:15 -0700497 else:
GlennRC2cf7d952015-09-11 16:32:13 -0700498 pingResponse += " X"
Hari Krishna9592fc82015-07-31 15:11:15 -0700499 # One of the host to host pair is unreachable
500 isReachable = main.FALSE
GlennRC6d506272015-09-25 11:36:07 -0700501 failedPings += 1
GlennRCd10d3cc2015-09-24 12:47:16 -0700502 pingResponse += "\n"
GlennRC6d506272015-09-25 11:36:07 -0700503 main.log.info( pingResponse + "Failed pings: " + str(failedPings) )
Hari Krishna9592fc82015-07-31 15:11:15 -0700504 return isReachable
505
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700506 except pexpect.TIMEOUT:
507 main.log.exception( self.name + ": TIMEOUT exception" )
508 return main.FALSE
Hari Krishna9592fc82015-07-31 15:11:15 -0700509 except pexpect.EOF:
510 main.log.error( self.name + ": EOF exception found" )
511 main.log.error( self.name + ": " + self.handle.before )
512 main.cleanup()
513 main.exit()
Hari Krishna3bf8ea82015-08-11 09:02:02 -0700514 except Exception:
515 main.log.exception( self.name + ": Uncaught exception!" )
516 main.cleanup()
517 main.exit()
Hari Krishna9592fc82015-07-31 15:11:15 -0700518
Jon Hall7eb38402015-01-08 17:19:54 -0800519 def pingHost( self, **pingParams ):
520 """
521 Ping from one mininet host to another
522 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800523 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800524 command = args[ "SRC" ] + " ping " + \
525 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700526 try:
Jon Hall61282e32015-03-19 11:34:11 -0700527 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800528 self.handle.sendline( command )
529 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700530 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800531 main.log.error(
532 self.name +
533 ": timeout when waiting for response from mininet" )
534 main.log.error( "response: " + str( self.handle.before ) )
535 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700536 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800537 main.log.error(
538 self.name +
539 ": timeout when waiting for response from mininet" )
540 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700541 response = self.handle.before
Hari Krishna012a1c12015-08-25 14:23:58 -0700542 if re.search( ',\s0\%\spacket\sloss', response ):
543 main.log.info( self.name + ": no packets lost, host is reachable" )
544 return main.TRUE
545 else:
546 main.log.error(
547 self.name +
548 ": PACKET LOST, HOST IS NOT REACHABLE" )
549 return main.FALSE
550
Jon Hallfbc828e2015-01-06 17:30:19 -0800551 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800552 main.log.error( self.name + ": EOF exception found" )
553 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700554 main.cleanup()
555 main.exit()
Hari Krishna012a1c12015-08-25 14:23:58 -0700556 except Exception:
557 main.log.exception( self.name + ": Uncaught exception!" )
558 main.cleanup()
559 main.exit()
560
561 def ping6pair( self, **pingParams ):
562 """
GlennRC2cf7d952015-09-11 16:32:13 -0700563 IPv6 Ping between a pair of mininet hosts
Hari Krishna012a1c12015-08-25 14:23:58 -0700564 Currently the only supported Params are: SRC , TARGET
565 FLOWLABEL and -I (src interface) will be added later after running some tests.
566 Example: main.Mininet1.ping6pair( src="h1", target="1000::2" )
567 """
568 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
569 command = args[ "SRC" ] + " ping6 " + \
570 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
571 try:
572 main.log.info( "Sending: " + command )
573 self.handle.sendline( command )
574 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
575 if i == 1:
576 main.log.error(
577 self.name +
578 ": timeout when waiting for response from mininet" )
579 main.log.error( "response: " + str( self.handle.before ) )
580 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
581 if i == 1:
582 main.log.error(
583 self.name +
584 ": timeout when waiting for response from mininet" )
585 main.log.error( "response: " + str( self.handle.before ) )
586 response = self.handle.before
587 main.log.info( self.name + ": Ping Response: " + response )
588 if re.search( ',\s0\%\spacket\sloss', response ):
589 main.log.info( self.name + ": no packets lost, host is reachable" )
GlennRC2cf7d952015-09-11 16:32:13 -0700590 return main.TRUE
Hari Krishna012a1c12015-08-25 14:23:58 -0700591 else:
592 main.log.error(
593 self.name +
594 ": PACKET LOST, HOST IS NOT REACHABLE" )
595 return main.FALSE
596
597 except pexpect.EOF:
598 main.log.error( self.name + ": EOF exception found" )
599 main.log.error( self.name + ": " + self.handle.before )
600 main.cleanup()
601 main.exit()
602 except Exception:
603 main.log.exception( self.name + ": Uncaught exception!" )
604 main.cleanup()
605 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800606
Jon Hall7eb38402015-01-08 17:19:54 -0800607 def checkIP( self, host ):
608 """
609 Verifies the host's ip configured or not."""
610 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700611 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800612 response = self.execute(
613 cmd=host +
614 " ifconfig",
615 prompt="mininet>",
616 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800617 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800618 main.log.error( self.name + ": EOF exception found" )
619 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700620 main.cleanup()
621 main.exit()
adminbae64d82013-08-01 10:50:15 -0700622
Jon Hall7eb38402015-01-08 17:19:54 -0800623 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800624 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
625 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
626 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
627 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
628 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800629 # pattern = "inet addr:10.0.0.6"
630 if re.search( pattern, response ):
631 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700632 return main.TRUE
633 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800634 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700635 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800636 else:
637 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800638
Jon Hall7eb38402015-01-08 17:19:54 -0800639 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800640 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700641 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800642 response = self.execute(
643 cmd="h1 /usr/sbin/sshd -D&",
644 prompt="mininet>",
645 timeout=10 )
646 response = self.execute(
647 cmd="h4 /usr/sbin/sshd -D&",
648 prompt="mininet>",
649 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700650 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800651 vars( self )[ key ] = connectargs[ key ]
652 response = self.execute(
653 cmd="xterm h1 h4 ",
654 prompt="mininet>",
655 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800656 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800657 main.log.error( self.name + ": EOF exception found" )
658 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700659 main.cleanup()
660 main.exit()
adminbae64d82013-08-01 10:50:15 -0700661 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800662 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700663 if self.flag == 0:
664 self.flag = 1
665 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800666 else:
adminbae64d82013-08-01 10:50:15 -0700667 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800668
kelvin-onlaba1484582015-02-02 15:46:20 -0800669 def moveHost( self, host, oldSw, newSw, ):
670 """
671 Moves a host from one switch to another on the fly
672 Note: The intf between host and oldSw when detached
673 using detach(), will still show up in the 'net'
674 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700675 ( which is correct behavior since the interfaces
676 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800677 """
678 if self.handle:
679 try:
680 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700681 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800682 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800683 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800684 response = self.execute( cmd=cmd,
685 prompt="mininet>",
686 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700687
kelvin-onlaba1484582015-02-02 15:46:20 -0800688 # Determine hostintf and Oldswitchintf
689 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800690 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800691 print "cmd2= ", cmd
692 self.handle.sendline( cmd )
693 self.handle.expect( "mininet>" )
694
shahshreya73537862015-02-11 15:15:24 -0800695 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800696 cmd = "px ipaddr = hintf.IP()"
697 print "cmd3= ", cmd
698 self.handle.sendline( cmd )
699 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800700
701 cmd = "px macaddr = hintf.MAC()"
702 print "cmd3= ", 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 # Detach interface between oldSw-host
707 cmd = "px " + oldSw + ".detach( sintf )"
708 print "cmd4= ", cmd
709 self.handle.sendline( cmd )
710 self.handle.expect( "mininet>" )
711
712 # Add link between host-newSw
713 cmd = "py net.addLink(" + host + "," + newSw + ")"
714 print "cmd5= ", cmd
715 self.handle.sendline( cmd )
716 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700717
kelvin-onlaba1484582015-02-02 15:46:20 -0800718 # Determine hostintf and Newswitchintf
719 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800720 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800721 print "cmd6= ", cmd
722 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700723 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800724
725 # Attach interface between newSw-host
726 cmd = "px " + newSw + ".attach( sintf )"
727 print "cmd3= ", 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 # Set ipaddress of the host-newSw interface
732 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
733 print "cmd7 = ", cmd
734 self.handle.sendline( cmd )
735 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800736
737 # Set macaddress of the host-newSw interface
738 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
739 print "cmd8 = ", cmd
740 self.handle.sendline( cmd )
741 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700742
kelvin-onlaba1484582015-02-02 15:46:20 -0800743 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800744 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800745 self.handle.sendline( cmd )
746 self.handle.expect( "mininet>" )
747 print "output = ", self.handle.before
748
749 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800750 cmd = host + " ifconfig"
751 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800752 self.handle.sendline( cmd )
753 self.handle.expect( "mininet>" )
754 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700755
kelvin-onlaba1484582015-02-02 15:46:20 -0800756 return main.TRUE
757 except pexpect.EOF:
758 main.log.error( self.name + ": EOF exception found" )
759 main.log.error( self.name + ": " + self.handle.before )
760 return main.FALSE
761
Jon Hall7eb38402015-01-08 17:19:54 -0800762 def changeIP( self, host, intf, newIP, newNetmask ):
763 """
764 Changes the ip address of a host on the fly
765 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800766 if self.handle:
767 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800768 cmd = host + " ifconfig " + intf + " " + \
769 newIP + " " + 'netmask' + " " + newNetmask
770 self.handle.sendline( cmd )
771 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800772 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800773 main.log.info( "response = " + response )
774 main.log.info(
775 "Ip of host " +
776 host +
777 " changed to new IP " +
778 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800779 return main.TRUE
780 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800781 main.log.error( self.name + ": EOF exception found" )
782 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800783 return main.FALSE
784
Jon Hall7eb38402015-01-08 17:19:54 -0800785 def changeDefaultGateway( self, host, newGW ):
786 """
787 Changes the default gateway of a host
788 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800789 if self.handle:
790 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800791 cmd = host + " route add default gw " + newGW
792 self.handle.sendline( cmd )
793 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800794 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800795 main.log.info( "response = " + response )
796 main.log.info(
797 "Default gateway of host " +
798 host +
799 " changed to " +
800 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800801 return main.TRUE
802 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800803 main.log.error( self.name + ": EOF exception found" )
804 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800805 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800806
Jon Hall7eb38402015-01-08 17:19:54 -0800807 def addStaticMACAddress( self, host, GW, macaddr ):
808 """
Jon Hallefbd9792015-03-05 16:11:36 -0800809 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800810 if self.handle:
811 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800812 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
813 cmd = host + " arp -s " + GW + " " + macaddr
814 self.handle.sendline( cmd )
815 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800816 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800817 main.log.info( "response = " + response )
818 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800819 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800820 GW +
821 " changed to " +
822 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800823 return main.TRUE
824 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800825 main.log.error( self.name + ": EOF exception found" )
826 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800827 return main.FALSE
828
Jon Hall7eb38402015-01-08 17:19:54 -0800829 def verifyStaticGWandMAC( self, host ):
830 """
831 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800832 if self.handle:
833 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800834 # h1 arp -an
835 cmd = host + " arp -an "
836 self.handle.sendline( cmd )
837 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800838 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800839 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800840 return main.TRUE
841 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800842 main.log.error( self.name + ": EOF exception found" )
843 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800844 return main.FALSE
845
Jon Hall7eb38402015-01-08 17:19:54 -0800846 def getMacAddress( self, host ):
847 """
848 Verifies the host's ip configured or not."""
849 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700850 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800851 response = self.execute(
852 cmd=host +
853 " ifconfig",
854 prompt="mininet>",
855 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800856 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800857 main.log.error( self.name + ": EOF exception found" )
858 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700859 main.cleanup()
860 main.exit()
adminbae64d82013-08-01 10:50:15 -0700861
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700862 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800863 macAddressSearch = re.search( pattern, response, re.I )
864 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800865 main.log.info(
866 self.name +
867 ": Mac-Address of Host " +
868 host +
869 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800870 macAddress )
871 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700872 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800873 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700874
Jon Hall7eb38402015-01-08 17:19:54 -0800875 def getInterfaceMACAddress( self, host, interface ):
876 """
877 Return the IP address of the interface on the given host"""
878 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700879 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800880 response = self.execute( cmd=host + " ifconfig " + interface,
881 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800882 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800883 main.log.error( self.name + ": EOF exception found" )
884 main.log.error( self.name + ": " + self.handle.before )
885 main.cleanup()
886 main.exit()
887
888 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800889 macAddressSearch = re.search( pattern, response, re.I )
890 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800891 main.log.info( "No mac address found in %s" % response )
892 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800893 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800894 main.log.info(
895 "Mac-Address of " +
896 host +
897 ":" +
898 interface +
899 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800900 macAddress )
901 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800902 else:
903 main.log.error( "Connection failed to the host" )
904
905 def getIPAddress( self, host ):
906 """
907 Verifies the host's ip configured or not."""
908 if self.handle:
909 try:
910 response = self.execute(
911 cmd=host +
912 " ifconfig",
913 prompt="mininet>",
914 timeout=10 )
915 except pexpect.EOF:
916 main.log.error( self.name + ": EOF exception found" )
917 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700918 main.cleanup()
919 main.exit()
adminbae64d82013-08-01 10:50:15 -0700920
921 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800922 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800923 main.log.info(
924 self.name +
925 ": IP-Address of Host " +
926 host +
927 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800928 ipAddressSearch.group( 1 ) )
929 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800930 else:
931 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800932
Jon Hall7eb38402015-01-08 17:19:54 -0800933 def getSwitchDPID( self, switch ):
934 """
935 return the datapath ID of the switch"""
936 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700937 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700938 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800939 response = self.execute(
940 cmd=cmd,
941 prompt="mininet>",
942 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800943 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800944 main.log.error( self.name + ": EOF exception found" )
945 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700946 main.cleanup()
947 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800948 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800949 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700950 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800951 main.log.info(
952 "Couldn't find DPID for switch %s, found: %s" %
953 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700954 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800955 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700956 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800957 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700958
Jon Hall7eb38402015-01-08 17:19:54 -0800959 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700960 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800961 self.handle.sendline( "" )
962 self.expect( "mininet>" )
963 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700964 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800965 response = self.execute(
966 cmd=cmd,
967 prompt="mininet>",
968 timeout=10 )
969 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700970 response = self.handle.before
971 return response
972 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800973 main.log.error( self.name + ": EOF exception found" )
974 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700975 main.cleanup()
976 main.exit()
977
Jon Hall7eb38402015-01-08 17:19:54 -0800978 def getInterfaces( self, node ):
979 """
980 return information dict about interfaces connected to the node"""
981 if self.handle:
982 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800983 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700984 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700985 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800986 response = self.execute(
987 cmd=cmd,
988 prompt="mininet>",
989 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800990 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800991 main.log.error( self.name + ": EOF exception found" )
992 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700993 main.cleanup()
994 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700995 return response
996 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800997 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700998
Jon Hall7eb38402015-01-08 17:19:54 -0800999 def dump( self ):
1000 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -07001001 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001002 response = self.execute(
1003 cmd='dump',
1004 prompt='mininet>',
1005 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001006 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001007 main.log.error( self.name + ": EOF exception found" )
1008 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001009 main.cleanup()
1010 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -07001011 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001012
Jon Hall7eb38402015-01-08 17:19:54 -08001013 def intfs( self ):
1014 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -07001015 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001016 response = self.execute(
1017 cmd='intfs',
1018 prompt='mininet>',
1019 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001020 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001021 main.log.error( self.name + ": EOF exception found" )
1022 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001023 main.cleanup()
1024 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001025 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001026
Jon Hall7eb38402015-01-08 17:19:54 -08001027 def net( self ):
1028 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -07001029 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001030 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001031 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001032 main.log.error( self.name + ": EOF exception found" )
1033 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001034 main.cleanup()
1035 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001036 return response
Jon Hall7eb38402015-01-08 17:19:54 -08001037
Jon Hallafa8a472015-06-12 14:02:42 -07001038 def links( self ):
1039 main.log.info( self.name + ": List network links" )
1040 try:
1041 response = self.execute( cmd='links', prompt='mininet>',
1042 timeout=10 )
1043 except pexpect.EOF:
1044 main.log.error( self.name + ": EOF exception found" )
1045 main.log.error( self.name + ": " + self.handle.before )
1046 main.cleanup()
1047 main.exit()
1048 return response
1049
GlennRC61321f22015-07-16 13:36:54 -07001050 def iperftcpAll(self, hosts, timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001051 '''
1052 Runs the iperftcp function with a given set of hosts and specified timeout.
GlennRC61321f22015-07-16 13:36:54 -07001053
kelvin-onlab7cce9382015-07-17 10:21:03 -07001054 @parm:
1055 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1056 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1057 '''
1058 for host1 in hosts:
1059 for host2 in hosts:
1060 if host1 != host2:
1061 if self.iperftcp(host1, host2, timeout) == main.FALSE:
1062 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
GlennRC61321f22015-07-16 13:36:54 -07001063
1064 def iperftcp(self, host1="h1", host2="h2", timeout=6):
kelvin-onlab7cce9382015-07-17 10:21:03 -07001065 '''
1066 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
1067 are valid.
GlennRC61321f22015-07-16 13:36:54 -07001068
kelvin-onlab7cce9382015-07-17 10:21:03 -07001069 @parm:
1070 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete,
1071 and short enough to stop an unsuccessful test from quiting and cleaning up mininet.
1072 '''
1073 main.log.info( self.name + ": Simple iperf TCP test between two hosts" )
1074 try:
1075 # Setup the mininet command
1076 cmd1 = 'iperf ' + host1 + " " + host2
1077 self.handle.sendline( cmd1 )
1078 outcome = self.handle.expect( "mininet>", timeout )
1079 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001080
kelvin-onlab7cce9382015-07-17 10:21:03 -07001081 # checks if there are results in the mininet response
1082 if "Results:" in response:
1083 main.log.report(self.name + ": iperf test completed")
1084 # parse the mn results
1085 response = response.split("\r\n")
1086 response = response[len(response)-2]
1087 response = response.split(": ")
1088 response = response[len(response)-1]
1089 response = response.replace("[", "")
1090 response = response.replace("]", "")
1091 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001092
kelvin-onlab7cce9382015-07-17 10:21:03 -07001093 # this is the bandwith two and from the two hosts
1094 bandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001095
kelvin-onlab7cce9382015-07-17 10:21:03 -07001096 # there should be two elements in the bandwidth list
1097 # ['host1 to host2', 'host2 to host1"]
1098 if len(bandwidth) == 2:
1099 main.log.report(self.name + ": iperf test successful")
1100 return main.TRUE
1101 else:
1102 main.log.error(self.name + ": invalid iperf results")
1103 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -08001104 else:
kelvin-onlab7cce9382015-07-17 10:21:03 -07001105 main.log.error( self.name + ": iperf test failed" )
Jon Hall7eb38402015-01-08 17:19:54 -08001106 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001107
GlennRC61321f22015-07-16 13:36:54 -07001108 except pexpect.TIMEOUT:
1109 main.log.error( self.name + ": TIMEOUT exception found")
1110 main.log.error( self.name + ": Exception: Cannot connect to iperf on port 5001" )
1111 return main.FALSE
1112
Jon Hallfbc828e2015-01-06 17:30:19 -08001113 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001114 main.log.error( self.name + ": EOF exception found" )
1115 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001116 main.cleanup()
kelvin-onlab7cce9382015-07-17 10:21:03 -07001117 main.exit()
GlennRC61321f22015-07-16 13:36:54 -07001118
1119 def iperfudpAll(self, hosts, bandwidth="10M"):
1120 '''
1121 Runs the iperfudp function with a given set of hosts and specified
1122 bandwidth
kelvin-onlab7cce9382015-07-17 10:21:03 -07001123
GlennRC61321f22015-07-16 13:36:54 -07001124 @param:
1125 bandwidth: the targeted bandwidth, in megabits ('M')
1126 '''
1127 for host1 in hosts:
1128 for host2 in hosts:
1129 if host1 != host2:
1130 if self.iperfudp(host1, host2, bandwidth) == main.FALSE:
1131 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1132
1133 def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1134
kelvin-onlab7cce9382015-07-17 10:21:03 -07001135 '''
1136 Creates an iperf UDP test with a specific bandwidth.
1137 Returns true if results are valid.
GlennRC61321f22015-07-16 13:36:54 -07001138
kelvin-onlab7cce9382015-07-17 10:21:03 -07001139 @param:
1140 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test
1141 '''
1142 main.log.info(self.name + ": Simple iperf UDP test between two hosts")
1143 try:
1144 # setup the mininet command
1145 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2
1146 self.handle.sendline(cmd)
1147 self.handle.expect("mininet>")
1148 response = self.handle.before
GlennRC61321f22015-07-16 13:36:54 -07001149
kelvin-onlab7cce9382015-07-17 10:21:03 -07001150 # check if there are in results in the mininet response
1151 if "Results:" in response:
1152 main.log.report(self.name + ": iperfudp test completed")
1153 # parse the results
1154 response = response.split("\r\n")
1155 response = response[len(response)-2]
1156 response = response.split(": ")
1157 response = response[len(response)-1]
1158 response = response.replace("[", "")
1159 response = response.replace("]", "")
1160 response = response.replace("\'", "")
GlennRC61321f22015-07-16 13:36:54 -07001161
kelvin-onlab7cce9382015-07-17 10:21:03 -07001162 mnBandwidth = response.split(", ")
GlennRC61321f22015-07-16 13:36:54 -07001163
kelvin-onlab7cce9382015-07-17 10:21:03 -07001164 # check to see if there are at least three entries
1165 # ['bandwidth', 'host1 to host2', 'host2 to host1']
1166 if len(mnBandwidth) == 3:
1167 # if one entry is blank then something is wrong
1168 for item in mnBandwidth:
1169 if item == "":
1170 main.log.error(self.name + ": Could not parse iperf output")
1171 main.log.error(self.name + ": invalid iperfudp results")
1172 return main.FALSE
1173 # otherwise results are vaild
1174 main.log.report(self.name + ": iperfudp test successful")
1175 return main.TRUE
1176 else:
1177 main.log.error(self.name + ": invalid iperfudp results")
1178 return main.FALSE
GlennRC61321f22015-07-16 13:36:54 -07001179
kelvin-onlab7cce9382015-07-17 10:21:03 -07001180 except pexpect.EOF:
1181 main.log.error( self.name + ": EOF exception found" )
1182 main.log.error( self.name + ": " + self.handle.before )
1183 main.cleanup()
1184 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001185
Jon Hall7eb38402015-01-08 17:19:54 -08001186 def nodes( self ):
1187 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -07001188 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001189 response = self.execute(
1190 cmd='nodes',
1191 prompt='mininet>',
1192 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001193 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001194 main.log.error( self.name + ": EOF exception found" )
1195 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001196 main.cleanup()
1197 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -07001198 return response
Jon Hallfbc828e2015-01-06 17:30:19 -08001199
Jon Hall7eb38402015-01-08 17:19:54 -08001200 def pingpair( self ):
1201 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -07001202 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001203 response = self.execute(
1204 cmd='pingpair',
1205 prompt='mininet>',
1206 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001207 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001208 main.log.error( self.name + ": EOF exception found" )
1209 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001210 main.cleanup()
1211 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001212
Jon Hall7eb38402015-01-08 17:19:54 -08001213 if re.search( ',\s0\%\spacket\sloss', response ):
1214 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
adminbae64d82013-08-01 10:50:15 -07001215 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001216 else:
1217 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
adminbae64d82013-08-01 10:50:15 -07001218 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001219
Jon Hall7eb38402015-01-08 17:19:54 -08001220 def link( self, **linkargs ):
1221 """
1222 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001223 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001224 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1225 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1226 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1227 main.log.info(
1228 "Bring link between '" +
1229 end1 +
1230 "' and '" +
1231 end2 +
1232 "' '" +
1233 option +
1234 "'" )
1235 command = "link " + \
1236 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001237 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001238 self.handle.sendline( command )
1239 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001240 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001241 main.log.error( self.name + ": EOF exception found" )
1242 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001243 main.cleanup()
1244 main.exit()
adminbae64d82013-08-01 10:50:15 -07001245 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001246
pingping-lin8244a3b2015-09-16 13:36:56 -07001247 def switch( self, **switchargs ):
1248 """
1249 start/stop a switch
1250 """
1251 args = utilities.parse_args( [ "SW", "OPTION" ], **switchargs )
1252 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1253 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1254 command = "switch " + str( sw ) + " " + str( option )
1255 main.log.info( command )
1256 try:
1257 self.handle.sendline( command )
1258 self.handle.expect( "mininet>" )
1259 except pexpect.TIMEOUT:
1260 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1261 main.cleanup()
1262 main.exit()
1263 except pexpect.EOF:
1264 main.log.error( self.name + ": EOF exception found" )
1265 main.log.error( self.name + ": " + self.handle.before )
1266 main.cleanup()
1267 main.exit()
1268 return main.TRUE
1269
Jon Hall7eb38402015-01-08 17:19:54 -08001270 def yank( self, **yankargs ):
1271 """
1272 yank a mininet switch interface to a host"""
1273 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001274 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001275 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1276 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1277 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001278 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001279 response = self.execute(
1280 cmd=command,
1281 prompt="mininet>",
1282 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001283 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001284 main.log.error( self.name + ": EOF exception found" )
1285 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001286 main.cleanup()
1287 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001288 return main.TRUE
1289
Jon Hall7eb38402015-01-08 17:19:54 -08001290 def plug( self, **plugargs ):
1291 """
1292 plug the yanked mininet switch interface to a switch"""
1293 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001294 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001295 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1296 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1297 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001298 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001299 response = self.execute(
1300 cmd=command,
1301 prompt="mininet>",
1302 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001303 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001304 main.log.error( self.name + ": EOF exception found" )
1305 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001306 main.cleanup()
1307 main.exit()
adminbae64d82013-08-01 10:50:15 -07001308 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001309
Jon Hall7eb38402015-01-08 17:19:54 -08001310 def dpctl( self, **dpctlargs ):
1311 """
1312 Run dpctl command on all switches."""
1313 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001314 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001315 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1316 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1317 command = "dpctl " + cmd + " " + str( cmdargs )
1318 try:
1319 response = self.execute(
1320 cmd=command,
1321 prompt="mininet>",
1322 timeout=10 )
1323 except pexpect.EOF:
1324 main.log.error( self.name + ": EOF exception found" )
1325 main.log.error( self.name + ": " + self.handle.before )
1326 main.cleanup()
1327 main.exit()
1328 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001329
kelvin-onlabd3b64892015-01-20 13:26:24 -08001330 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001331 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001332 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001333 fileInput = path + '/lib/Mininet/INSTALL'
1334 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001335 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001336 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001337 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001338 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001339 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001340 return version
adminbae64d82013-08-01 10:50:15 -07001341
kelvin-onlabd3b64892015-01-20 13:26:24 -08001342 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001343 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001344 Parameters:
1345 sw: The name of an OVS switch. Example "s1"
1346 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001347 The output of the command from the mininet cli
1348 or main.FALSE on timeout"""
1349 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001350 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001351 response = self.execute(
1352 cmd=command,
1353 prompt="mininet>",
1354 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001355 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001356 return response
admin2a9548d2014-06-17 14:08:07 -07001357 else:
1358 return main.FALSE
1359 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001360 main.log.error( self.name + ": EOF exception found" )
1361 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001362 main.cleanup()
1363 main.exit()
adminbae64d82013-08-01 10:50:15 -07001364
Charles Chan029be652015-08-24 01:46:10 +08001365 def assignSwController( self, sw, ip, port="6653", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001366 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001367 Description:
1368 Assign switches to the controllers ( for ovs use only )
1369 Required:
1370 sw - Name of the switch. This can be a list or a string.
1371 ip - Ip addresses of controllers. This can be a list or a string.
1372 Optional:
Charles Chan029be652015-08-24 01:46:10 +08001373 port - ONOS use port 6653, if no list of ports is passed, then
1374 the all the controller will use 6653 as their port number
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001375 ptcp - ptcp number, This can be a string or a list that has
1376 the same length as switch. This is optional and not required
1377 when using ovs switches.
1378 NOTE: If switches and ptcp are given in a list type they should have the
1379 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1380 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001381
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001382 Return:
1383 Returns main.TRUE if mininet correctly assigned switches to
1384 controllers, otherwise it will return main.FALSE or an appropriate
1385 exception(s)
1386 """
1387 assignResult = main.TRUE
1388 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001389 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001390 command = "sh ovs-vsctl set-controller "
1391 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001392 try:
1393 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001394 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001395 if isinstance( port, types.StringType ) or \
1396 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001397 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001398 elif isinstance( port, types.ListType ):
1399 main.log.error( self.name + ": Only one controller " +
1400 "assigned and a list of ports has" +
1401 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001402 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001403 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001404 main.log.error( self.name + ": Invalid controller port " +
1405 "number. Please specify correct " +
1406 "controller port" )
1407 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001408
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001409 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001410 if isinstance( port, types.StringType ) or \
1411 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001412 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001413 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1414 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001415 elif isinstance( port, types.ListType ):
1416 if ( len( ip ) != len( port ) ):
1417 main.log.error( self.name + ": Port list = " +
1418 str( len( port ) ) +
1419 "should be the same as controller" +
1420 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001421 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001422 else:
1423 onosIp = ""
1424 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001425 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1426 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001427 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001428 main.log.error( self.name + ": Invalid controller port " +
1429 "number. Please specify correct " +
1430 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001431 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001432 else:
1433 main.log.error( self.name + ": Invalid ip address" )
1434 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001435
1436 if isinstance( sw, types.StringType ):
1437 command += sw + " "
1438 if ptcp:
1439 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001440 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001441 elif isinstance( ptcp, types.ListType ):
1442 main.log.error( self.name + ": Only one switch is " +
1443 "being set and multiple PTCP is " +
1444 "being passed " )
1445 else:
1446 main.log.error( self.name + ": Invalid PTCP" )
1447 ptcp = ""
1448 command += onosIp
1449 commandList.append( command )
1450
1451 elif isinstance( sw, types.ListType ):
1452 if ptcp:
1453 if isinstance( ptcp, types.ListType ):
1454 if len( ptcp ) != len( sw ):
1455 main.log.error( self.name + ": PTCP length = " +
1456 str( len( ptcp ) ) +
1457 " is not the same as switch" +
1458 " length = " +
1459 str( len( sw ) ) )
1460 return main.FALSE
1461 else:
1462 for switch, ptcpNum in zip( sw, ptcp ):
1463 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001464 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001465 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001466 tempCmd += onosIp
1467 commandList.append( tempCmd )
1468 else:
1469 main.log.error( self.name + ": Invalid PTCP" )
1470 return main.FALSE
1471 else:
1472 for switch in sw:
1473 tempCmd = "sh ovs-vsctl set-controller "
1474 tempCmd += switch + " " + onosIp
1475 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001476 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001477 main.log.error( self.name + ": Invalid switch type " )
1478 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001479
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001480 for cmd in commandList:
1481 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001482 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001483 except pexpect.TIMEOUT:
1484 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1485 return main.FALSE
1486 except pexpect.EOF:
1487 main.log.error( self.name + ": EOF exception found" )
1488 main.log.error( self.name + ": " + self.handle.before )
1489 main.cleanup()
1490 main.exit()
1491 return main.TRUE
1492 except Exception:
1493 main.log.exception( self.name + ": Uncaught exception!" )
1494 main.cleanup()
1495 main.exit()
adminbae64d82013-08-01 10:50:15 -07001496
kelvin-onlabd3b64892015-01-20 13:26:24 -08001497 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001498 """
1499 Removes the controller target from sw"""
1500 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001501 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001502 response = self.execute(
1503 cmd=command,
1504 prompt="mininet>",
1505 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001506 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001507 main.log.error( self.name + ": EOF exception found" )
1508 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001509 main.cleanup()
1510 main.exit()
1511 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001512 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001513
kelvin-onlabd3b64892015-01-20 13:26:24 -08001514 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001515 """
Jon Hallb1290e82014-11-18 16:17:48 -05001516 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001517 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001518 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001519 NOTE: cannot currently specify what type of switch
1520 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001521 sw = name of the new switch as a string
1522 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001523 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001524 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001525 """
1526 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001527 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001528 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001529 response = self.execute(
1530 cmd=command,
1531 prompt="mininet>",
1532 timeout=10 )
1533 if re.search( "already exists!", response ):
1534 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001535 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001536 elif re.search( "Error", response ):
1537 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001538 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001539 elif re.search( "usage:", response ):
1540 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001541 return main.FALSE
1542 else:
1543 return main.TRUE
1544 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001545 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001546 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001547 main.cleanup()
1548 main.exit()
1549
kelvin-onlabd3b64892015-01-20 13:26:24 -08001550 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001551 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001552 delete a switch from the mininet topology
1553 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001554 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001555 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001556 sw = name of the switch as a string
1557 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001558 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001559 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001560 response = self.execute(
1561 cmd=command,
1562 prompt="mininet>",
1563 timeout=10 )
1564 if re.search( "no switch named", response ):
1565 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001566 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001567 elif re.search( "Error", response ):
1568 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001569 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001570 elif re.search( "usage:", response ):
1571 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001572 return main.FALSE
1573 else:
1574 return main.TRUE
1575 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001576 main.log.error( self.name + ": EOF exception found" )
1577 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001578 main.cleanup()
1579 main.exit()
1580
kelvin-onlabd3b64892015-01-20 13:26:24 -08001581 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001582 """
1583 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001584 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001585 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001586 NOTE: cannot currently specify what type of link
1587 required params:
1588 node1 = the string node name of the first endpoint of the link
1589 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001590 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001591 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001592 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001593 response = self.execute(
1594 cmd=command,
1595 prompt="mininet>",
1596 timeout=10 )
1597 if re.search( "doesnt exist!", response ):
1598 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001599 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001600 elif re.search( "Error", response ):
1601 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001602 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001603 elif re.search( "usage:", response ):
1604 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001605 return main.FALSE
1606 else:
1607 return main.TRUE
1608 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 main.log.error( self.name + ": EOF exception found" )
1610 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001611 main.cleanup()
1612 main.exit()
1613
kelvin-onlabd3b64892015-01-20 13:26:24 -08001614 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001615 """
1616 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001617 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001618 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001619 required params:
1620 node1 = the string node name of the first endpoint of the link
1621 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001622 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001623 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001624 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001625 response = self.execute(
1626 cmd=command,
1627 prompt="mininet>",
1628 timeout=10 )
1629 if re.search( "no node named", response ):
1630 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001631 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001632 elif re.search( "Error", response ):
1633 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001634 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001635 elif re.search( "usage:", response ):
1636 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001637 return main.FALSE
1638 else:
1639 return main.TRUE
1640 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001641 main.log.error( self.name + ": EOF exception found" )
1642 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001643 main.cleanup()
1644 main.exit()
1645
kelvin-onlabd3b64892015-01-20 13:26:24 -08001646 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001647 """
Jon Hallb1290e82014-11-18 16:17:48 -05001648 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001649 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001650 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001651 NOTE: cannot currently specify what type of host
1652 required params:
1653 hostname = the string hostname
1654 optional key-value params
1655 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001656 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001657 """
1658 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001659 command = "addhost " + str( hostname ) + " " + str( switch )
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( "already exists!", 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( "doesnt exists!", response ):
1669 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001670 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001671 elif re.search( "Error", response ):
1672 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001673 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001674 elif re.search( "usage:", response ):
1675 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001676 return main.FALSE
1677 else:
1678 return main.TRUE
1679 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001680 main.log.error( self.name + ": EOF exception found" )
1681 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001682 main.cleanup()
1683 main.exit()
1684
kelvin-onlabd3b64892015-01-20 13:26:24 -08001685 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001686 """
1687 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001688 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001689 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001690 NOTE: this uses a custom mn function
1691 required params:
1692 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001693 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001694 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001695 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001696 response = self.execute(
1697 cmd=command,
1698 prompt="mininet>",
1699 timeout=10 )
1700 if re.search( "no host named", response ):
1701 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001702 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001703 elif re.search( "Error", response ):
1704 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001705 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001706 elif re.search( "usage:", response ):
1707 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001708 return main.FALSE
1709 else:
1710 return main.TRUE
1711 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001712 main.log.error( self.name + ": EOF exception found" )
1713 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001714 main.cleanup()
1715 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001716
Jon Hall7eb38402015-01-08 17:19:54 -08001717 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001718 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001719 Called at the end of the test to stop the mininet and
1720 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001721 """
Jon Halld80cc142015-07-06 13:36:05 -07001722 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001723 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001724 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001725 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001726 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001727 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001728 elif i == 1:
1729 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001730 # print "Disconnecting Mininet"
1731 if self.handle:
1732 self.handle.sendline( "exit" )
1733 self.handle.expect( "exit" )
1734 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001735 else:
1736 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001737 return response
1738
Jon Halld80cc142015-07-06 13:36:05 -07001739 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001740 """
Jon Hall21270ac2015-02-16 17:59:55 -08001741 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001742 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001743 main.FALSE if the pexpect handle does not exist.
1744
Jon Halld61331b2015-02-17 16:35:47 -08001745 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001746 """
Jon Halld61331b2015-02-17 16:35:47 -08001747 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001748 response = ''
1749 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001750 try:
Jon Halld80cc142015-07-06 13:36:05 -07001751 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001752 i = self.handle.expect( [ 'mininet>',
1753 '\$',
1754 pexpect.EOF,
1755 pexpect.TIMEOUT ],
1756 timeout )
1757 if i == 0:
1758 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001759 response = self.execute(
1760 cmd="exit",
1761 prompt="(.*)",
1762 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001763 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001764 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001765 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001766
kelvin-onlab56a3f462015-02-06 14:04:43 -08001767 if i == 1:
1768 main.log.info( " Mininet trying to exit while not " +
1769 "in the mininet prompt" )
1770 elif i == 2:
1771 main.log.error( "Something went wrong exiting mininet" )
1772 elif i == 3: # timeout
1773 main.log.error( "Something went wrong exiting mininet " +
1774 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001775
Hari Krishnab35c6d02015-03-18 11:13:51 -07001776 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001777 self.handle.sendline( "" )
1778 self.handle.expect( '\$' )
1779 self.handle.sendline(
1780 "sudo kill -9 \`ps -ef | grep \"" +
1781 fileName +
1782 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001783 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001784 main.log.error( self.name + ": EOF exception found" )
1785 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001786 main.cleanup()
1787 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001788 else:
1789 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001790 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001791 return response
1792
Jon Halla5cb3412015-08-18 14:08:22 -07001793 def arping( self, srcHost="", dstHost="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001794 """
1795 Description:
1796 Sends arp message from mininet host for hosts discovery
1797 Required:
1798 host - hosts name
1799 Optional:
1800 ip - ip address that does not exist in the network so there would
1801 be no reply.
1802 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001803 if ethDevice:
1804 ethDevice = '-I ' + ethDevice + ' '
Jon Halla5cb3412015-08-18 14:08:22 -07001805 cmd = srcHost + " arping -c1 " + ethDevice + dstHost
admin07529932013-11-22 14:58:28 -08001806 try:
Jon Halla5cb3412015-08-18 14:08:22 -07001807 main.log.info( "Sending: " + cmd )
kelvin-onlab65782a82015-05-07 14:12:13 -07001808 self.handle.sendline( cmd )
Jon Halla5cb3412015-08-18 14:08:22 -07001809 i = self.handle.expect( [ "mininet>", "arping: " ] )
1810 if i == 0:
1811 return main.TRUE
1812 elif i == 1:
1813 response = self.handle.before + self.handle.after
1814 self.handle.expect( "mininet>" )
1815 response += self.handle.before + self.handle.after
1816 main.log.warn( "Error sending arping, output was: " +
1817 response )
1818 return main.FALSE
1819 except pexpect.TIMEOUT:
1820 main.log.error( self.name + ": TIMEOUT exception found" )
1821 main.log.warn( self.handle.before )
1822 return main.FALSE
kelvin-onlab65782a82015-05-07 14:12:13 -07001823 except pexpect.EOF:
1824 main.log.error( self.name + ": EOF exception found" )
1825 main.log.error( self.name + ": " + self.handle.before )
1826 main.cleanup()
1827 main.exit()
admin07529932013-11-22 14:58:28 -08001828
Jon Hall7eb38402015-01-08 17:19:54 -08001829 def decToHex( self, num ):
1830 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001831
Jon Hall7eb38402015-01-08 17:19:54 -08001832 def getSwitchFlowCount( self, switch ):
1833 """
1834 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001835 if self.handle:
1836 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1837 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001838 response = self.execute(
1839 cmd=cmd,
1840 prompt="mininet>",
1841 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001842 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001843 main.log.error( self.name + ": EOF exception found" )
1844 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001845 main.cleanup()
1846 main.exit()
1847 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001848 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001849 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001850 main.log.info(
1851 "Couldn't find flows on switch %s, found: %s" %
1852 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001853 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001854 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001855 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001856 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001857
kelvin-onlabd3b64892015-01-20 13:26:24 -08001858 def checkFlows( self, sw, dumpFormat=None ):
1859 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001860 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001861 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001862 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001863 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001864 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001865 response = self.execute(
1866 cmd=command,
1867 prompt="mininet>",
1868 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001869 return response
1870 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001871 main.log.error( self.name + ": EOF exception found" )
1872 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001873 main.cleanup()
1874 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001875
Jon Hall9043c902015-07-30 14:23:44 -07001876 def getFlowTable( self, protoVersion, sw ):
1877 """
1878 Returns certain fields of an OVS flow table. Will force output to
1879 either OF 1.0 or 1.3 format for consistency.
1880
1881 TODO add option to look at cookies. ignoring them for now
1882
1883 NOTE: Use format to force consistent flow table output across
1884 versions
1885 """
1886 try:
1887 self.handle.sendline( "" )
1888 self.handle.expect( "mininet>" )
1889 command = "sh ovs-ofctl dump-flows " + sw
1890 if protoVersion == 1.0:
1891 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\
1892 " print $1 $3 $6 $7 $8}' | "
1893 elif protoVersion == 1.3:
1894 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\
1895 " print $1 $3 $6 $7}' | "
1896 else:
1897 main.log.error(
1898 "Unknown protoVersion in getFlowTable(). given: (" +
1899 str( type( protoVersion ) ) +
1900 ") '" + str( protoVersion ) + "'" )
1901 return None
1902 command += "cut -d ',' -f 2- | sort -n -k1 -r"
1903 self.handle.sendline( command )
1904 self.handle.expect( "sort" )
1905 self.handle.expect( "OFPST_FLOW" )
1906 response = self.handle.before
1907 return response
1908 except pexpect.EOF:
1909 main.log.error( self.name + ": EOF exception found" )
1910 main.log.error( self.name + ": " + self.handle.before )
1911 main.cleanup()
1912 main.exit()
1913 except pexpect.TIMEOUT:
1914 main.log.exception( self.name + ": Timeout exception: " )
1915 return None
1916
1917 def flowComp( self, flow1, flow2 ):
1918 if flow1 == flow2:
1919 return main.TRUE
1920 else:
1921 main.log.info( "Flow tables do not match, printing tables:" )
1922 main.log.info( "Flow Table 1:" )
1923 main.log.info( flow1 )
1924 main.log.info( "Flow Table 2:" )
1925 main.log.info( flow2 )
1926 return main.FALSE
1927
Charles Chan029be652015-08-24 01:46:10 +08001928 def startTcpdump( self, filename, intf="eth0", port="port 6653" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001929 """
Jon Hallefbd9792015-03-05 16:11:36 -08001930 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001931 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001932 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001933 self.handle.sendline( "" )
1934 self.handle.expect( "mininet>" )
1935 self.handle.sendline(
1936 "sh sudo tcpdump -n -i " +
1937 intf +
1938 " " +
1939 port +
1940 " -w " +
1941 filename.strip() +
1942 " &" )
1943 self.handle.sendline( "" )
1944 i = self.handle.expect( [ 'No\ssuch\device',
1945 'listening\son',
1946 pexpect.TIMEOUT,
1947 "mininet>" ],
1948 timeout=10 )
1949 main.log.warn( self.handle.before + self.handle.after )
1950 self.handle.sendline( "" )
1951 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001952 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001953 main.log.error(
1954 self.name +
1955 ": tcpdump - No such device exists. " +
1956 "tcpdump attempted on: " +
1957 intf )
admin2a9548d2014-06-17 14:08:07 -07001958 return main.FALSE
1959 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001960 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001961 return main.TRUE
1962 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001963 main.log.error(
1964 self.name +
1965 ": tcpdump command timed out! Check interface name," +
1966 " given interface was: " +
1967 intf )
admin2a9548d2014-06-17 14:08:07 -07001968 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001969 elif i == 3:
1970 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001971 return main.TRUE
1972 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001973 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001974 return main.FALSE
1975 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001976 main.log.error( self.name + ": EOF exception found" )
1977 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001978 main.cleanup()
1979 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001980 except Exception:
1981 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001982 main.cleanup()
1983 main.exit()
1984
kelvin-onlabd3b64892015-01-20 13:26:24 -08001985 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001986 """
1987 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001988 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001989 self.handle.sendline( "sh sudo pkill tcpdump" )
1990 self.handle.expect( "mininet>" )
1991 self.handle.sendline( "" )
1992 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001993 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001994 main.log.error( self.name + ": EOF exception found" )
1995 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001996 main.cleanup()
1997 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001998 except Exception:
1999 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07002000 main.cleanup()
2001 main.exit()
2002
Jon Halld80cc142015-07-06 13:36:05 -07002003 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002004 """
2005 Read ports from a Mininet switch.
2006
2007 Returns a json structure containing information about the
2008 ports of the given switch.
2009 """
2010 response = self.getInterfaces( nodeName )
2011 # TODO: Sanity check on response. log if no such switch exists
2012 ports = []
2013 for line in response.split( "\n" ):
2014 if not line.startswith( "name=" ):
2015 continue
2016 portVars = {}
2017 for var in line.split( "," ):
2018 key, value = var.split( "=" )
2019 portVars[ key ] = value
2020 isUp = portVars.pop( 'enabled', "True" )
2021 isUp = "True" in isUp
2022 if verbose:
2023 main.log.info( "Reading switch port %s(%s)" %
2024 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
2025 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002026 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002027 mac = None
2028 ips = []
2029 ip = portVars[ 'ip' ]
2030 if ip == 'None':
2031 ip = None
2032 ips.append( ip )
2033 name = portVars[ 'name' ]
2034 if name == 'None':
2035 name = None
2036 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
2037 if name == 'lo':
2038 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
2039 else:
2040 portNo = re.search( portRe, name ).group( 'port' )
2041 ports.append( { 'of_port': portNo,
2042 'mac': str( mac ).replace( '\'', '' ),
2043 'name': name,
2044 'ips': ips,
2045 'enabled': isUp } )
2046 return ports
2047
Jon Halld80cc142015-07-06 13:36:05 -07002048 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002049 """
2050 Read switches from Mininet.
2051
2052 Returns a dictionary whose keys are the switch names and the value is
2053 a dictionary containing information about the switch.
2054 """
Jon Halla22481b2015-07-28 17:46:01 -07002055 # NOTE: To support new Mininet switch classes, just append the new
2056 # class to the switchClasses variable
Jon Hallafa8a472015-06-12 14:02:42 -07002057
Jon Halla22481b2015-07-28 17:46:01 -07002058 # Regex patterns to parse 'dump' output
2059 # Example Switches:
Jon Hallafa8a472015-06-12 14:02:42 -07002060 # <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 -07002061 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Halla22481b2015-07-28 17:46:01 -07002062 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550>
2063 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830>
2064 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737>
2065 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)"
2066 swRE = r"<(?P<class>" + switchClasses + r")" +\
2067 r"(?P<options>\{.*\})?\s" +\
2068 r"(?P<name>[^:]+)\:\s" +\
2069 r"(?P<ports>([^,]+,)*[^,\s]+)" +\
2070 r"\spid=(?P<pid>(\d)+)"
Jon Hallafa8a472015-06-12 14:02:42 -07002071 # Update mn port info
2072 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07002073 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002074 dump = self.dump().split( "\n" )
2075 for line in dump:
Jon Halla22481b2015-07-28 17:46:01 -07002076 result = re.search( swRE, line, re.I )
2077 if result:
Jon Hallafa8a472015-06-12 14:02:42 -07002078 name = result.group( 'name' )
2079 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
Jon Halla22481b2015-07-28 17:46:01 -07002080 pid = result.group( 'pid' )
2081 swClass = result.group( 'class' )
2082 options = result.group( 'options' )
Jon Hallafa8a472015-06-12 14:02:42 -07002083 if verbose:
2084 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
2085 ports = self.getPorts( name )
Jon Halla22481b2015-07-28 17:46:01 -07002086 output[ name ] = { "dpid": dpid,
2087 "ports": ports,
2088 "swClass": swClass,
2089 "pid": pid,
2090 "options": options }
Jon Hallafa8a472015-06-12 14:02:42 -07002091 return output
2092
Jon Halld80cc142015-07-06 13:36:05 -07002093 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07002094 """
2095 Read hosts from Mininet.
2096
2097 Returns a dictionary whose keys are the host names and the value is
2098 a dictionary containing information about the host.
2099 """
2100 # Regex patterns to parse dump output
2101 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07002102 # <Host h1: pid=12725>
2103 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
2104 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
2105 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07002106 # NOTE: Does not correctly match hosts with multi-links
2107 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
2108 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002109 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07002110 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07002111 # update mn port info
2112 self.update()
2113 # Get mininet dump
2114 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07002115 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07002116 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07002117 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07002118 result = re.search( hostRE, line )
2119 name = result.group( 'name' )
2120 interfaces = []
2121 response = self.getInterfaces( name )
2122 # Populate interface info
2123 for line in response.split( "\n" ):
2124 if line.startswith( "name=" ):
2125 portVars = {}
2126 for var in line.split( "," ):
2127 key, value = var.split( "=" )
2128 portVars[ key ] = value
2129 isUp = portVars.pop( 'enabled', "True" )
2130 isUp = "True" in isUp
2131 if verbose:
2132 main.log.info( "Reading host port %s(%s)" %
2133 ( portVars[ 'name' ],
2134 portVars[ 'mac' ] ) )
2135 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07002136 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07002137 mac = None
2138 ips = []
2139 ip = portVars[ 'ip' ]
2140 if ip == 'None':
2141 ip = None
2142 ips.append( ip )
2143 intfName = portVars[ 'name' ]
2144 if name == 'None':
2145 name = None
2146 interfaces.append( {
2147 "name": intfName,
2148 "ips": ips,
2149 "mac": str( mac ),
2150 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07002151 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07002152 return hosts
2153
2154 def getLinks( self ):
2155 """
2156 Gathers information about current Mininet links. These links may not
2157 be up if one of the ports is down.
2158
2159 Returns a list of dictionaries with link endpoints.
2160
2161 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07002162 { 'node1': str( node1 name )
2163 'node2': str( node2 name )
2164 'port1': str( port1 of_port )
2165 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07002166 Note: The port number returned is the eth#, not necessarily the of_port
2167 number. In Mininet, for OVS switch, these should be the same. For
2168 hosts, this is just the eth#.
2169 """
2170 self.update()
2171 response = self.links().split( '\n' )
2172
2173 # Examples:
2174 # s1-eth3<->s2-eth1 (OK OK)
2175 # s13-eth3<->h27-eth0 (OK OK)
2176 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
2177 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
2178 links = []
2179 for line in response:
2180 match = re.search( linkRE, line )
2181 if match:
2182 node1 = match.group( 'node1' )
2183 node2 = match.group( 'node2' )
2184 port1 = match.group( 'port1' )
2185 port2 = match.group( 'port2' )
2186 links.append( { 'node1': node1,
2187 'node2': node2,
2188 'port1': port1,
2189 'port2': port2 } )
2190 return links
2191
2192 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002193 """
2194 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07002195 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04002196
Jon Hallafa8a472015-06-12 14:02:42 -07002197 Dependencies:
2198 1. numpy - "sudo pip install numpy"
2199 """
2200 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04002201 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08002202 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07002203 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08002204 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002205 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08002206 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08002207 main.log.error(
2208 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07002209 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04002210 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08002211 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08002212 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04002213 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08002214 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002215 onosDPIDs.append(
2216 switch[ 'id' ].replace(
2217 ":",
2218 '' ).replace(
2219 "of",
2220 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04002221 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04002222
Jon Hall7eb38402015-01-08 17:19:54 -08002223 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002224 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002225 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002226 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002227 main.log.error( str( list1 ) )
2228 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08002229 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07002230 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002231 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08002232 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07002233 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04002234
Jon Hall7eb38402015-01-08 17:19:54 -08002235 # FIXME: this does not look for extra ports in ONOS, only checks that
2236 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002237 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002238
Jon Hall7eb38402015-01-08 17:19:54 -08002239 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07002240 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08002241 mnPorts = []
2242 onosPorts = []
2243 switchResult = main.TRUE
2244 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002245 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002246 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002247 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002248 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002249 if onosSwitch[ 'device' ][ 'id' ].replace(
2250 ':',
2251 '' ).replace(
2252 "of",
2253 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002254 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002255 if port[ 'isEnabled' ]:
2256 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08002257 # onosPorts.append( 'local' )
2258 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002259 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002260 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05002261 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08002262 mnPorts.sort( key=float )
2263 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07002264
kelvin-onlabd3b64892015-01-20 13:26:24 -08002265 mnPortsLog = mnPorts
2266 onosPortsLog = onosPorts
2267 mnPorts = [ x for x in mnPorts ]
2268 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05002269
Jon Hall7eb38402015-01-08 17:19:54 -08002270 # TODO: handle other reserved port numbers besides LOCAL
2271 # NOTE: Reserved ports
2272 # Local port: -2 in Openflow, ONOS shows 'local', we store as
2273 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002274 for mnPort in mnPortsLog:
2275 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08002276 # don't set results to true here as this is just one of
2277 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08002278 mnPorts.remove( mnPort )
2279 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07002280
Jon Hall7eb38402015-01-08 17:19:54 -08002281 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05002282 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08002283 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08002284 if 65534 in mnPorts:
2285 mnPorts.remove( 65534 )
2286 if long( uint64( -2 ) ) in onosPorts:
2287 onosPorts.remove( long( uint64( -2 ) ) )
2288 if len( mnPorts ): # the ports of this switch don't match
2289 switchResult = main.FALSE
2290 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
2291 if len( onosPorts ): # the ports of this switch don't match
2292 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08002293 main.log.warn(
2294 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08002295 str( onosPorts ) )
2296 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07002297 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002298 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07002299 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002300 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
2301 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
2302 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07002303 finalResults = finalResults and portsResults
2304 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002305
Jon Hallafa8a472015-06-12 14:02:42 -07002306 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002307 """
2308 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002309 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002310
Jon Hallafa8a472015-06-12 14:02:42 -07002311 """
Jon Hall7eb38402015-01-08 17:19:54 -08002312 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002313 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002314 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002315
Jon Halld80cc142015-07-06 13:36:05 -07002316 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002317 for l in links:
2318 try:
2319 node1 = switches[ l[ 'node1' ] ]
2320 node2 = switches[ l[ 'node2' ] ]
2321 enabled = True
2322 for port in node1[ 'ports' ]:
2323 if port[ 'of_port' ] == l[ 'port1' ]:
2324 enabled = enabled and port[ 'enabled' ]
2325 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002326 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002327 enabled = enabled and port[ 'enabled' ]
2328 if enabled:
2329 mnLinks.append( l )
2330 except KeyError:
2331 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002332 if 2 * len( mnLinks ) == len( onos ):
2333 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002334 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002335 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002336 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002337 "Mininet has " + str( len( mnLinks ) ) +
2338 " bidirectional links and ONOS has " +
2339 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002340
Jon Hall7eb38402015-01-08 17:19:54 -08002341 # iterate through MN links and check if an ONOS link exists in
2342 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002343 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002344 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002345 node1 = None
2346 port1 = None
2347 node2 = None
2348 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002349 firstDir = main.FALSE
2350 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002351 for swName, switch in switches.iteritems():
2352 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002353 node1 = switch[ 'dpid' ]
2354 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002355 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002356 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002357 if node1 is not None and node2 is not None:
2358 break
Jon Hallafa8a472015-06-12 14:02:42 -07002359 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002360 node2 = switch[ 'dpid' ]
2361 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002362 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002363 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002364 if node1 is not None and node2 is not None:
2365 break
2366
kelvin-onlabd3b64892015-01-20 13:26:24 -08002367 for onosLink in onos:
2368 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002369 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002370 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002371 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002372 onosPort1 = onosLink[ 'src' ][ 'port' ]
2373 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002374
Jon Hall72cf1dc2014-10-20 21:04:50 -04002375 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002376 if str( onosNode1 ) == str( node1 ) and str(
2377 onosNode2 ) == str( node2 ):
2378 if int( onosPort1 ) == int( port1 ) and int(
2379 onosPort2 ) == int( port2 ):
2380 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002381 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002382 main.log.warn(
2383 'The port numbers do not match for ' +
2384 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002385 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002386 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002387 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002388 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002389 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002390
2391 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002392 elif ( str( onosNode1 ) == str( node2 ) and
2393 str( onosNode2 ) == str( node1 ) ):
2394 if ( int( onosPort1 ) == int( port2 )
2395 and int( onosPort2 ) == int( port1 ) ):
2396 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002397 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002398 main.log.warn(
2399 'The port numbers do not match for ' +
2400 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002401 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002402 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002403 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002404 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002405 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002406 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002407 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002408 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002409 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002410 'ONOS does not have the link %s/%s -> %s/%s' %
2411 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002412 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002413 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002414 'ONOS does not have the link %s/%s -> %s/%s' %
2415 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002416 linkResults = linkResults and firstDir and secondDir
2417 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002418
Jon Hallafa8a472015-06-12 14:02:42 -07002419 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002420 """
Jon Hallafa8a472015-06-12 14:02:42 -07002421 Compare mn and onos Hosts.
2422 Since Mininet hosts are quiet, ONOS will only know of them when they
2423 speak. For this reason, we will only check that the hosts in ONOS
2424 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002425
Jon Hallafa8a472015-06-12 14:02:42 -07002426 Arguments:
2427 hostsJson: parsed json object from the onos hosts api
2428 Returns:
2429 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002430 import json
2431 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002432 for onosHost in hostsJson:
2433 onosMAC = onosHost[ 'mac' ].lower()
2434 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002435 for mnHost, info in hosts.iteritems():
2436 for mnIntf in info[ 'interfaces' ]:
2437 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002438 match = True
2439 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002440 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002441 pass # all is well
2442 else:
2443 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002444 main.log.error( "ONOS host " +
2445 onosHost[ 'id' ] +
2446 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002447 str( onosHost[ 'ipAddresses' ] ) +
2448 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002449 str( ip ) +
2450 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002451 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002452 onosHost,
2453 sort_keys=True,
2454 indent=4,
2455 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002456 main.log.info( output )
2457 hostResults = main.FALSE
2458 if not match:
2459 hostResults = main.FALSE
2460 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2461 "corresponding Mininet host." )
2462 output = json.dumps( onosHost,
2463 sort_keys=True,
2464 indent=4,
2465 separators=( ',', ': ' ) )
2466 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002467 return hostResults
2468
Jon Hallafa8a472015-06-12 14:02:42 -07002469 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002470 """
2471 Returns a list of all hosts
2472 Don't ask questions just use it"""
2473 self.handle.sendline( "" )
2474 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002475
Jon Hall7eb38402015-01-08 17:19:54 -08002476 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2477 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002478
kelvin-onlabd3b64892015-01-20 13:26:24 -08002479 handlePy = self.handle.before
2480 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2481 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002482
Jon Hall7eb38402015-01-08 17:19:54 -08002483 self.handle.sendline( "" )
2484 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002485
kelvin-onlabd3b64892015-01-20 13:26:24 -08002486 hostStr = handlePy.replace( "]", "" )
2487 hostStr = hostStr.replace( "'", "" )
2488 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002489 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002490 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002491
kelvin-onlabd3b64892015-01-20 13:26:24 -08002492 return hostList
adminbae64d82013-08-01 10:50:15 -07002493
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002494 def getSwitch( self ):
2495 """
2496 Returns a list of all switches
2497 Again, don't ask question just use it...
2498 """
2499 # get host list...
2500 hostList = self.getHosts()
2501 # Make host set
2502 hostSet = set( hostList )
2503
2504 # Getting all the nodes in mininet
2505 self.handle.sendline( "" )
2506 self.handle.expect( "mininet>" )
2507
2508 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2509 self.handle.expect( "mininet>" )
2510
2511 handlePy = self.handle.before
2512 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2513 handlePy = handlePy.rstrip()
2514
2515 self.handle.sendline( "" )
2516 self.handle.expect( "mininet>" )
2517
2518 nodesStr = handlePy.replace( "]", "" )
2519 nodesStr = nodesStr.replace( "'", "" )
2520 nodesStr = nodesStr.replace( "[", "" )
2521 nodesStr = nodesStr.replace( " ", "" )
2522 nodesList = nodesStr.split( "," )
2523
2524 nodesSet = set( nodesList )
2525 # discarding default controller(s) node
2526 nodesSet.discard( 'c0' )
2527 nodesSet.discard( 'c1' )
2528 nodesSet.discard( 'c2' )
2529
2530 switchSet = nodesSet - hostSet
2531 switchList = list( switchSet )
2532
2533 return switchList
2534
Jon Hall7eb38402015-01-08 17:19:54 -08002535 def update( self ):
2536 """
2537 updates the port address and status information for
2538 each port in mn"""
2539 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002540 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002541 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002542 self.handle.sendline( "" )
2543 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002544
Jon Hall7eb38402015-01-08 17:19:54 -08002545 self.handle.sendline( "update" )
2546 self.handle.expect( "update" )
2547 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002548
Jon Hall7eb38402015-01-08 17:19:54 -08002549 self.handle.sendline( "" )
2550 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002551
Jon Hallb1290e82014-11-18 16:17:48 -05002552 return main.TRUE
2553 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002554 main.log.error( self.name + ": EOF exception found" )
2555 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002556 main.cleanup()
2557 main.exit()
2558
Jon Halld80cc142015-07-06 13:36:05 -07002559 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002560 """
2561 Add vlan tag to a host.
2562 Dependencies:
2563 This class depends on the "vlan" package
2564 $ sudo apt-get install vlan
2565 Configuration:
2566 Load the 8021q module into the kernel
2567 $sudo modprobe 8021q
2568
2569 To make this setup permanent:
2570 $ sudo su -c 'echo "8021q" >> /etc/modules'
2571 """
2572 if self.handle:
2573 try:
Jon Halld80cc142015-07-06 13:36:05 -07002574 # get the ip address of the host
2575 main.log.info( "Get the ip address of the host" )
2576 ipaddr = self.getIPAddress( host )
2577 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002578
Jon Halld80cc142015-07-06 13:36:05 -07002579 # remove IP from interface intf
2580 # Ex: h1 ifconfig h1-eth0 inet 0
2581 main.log.info( "Remove IP from interface " )
2582 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2583 self.handle.sendline( cmd2 )
2584 self.handle.expect( "mininet>" )
2585 response = self.handle.before
2586 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002587
Jon Halld80cc142015-07-06 13:36:05 -07002588 # create VLAN interface
2589 # Ex: h1 vconfig add h1-eth0 100
2590 main.log.info( "Create Vlan" )
2591 cmd3 = host + " vconfig add " + intf + " " + vlan
2592 self.handle.sendline( cmd3 )
2593 self.handle.expect( "mininet>" )
2594 response = self.handle.before
2595 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002596
Jon Halld80cc142015-07-06 13:36:05 -07002597 # assign the host's IP to the VLAN interface
2598 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2599 main.log.info( "Assign the host IP to the vlan interface" )
2600 vintf = intf + "." + vlan
2601 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2602 self.handle.sendline( cmd4 )
2603 self.handle.expect( "mininet>" )
2604 response = self.handle.before
2605 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002606
2607 return main.TRUE
2608 except pexpect.EOF:
2609 main.log.error( self.name + ": EOF exception found" )
2610 main.log.error( self.name + ": " + self.handle.before )
2611 return main.FALSE
2612
adminbae64d82013-08-01 10:50:15 -07002613if __name__ != "__main__":
2614 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002615 sys.modules[ __name__ ] = MininetCliDriver()