blob: 27ce3dc613f9e97edb4391f58253a0a28ef249f6 [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 Hall7eb38402015-01-08 17:19:54 -080039sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040040from math import pow
adminbae64d82013-08-01 10:50:15 -070041from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070042
Jon Hall7eb38402015-01-08 17:19:54 -080043
kelvin-onlab50907142015-04-01 13:37:45 -070044class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080045
46 """
47 MininetCliDriver is the basic driver which will handle
48 the Mininet functions"""
49 def __init__( self ):
50 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070051 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080052 self.name = 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 ]
Jon Hallfbc828e2015-01-06 17:30:19 -080063
kelvin-onlaba1484582015-02-02 15:46:20 -080064 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070065
66 try:
67 if os.getenv( str( self.ip_address ) ) != None:
68 self.ip_address = os.getenv( str( self.ip_address ) )
69 else:
70 main.log.info( self.name +
71 ": Trying to connect to " +
72 self.ip_address )
73
74 except KeyError:
75 main.log.info( "Invalid host name," +
76 " connecting to local host instead" )
77 self.ip_address = 'localhost'
78 except Exception as inst:
79 main.log.error( "Uncaught exception: " + str( inst ) )
80
kelvin-onlaba1484582015-02-02 15:46:20 -080081 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070082 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080083 self ).connect(
84 user_name=self.user_name,
85 ip_address=self.ip_address,
86 port=None,
87 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080088
kelvin-onlaba1484582015-02-02 15:46:20 -080089 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080090 main.log.info( "Connection successful to the host " +
91 self.user_name +
92 "@" +
93 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080094 return main.TRUE
95 else:
96 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080097 self.user_name +
98 "@" +
99 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -0800100 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800101 return main.FALSE
102 except pexpect.EOF:
103 main.log.error( self.name + ": EOF exception found" )
104 main.log.error( self.name + ": " + self.handle.before )
105 main.cleanup()
106 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800107 except Exception:
108 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800109 main.cleanup()
110 main.exit()
111
kelvin-onlab10e8d392015-06-03 13:53:45 -0700112 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800113 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700114 Description:
115 Starts Mininet accepts a topology(.py) file and/or an optional
116 argument, to start the mininet, as a parameter.
117 Can also send regular mininet command to load up desired topology.
118 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
119 Options:
120 topoFile = file path for topology file (.py)
121 args = extra option added when starting the topology from the file
122 mnCmd = Mininet command use to start topology
123 Returns:
124 main.TRUE if the mininet starts successfully, main.FALSE
125 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800126 """
Jon Hall7eb38402015-01-08 17:19:54 -0800127 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700128 # make sure old networks are cleaned up
129 main.log.info( self.name +
130 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800131 self.handle.sendline( "sudo mn -c" )
132 i = self.handle.expect( [ 'password\sfor\s',
133 'Cleanup\scomplete',
134 pexpect.EOF,
135 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800136 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800137 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700138 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800139 main.log.info( self.name + ": Sending sudo password" )
140 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800141 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800142 '\$',
143 pexpect.EOF,
144 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800145 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800146 if i == 1:
147 main.log.info( self.name + ": Clean" )
148 elif i == 2:
149 main.log.error( self.name + ": Connection terminated" )
150 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700151 main.log.error( self.name + ": Something while cleaning " +
152 "Mininet took too long... " )
153 # Craft the string to start mininet
154 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700155 if not mnCmd:
156 if topoFile is None or topoFile == '': # If no file is given
157 main.log.info( self.name + ": building fresh Mininet" )
158 cmdString += "mn "
159 if args is None or args == '':
160 # If no args given, use args from .topo file
161 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700162 " " + self.options[ 'arg2' ] +\
163 " --mac --controller " +\
164 self.options[ 'controller' ] + " " +\
165 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700166 else: # else only use given args
167 pass
168 # TODO: allow use of topo args and method args?
169 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700170 main.log.info(
171 "Starting Mininet from topo file " +
172 topoFile )
kelvin-onlab10e8d392015-06-03 13:53:45 -0700173 cmdString += topoFile + " "
174 if args is None:
175 args = ''
176 # TODO: allow use of args from .topo file?
177 cmdString += args
178 else:
179 main.log.info( "Starting Mininet topology using '" + mnCmd +
180 "' command" )
181 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700182 # Send the command and check if network started
183 self.handle.sendline( "" )
184 self.handle.expect( '\$' )
185 main.log.info( "Sending '" + cmdString + "' to " + self.name )
186 self.handle.sendline( cmdString )
187 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800188 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700189 'Exception',
190 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800191 pexpect.EOF,
192 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700193 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800194 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700195 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800196 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800197 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700198 response = str( self.handle.before +
199 self.handle.after )
200 self.handle.expect( '\$' )
201 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700202 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700203 main.log.error(
204 self.name +
205 ": Launching Mininet failed: " + response )
206 return main.FALSE
207 elif i == 2:
208 self.handle.expect( [ "\n",
209 pexpect.EOF,
210 pexpect.TIMEOUT ],
211 timeout )
212 main.log.info( self.handle.before )
213 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800214 main.log.error( self.name + ": Connection timeout" )
215 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700216 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800217 main.log.error(
218 self.name +
219 ": Something took too long... " )
220 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700221 # Why did we hit this part?
222 main.log.error( "startNet did not return correctly" )
223 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800224 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700225 main.log.error( self.name + ": Connection failed to the host " +
226 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800227 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700228 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800229
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800230 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400231 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800232 # In tree topology, if fanout arg is not given, by default it is 2
233 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400234 fanout = 2
235 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500236 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800237 while( k <= depth - 1 ):
238 count = count + pow( fanout, k )
239 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800240 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800241 while( k <= depth - 2 ):
242 # depth-2 gives you only core links and not considering
243 # edge links as seen by ONOS. If all the links including
244 # edge links are required, do depth-1
245 count = count + pow( fanout, k )
246 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800247 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800248 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800249 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800250
Jon Hall7eb38402015-01-08 17:19:54 -0800251 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800252 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800253 # by default it is 1
254 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400255 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800256 numSwitches = depth
257 numHostsPerSw = fanout
258 totalNumHosts = numSwitches * numHostsPerSw
259 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800260 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800261 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800262 topoDict = { "num_switches": int( numSwitches ),
263 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400264 return topoDict
265
kelvin-onlabd3b64892015-01-20 13:26:24 -0800266 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700267 """
268 Calculate the number of switches and links in a topo."""
269 # TODO: combine this function and numSwitchesNlinks
270 argList = self.options[ 'arg1' ].split( "," )
271 topoArgList = argList[ 0 ].split( " " )
272 argList = map( int, argList[ 1: ] )
273 topoArgList = topoArgList[ 1: ] + argList
274
275 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400276 return topoDict
277
Jon Halld80cc142015-07-06 13:36:05 -0700278 def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800279 """
280 Verifies the reachability of the hosts using pingall command.
281 Optional parameter timeout allows you to specify how long to
282 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700283 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700284 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700285 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700286 ping
287 acceptableFailed - Set the number of acceptable failed pings for the
288 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800289 Returns:
290 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700291 otherwise main.FALSE
292 """
293 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700294 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700295 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700296 if self.handle:
297 main.log.info(
298 self.name +
299 ": Checking reachabilty to the hosts using pingall" )
300 response = ""
301 failedPings = 0
302 returnValue = main.TRUE
303 self.handle.sendline( "pingall" )
Jon Hall390696c2015-05-05 17:13:41 -0700304 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700305 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700306 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700307 pexpect.EOF,
308 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700309 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700310 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700311 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700312 response += self.handle.before
313 break
314 elif i == 1:
315 response += self.handle.before + self.handle.after
316 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700317 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700318 returnValue = main.FALSE
319 if shortCircuit:
320 main.log.error( self.name +
321 ": Aborting pingall - "
322 + str( failedPings ) +
323 " pings failed" )
324 break
Jon Hall390696c2015-05-05 17:13:41 -0700325 if ( time.time() - startTime ) > timeout:
326 returnValue = main.FALSE
327 main.log.error( self.name +
328 ": Aborting pingall - " +
329 "Function took too long " )
330 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700331 elif i == 2:
332 main.log.error( self.name +
333 ": EOF exception found" )
334 main.log.error( self.name + ": " +
335 self.handle.before )
336 main.cleanup()
337 main.exit()
338 elif i == 3:
339 response += self.handle.before
340 main.log.error( self.name +
341 ": TIMEOUT exception found" )
342 main.log.error( self.name +
343 ": " +
344 str( response ) )
345 # NOTE: Send ctrl-c to make sure pingall is done
346 self.handle.sendline( "\x03" )
347 self.handle.expect( "Interrupt" )
348 self.handle.expect( "mininet>" )
349 break
350 pattern = "Results\:"
351 main.log.info( "Pingall output: " + str( response ) )
352 if re.search( pattern, response ):
353 main.log.info( self.name + ": Pingall finished with "
354 + str( failedPings ) + " failed pings" )
355 return returnValue
356 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700357 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700358 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700359 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700360 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700361 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700362 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700363 main.log.error( self.name + ": Connection failed to the host" )
364 main.cleanup()
365 main.exit()
366 except pexpect.TIMEOUT:
367 if response:
368 main.log.info( "Pingall output: " + str( response ) )
369 main.log.error( self.name + ": pexpect.TIMEOUT found" )
370 return main.FALSE
371 except pexpect.EOF:
372 main.log.error( self.name + ": EOF exception found" )
373 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500374 main.cleanup()
375 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700376
Jon Hall7eb38402015-01-08 17:19:54 -0800377 def fpingHost( self, **pingParams ):
378 """
379 Uses the fping package for faster pinging...
380 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800381 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800382 command = args[ "SRC" ] + \
383 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
384 self.handle.sendline( command )
385 self.handle.expect(
386 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
387 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
388 response = self.handle.before
389 if re.search( ":\s-", response ):
390 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700391 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800392 elif re.search( ":\s\d{1,2}\.\d\d", response ):
393 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700394 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800395 main.log.info( self.name + ": Install fping on mininet machine... " )
396 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700397 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800398
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400399 def pingallHosts( self, hostList, pingType='ipv4' ):
400 """
kelvin-onlab2ff57022015-05-29 10:48:51 -0700401 Ping all specified hosts with a specific ping type
402
403 Acceptable pingTypes:
404 - 'ipv4'
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400405 - 'ipv6'
kelvin-onlab2ff57022015-05-29 10:48:51 -0700406
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400407 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700408 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700409
410 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400411 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700412
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400413 Returns main.FALSE if one or more of hosts specified
414 cannot reach each other"""
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400415 if pingType == "ipv4":
kelvin-onlab2ff57022015-05-29 10:48:51 -0700416 cmd = " ping -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400417 elif pingType == "ipv6":
418 cmd = " ping6 -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400419 else:
420 main.log.warn( "Invalid pingType specified" )
421 return
422
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
427
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400428 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700429 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400430 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700431 pingList = hostList[ :listIndex ] + \
432 hostList[ ( listIndex + 1 ): ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700433
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400434 for temp in pingList:
435 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700436 pingCmd = str( host ) + cmd + str( temp )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400437 self.handle.sendline( pingCmd )
438 i = self.handle.expect( [ pingCmd, pexpect.TIMEOUT ] )
439 j = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
440 response = self.handle.before
441 if re.search( ',\s0\%\spacket\sloss', response ):
Jon Halld80cc142015-07-06 13:36:05 -0700442 main.log.info( str( host ) + " -> " + str( temp ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400443 else:
Jon Halld80cc142015-07-06 13:36:05 -0700444 main.log.info(
445 str( host ) + " -> X (" + str( temp ) + ") "
446 " Destination Unreachable" )
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400447 # One of the host to host pair is unreachable
448 isReachable = main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400449
kelvin-onlab2ff57022015-05-29 10:48:51 -0700450 return isReachable
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400451
452 except pexpect.EOF:
453 main.log.error( self.name + ": EOF exception found" )
454 main.log.error( self.name + ": " + self.handle.before )
455 main.cleanup()
456 main.exit()
457
Jon Hall7eb38402015-01-08 17:19:54 -0800458 def pingHost( self, **pingParams ):
459 """
460 Ping from one mininet host to another
461 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800462 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800463 command = args[ "SRC" ] + " ping " + \
464 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700465 try:
Jon Hall61282e32015-03-19 11:34:11 -0700466 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800467 self.handle.sendline( command )
468 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700469 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800470 main.log.error(
471 self.name +
472 ": timeout when waiting for response from mininet" )
473 main.log.error( "response: " + str( self.handle.before ) )
474 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700475 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800476 main.log.error(
477 self.name +
478 ": timeout when waiting for response from mininet" )
479 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700480 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800481 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800482 main.log.error( self.name + ": EOF exception found" )
483 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700484 main.cleanup()
485 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800486 main.log.info( self.name + ": Ping Response: " + response )
487 if re.search( ',\s0\%\spacket\sloss', response ):
488 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800489 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700490 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800491 else:
492 main.log.error(
493 self.name +
494 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800495 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700496 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800497
Jon Hall7eb38402015-01-08 17:19:54 -0800498 def checkIP( self, host ):
499 """
500 Verifies the host's ip configured or not."""
501 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700502 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800503 response = self.execute(
504 cmd=host +
505 " ifconfig",
506 prompt="mininet>",
507 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800508 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800509 main.log.error( self.name + ": EOF exception found" )
510 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700511 main.cleanup()
512 main.exit()
adminbae64d82013-08-01 10:50:15 -0700513
Jon Hall7eb38402015-01-08 17:19:54 -0800514 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800515 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
516 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
517 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
518 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
519 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800520 # pattern = "inet addr:10.0.0.6"
521 if re.search( pattern, response ):
522 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700523 return main.TRUE
524 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800525 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700526 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800527 else:
528 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800529
Jon Hall7eb38402015-01-08 17:19:54 -0800530 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800531 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700532 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800533 response = self.execute(
534 cmd="h1 /usr/sbin/sshd -D&",
535 prompt="mininet>",
536 timeout=10 )
537 response = self.execute(
538 cmd="h4 /usr/sbin/sshd -D&",
539 prompt="mininet>",
540 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700541 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800542 vars( self )[ key ] = connectargs[ key ]
543 response = self.execute(
544 cmd="xterm h1 h4 ",
545 prompt="mininet>",
546 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800547 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800548 main.log.error( self.name + ": EOF exception found" )
549 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700550 main.cleanup()
551 main.exit()
adminbae64d82013-08-01 10:50:15 -0700552 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800553 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700554 if self.flag == 0:
555 self.flag = 1
556 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800557 else:
adminbae64d82013-08-01 10:50:15 -0700558 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800559
kelvin-onlaba1484582015-02-02 15:46:20 -0800560 def moveHost( self, host, oldSw, newSw, ):
561 """
562 Moves a host from one switch to another on the fly
563 Note: The intf between host and oldSw when detached
564 using detach(), will still show up in the 'net'
565 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700566 ( which is correct behavior since the interfaces
567 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800568 """
569 if self.handle:
570 try:
571 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700572 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800573 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800574 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800575 response = self.execute( cmd=cmd,
576 prompt="mininet>",
577 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700578
kelvin-onlaba1484582015-02-02 15:46:20 -0800579 # Determine hostintf and Oldswitchintf
580 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800581 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800582 print "cmd2= ", cmd
583 self.handle.sendline( cmd )
584 self.handle.expect( "mininet>" )
585
shahshreya73537862015-02-11 15:15:24 -0800586 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800587 cmd = "px ipaddr = hintf.IP()"
588 print "cmd3= ", cmd
589 self.handle.sendline( cmd )
590 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800591
592 cmd = "px macaddr = hintf.MAC()"
593 print "cmd3= ", cmd
594 self.handle.sendline( cmd )
595 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700596
kelvin-onlaba1484582015-02-02 15:46:20 -0800597 # Detach interface between oldSw-host
598 cmd = "px " + oldSw + ".detach( sintf )"
599 print "cmd4= ", cmd
600 self.handle.sendline( cmd )
601 self.handle.expect( "mininet>" )
602
603 # Add link between host-newSw
604 cmd = "py net.addLink(" + host + "," + newSw + ")"
605 print "cmd5= ", cmd
606 self.handle.sendline( cmd )
607 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700608
kelvin-onlaba1484582015-02-02 15:46:20 -0800609 # Determine hostintf and Newswitchintf
610 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800611 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800612 print "cmd6= ", cmd
613 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700614 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800615
616 # Attach interface between newSw-host
617 cmd = "px " + newSw + ".attach( sintf )"
618 print "cmd3= ", cmd
619 self.handle.sendline( cmd )
620 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700621
kelvin-onlaba1484582015-02-02 15:46:20 -0800622 # Set ipaddress of the host-newSw interface
623 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
624 print "cmd7 = ", cmd
625 self.handle.sendline( cmd )
626 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800627
628 # Set macaddress of the host-newSw interface
629 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
630 print "cmd8 = ", cmd
631 self.handle.sendline( cmd )
632 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700633
kelvin-onlaba1484582015-02-02 15:46:20 -0800634 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800635 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800636 self.handle.sendline( cmd )
637 self.handle.expect( "mininet>" )
638 print "output = ", self.handle.before
639
640 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800641 cmd = host + " ifconfig"
642 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800643 self.handle.sendline( cmd )
644 self.handle.expect( "mininet>" )
645 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700646
kelvin-onlaba1484582015-02-02 15:46:20 -0800647 return main.TRUE
648 except pexpect.EOF:
649 main.log.error( self.name + ": EOF exception found" )
650 main.log.error( self.name + ": " + self.handle.before )
651 return main.FALSE
652
Jon Hall7eb38402015-01-08 17:19:54 -0800653 def changeIP( self, host, intf, newIP, newNetmask ):
654 """
655 Changes the ip address of a host on the fly
656 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800657 if self.handle:
658 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800659 cmd = host + " ifconfig " + intf + " " + \
660 newIP + " " + 'netmask' + " " + newNetmask
661 self.handle.sendline( cmd )
662 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800663 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800664 main.log.info( "response = " + response )
665 main.log.info(
666 "Ip of host " +
667 host +
668 " changed to new IP " +
669 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800670 return main.TRUE
671 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800672 main.log.error( self.name + ": EOF exception found" )
673 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800674 return main.FALSE
675
Jon Hall7eb38402015-01-08 17:19:54 -0800676 def changeDefaultGateway( self, host, newGW ):
677 """
678 Changes the default gateway of a host
679 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800680 if self.handle:
681 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800682 cmd = host + " route add default gw " + newGW
683 self.handle.sendline( cmd )
684 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800685 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800686 main.log.info( "response = " + response )
687 main.log.info(
688 "Default gateway of host " +
689 host +
690 " changed to " +
691 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800692 return main.TRUE
693 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800694 main.log.error( self.name + ": EOF exception found" )
695 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800696 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800697
Jon Hall7eb38402015-01-08 17:19:54 -0800698 def addStaticMACAddress( self, host, GW, macaddr ):
699 """
Jon Hallefbd9792015-03-05 16:11:36 -0800700 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800701 if self.handle:
702 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800703 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
704 cmd = host + " arp -s " + GW + " " + macaddr
705 self.handle.sendline( cmd )
706 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800707 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800708 main.log.info( "response = " + response )
709 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800710 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800711 GW +
712 " changed to " +
713 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800714 return main.TRUE
715 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800716 main.log.error( self.name + ": EOF exception found" )
717 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800718 return main.FALSE
719
Jon Hall7eb38402015-01-08 17:19:54 -0800720 def verifyStaticGWandMAC( self, host ):
721 """
722 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800723 if self.handle:
724 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800725 # h1 arp -an
726 cmd = host + " arp -an "
727 self.handle.sendline( cmd )
728 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800729 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800730 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800731 return main.TRUE
732 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800733 main.log.error( self.name + ": EOF exception found" )
734 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800735 return main.FALSE
736
Jon Hall7eb38402015-01-08 17:19:54 -0800737 def getMacAddress( self, host ):
738 """
739 Verifies the host's ip configured or not."""
740 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700741 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800742 response = self.execute(
743 cmd=host +
744 " ifconfig",
745 prompt="mininet>",
746 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800747 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800748 main.log.error( self.name + ": EOF exception found" )
749 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700750 main.cleanup()
751 main.exit()
adminbae64d82013-08-01 10:50:15 -0700752
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700753 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800754 macAddressSearch = re.search( pattern, response, re.I )
755 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800756 main.log.info(
757 self.name +
758 ": Mac-Address of Host " +
759 host +
760 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800761 macAddress )
762 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700763 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800764 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700765
Jon Hall7eb38402015-01-08 17:19:54 -0800766 def getInterfaceMACAddress( self, host, interface ):
767 """
768 Return the IP address of the interface on the given host"""
769 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700770 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800771 response = self.execute( cmd=host + " ifconfig " + interface,
772 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800773 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800774 main.log.error( self.name + ": EOF exception found" )
775 main.log.error( self.name + ": " + self.handle.before )
776 main.cleanup()
777 main.exit()
778
779 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800780 macAddressSearch = re.search( pattern, response, re.I )
781 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800782 main.log.info( "No mac address found in %s" % response )
783 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800784 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800785 main.log.info(
786 "Mac-Address of " +
787 host +
788 ":" +
789 interface +
790 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800791 macAddress )
792 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800793 else:
794 main.log.error( "Connection failed to the host" )
795
796 def getIPAddress( self, host ):
797 """
798 Verifies the host's ip configured or not."""
799 if self.handle:
800 try:
801 response = self.execute(
802 cmd=host +
803 " ifconfig",
804 prompt="mininet>",
805 timeout=10 )
806 except pexpect.EOF:
807 main.log.error( self.name + ": EOF exception found" )
808 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700809 main.cleanup()
810 main.exit()
adminbae64d82013-08-01 10:50:15 -0700811
812 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800813 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800814 main.log.info(
815 self.name +
816 ": IP-Address of Host " +
817 host +
818 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800819 ipAddressSearch.group( 1 ) )
820 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800821 else:
822 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800823
Jon Hall7eb38402015-01-08 17:19:54 -0800824 def getSwitchDPID( self, switch ):
825 """
826 return the datapath ID of the switch"""
827 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700828 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700829 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800830 response = self.execute(
831 cmd=cmd,
832 prompt="mininet>",
833 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800834 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800835 main.log.error( self.name + ": EOF exception found" )
836 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700837 main.cleanup()
838 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800839 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800840 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700841 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800842 main.log.info(
843 "Couldn't find DPID for switch %s, found: %s" %
844 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700845 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800846 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700847 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800848 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700849
Jon Hall7eb38402015-01-08 17:19:54 -0800850 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700851 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800852 self.handle.sendline( "" )
853 self.expect( "mininet>" )
854 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700855 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800856 response = self.execute(
857 cmd=cmd,
858 prompt="mininet>",
859 timeout=10 )
860 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700861 response = self.handle.before
862 return response
863 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800864 main.log.error( self.name + ": EOF exception found" )
865 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700866 main.cleanup()
867 main.exit()
868
Jon Hall7eb38402015-01-08 17:19:54 -0800869 def getInterfaces( self, node ):
870 """
871 return information dict about interfaces connected to the node"""
872 if self.handle:
873 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800874 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700875 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700876 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800877 response = self.execute(
878 cmd=cmd,
879 prompt="mininet>",
880 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800881 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800882 main.log.error( self.name + ": EOF exception found" )
883 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700884 main.cleanup()
885 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700886 return response
887 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800888 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700889
Jon Hall7eb38402015-01-08 17:19:54 -0800890 def dump( self ):
891 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700892 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800893 response = self.execute(
894 cmd='dump',
895 prompt='mininet>',
896 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800897 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800898 main.log.error( self.name + ": EOF exception found" )
899 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700900 main.cleanup()
901 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700902 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800903
Jon Hall7eb38402015-01-08 17:19:54 -0800904 def intfs( self ):
905 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700906 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800907 response = self.execute(
908 cmd='intfs',
909 prompt='mininet>',
910 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800911 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800912 main.log.error( self.name + ": EOF exception found" )
913 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700914 main.cleanup()
915 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700916 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800917
Jon Hall7eb38402015-01-08 17:19:54 -0800918 def net( self ):
919 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700920 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800921 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800922 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800923 main.log.error( self.name + ": EOF exception found" )
924 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700925 main.cleanup()
926 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700927 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800928
Jon Hallafa8a472015-06-12 14:02:42 -0700929 def links( self ):
930 main.log.info( self.name + ": List network links" )
931 try:
932 response = self.execute( cmd='links', prompt='mininet>',
933 timeout=10 )
934 except pexpect.EOF:
935 main.log.error( self.name + ": EOF exception found" )
936 main.log.error( self.name + ": " + self.handle.before )
937 main.cleanup()
938 main.exit()
939 return response
940
Jon Hall7eb38402015-01-08 17:19:54 -0800941 def iperf( self, host1, host2 ):
942 main.log.info(
943 self.name +
944 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700945 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800946 cmd1 = 'iperf ' + host1 + " " + host2
947 self.handle.sendline( cmd1 )
948 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800949 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800950 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800951 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800952 return main.TRUE
953 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800954 main.log.error( self.name + ": iperf test failed" )
955 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800956 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800957 main.log.error( self.name + ": EOF exception found" )
958 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800959 main.cleanup()
960 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800961
Jon Hall7eb38402015-01-08 17:19:54 -0800962 def iperfudp( self ):
963 main.log.info(
964 self.name +
965 ": Simple iperf TCP test between two " +
966 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700967 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800968 response = self.execute(
969 cmd='iperfudp',
970 prompt='mininet>',
971 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800972 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 )
Jon Hall6094a362014-04-11 14:46:56 -0700975 main.cleanup()
976 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700977 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800978
Jon Hall7eb38402015-01-08 17:19:54 -0800979 def nodes( self ):
980 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700981 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800982 response = self.execute(
983 cmd='nodes',
984 prompt='mininet>',
985 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800986 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800987 main.log.error( self.name + ": EOF exception found" )
988 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700989 main.cleanup()
990 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700991 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800992
Jon Hall7eb38402015-01-08 17:19:54 -0800993 def pingpair( self ):
994 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700995 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800996 response = self.execute(
997 cmd='pingpair',
998 prompt='mininet>',
999 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001000 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001001 main.log.error( self.name + ": EOF exception found" )
1002 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001003 main.cleanup()
1004 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -08001005
Jon Hall7eb38402015-01-08 17:19:54 -08001006 if re.search( ',\s0\%\spacket\sloss', response ):
1007 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001008 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -07001009 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001010 else:
1011 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001012 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -07001013 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001014
Jon Hall7eb38402015-01-08 17:19:54 -08001015 def link( self, **linkargs ):
1016 """
1017 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001018 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001019 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1020 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1021 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1022 main.log.info(
1023 "Bring link between '" +
1024 end1 +
1025 "' and '" +
1026 end2 +
1027 "' '" +
1028 option +
1029 "'" )
1030 command = "link " + \
1031 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001032 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001033 self.handle.sendline( command )
1034 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001035 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001036 main.log.error( self.name + ": EOF exception found" )
1037 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001038 main.cleanup()
1039 main.exit()
adminbae64d82013-08-01 10:50:15 -07001040 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001041
Jon Hall7eb38402015-01-08 17:19:54 -08001042 def yank( self, **yankargs ):
1043 """
1044 yank a mininet switch interface to a host"""
1045 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001046 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001047 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1048 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1049 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001050 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001051 response = self.execute(
1052 cmd=command,
1053 prompt="mininet>",
1054 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001055 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001056 main.log.error( self.name + ": EOF exception found" )
1057 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001058 main.cleanup()
1059 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001060 return main.TRUE
1061
Jon Hall7eb38402015-01-08 17:19:54 -08001062 def plug( self, **plugargs ):
1063 """
1064 plug the yanked mininet switch interface to a switch"""
1065 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001066 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001067 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1068 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1069 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001070 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001071 response = self.execute(
1072 cmd=command,
1073 prompt="mininet>",
1074 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001075 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001076 main.log.error( self.name + ": EOF exception found" )
1077 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001078 main.cleanup()
1079 main.exit()
adminbae64d82013-08-01 10:50:15 -07001080 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001081
Jon Hall7eb38402015-01-08 17:19:54 -08001082 def dpctl( self, **dpctlargs ):
1083 """
1084 Run dpctl command on all switches."""
1085 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001086 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001087 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1088 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1089 command = "dpctl " + cmd + " " + str( cmdargs )
1090 try:
1091 response = self.execute(
1092 cmd=command,
1093 prompt="mininet>",
1094 timeout=10 )
1095 except pexpect.EOF:
1096 main.log.error( self.name + ": EOF exception found" )
1097 main.log.error( self.name + ": " + self.handle.before )
1098 main.cleanup()
1099 main.exit()
1100 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001101
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001103 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001104 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001105 fileInput = path + '/lib/Mininet/INSTALL'
1106 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001107 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001108 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001109 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001110 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001111 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001112 return version
adminbae64d82013-08-01 10:50:15 -07001113
kelvin-onlabd3b64892015-01-20 13:26:24 -08001114 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001115 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001116 Parameters:
1117 sw: The name of an OVS switch. Example "s1"
1118 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001119 The output of the command from the mininet cli
1120 or main.FALSE on timeout"""
1121 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001122 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001123 response = self.execute(
1124 cmd=command,
1125 prompt="mininet>",
1126 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001127 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001128 return response
admin2a9548d2014-06-17 14:08:07 -07001129 else:
1130 return main.FALSE
1131 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001132 main.log.error( self.name + ": EOF exception found" )
1133 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001134 main.cleanup()
1135 main.exit()
adminbae64d82013-08-01 10:50:15 -07001136
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001137 def assignSwController( self, sw, ip, port="6633", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001138 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001139 Description:
1140 Assign switches to the controllers ( for ovs use only )
1141 Required:
1142 sw - Name of the switch. This can be a list or a string.
1143 ip - Ip addresses of controllers. This can be a list or a string.
1144 Optional:
1145 port - ONOS use port 6633, if no list of ports is passed, then
1146 the all the controller will use 6633 as their port number
1147 ptcp - ptcp number, This can be a string or a list that has
1148 the same length as switch. This is optional and not required
1149 when using ovs switches.
1150 NOTE: If switches and ptcp are given in a list type they should have the
1151 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1152 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001153
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001154 Return:
1155 Returns main.TRUE if mininet correctly assigned switches to
1156 controllers, otherwise it will return main.FALSE or an appropriate
1157 exception(s)
1158 """
1159 assignResult = main.TRUE
1160 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001161 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001162 command = "sh ovs-vsctl set-controller "
1163 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001164 try:
1165 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001166 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001167 if isinstance( port, types.StringType ) or \
1168 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001169 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001170 elif isinstance( port, types.ListType ):
1171 main.log.error( self.name + ": Only one controller " +
1172 "assigned and a list of ports has" +
1173 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001174 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001175 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001176 main.log.error( self.name + ": Invalid controller port " +
1177 "number. Please specify correct " +
1178 "controller port" )
1179 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001180
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001181 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001182 if isinstance( port, types.StringType ) or \
1183 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001184 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001185 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1186 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001187 elif isinstance( port, types.ListType ):
1188 if ( len( ip ) != len( port ) ):
1189 main.log.error( self.name + ": Port list = " +
1190 str( len( port ) ) +
1191 "should be the same as controller" +
1192 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001193 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001194 else:
1195 onosIp = ""
1196 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001197 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1198 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001199 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001200 main.log.error( self.name + ": Invalid controller port " +
1201 "number. Please specify correct " +
1202 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001203 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001204 else:
1205 main.log.error( self.name + ": Invalid ip address" )
1206 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001207
1208 if isinstance( sw, types.StringType ):
1209 command += sw + " "
1210 if ptcp:
1211 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001212 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001213 elif isinstance( ptcp, types.ListType ):
1214 main.log.error( self.name + ": Only one switch is " +
1215 "being set and multiple PTCP is " +
1216 "being passed " )
1217 else:
1218 main.log.error( self.name + ": Invalid PTCP" )
1219 ptcp = ""
1220 command += onosIp
1221 commandList.append( command )
1222
1223 elif isinstance( sw, types.ListType ):
1224 if ptcp:
1225 if isinstance( ptcp, types.ListType ):
1226 if len( ptcp ) != len( sw ):
1227 main.log.error( self.name + ": PTCP length = " +
1228 str( len( ptcp ) ) +
1229 " is not the same as switch" +
1230 " length = " +
1231 str( len( sw ) ) )
1232 return main.FALSE
1233 else:
1234 for switch, ptcpNum in zip( sw, ptcp ):
1235 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001236 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001237 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001238 tempCmd += onosIp
1239 commandList.append( tempCmd )
1240 else:
1241 main.log.error( self.name + ": Invalid PTCP" )
1242 return main.FALSE
1243 else:
1244 for switch in sw:
1245 tempCmd = "sh ovs-vsctl set-controller "
1246 tempCmd += switch + " " + onosIp
1247 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001248 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001249 main.log.error( self.name + ": Invalid switch type " )
1250 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001251
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001252 for cmd in commandList:
1253 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001254 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001255 except pexpect.TIMEOUT:
1256 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1257 return main.FALSE
1258 except pexpect.EOF:
1259 main.log.error( self.name + ": EOF exception found" )
1260 main.log.error( self.name + ": " + self.handle.before )
1261 main.cleanup()
1262 main.exit()
1263 return main.TRUE
1264 except Exception:
1265 main.log.exception( self.name + ": Uncaught exception!" )
1266 main.cleanup()
1267 main.exit()
adminbae64d82013-08-01 10:50:15 -07001268
kelvin-onlabd3b64892015-01-20 13:26:24 -08001269 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001270 """
1271 Removes the controller target from sw"""
1272 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001273 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001274 response = self.execute(
1275 cmd=command,
1276 prompt="mininet>",
1277 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001278 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001279 main.log.error( self.name + ": EOF exception found" )
1280 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001281 main.cleanup()
1282 main.exit()
1283 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001284 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001285
kelvin-onlabd3b64892015-01-20 13:26:24 -08001286 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001287 """
Jon Hallb1290e82014-11-18 16:17:48 -05001288 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001289 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001290 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001291 NOTE: cannot currently specify what type of switch
1292 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001293 sw = name of the new switch as a string
1294 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001295 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001296 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001297 """
1298 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001299 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001300 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001301 response = self.execute(
1302 cmd=command,
1303 prompt="mininet>",
1304 timeout=10 )
1305 if re.search( "already exists!", response ):
1306 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001307 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001308 elif re.search( "Error", response ):
1309 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001310 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001311 elif re.search( "usage:", response ):
1312 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001313 return main.FALSE
1314 else:
1315 return main.TRUE
1316 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001317 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001318 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001319 main.cleanup()
1320 main.exit()
1321
kelvin-onlabd3b64892015-01-20 13:26:24 -08001322 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001323 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001324 delete a switch from the mininet topology
1325 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001326 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001327 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001328 sw = name of the switch as a string
1329 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001330 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001331 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001332 response = self.execute(
1333 cmd=command,
1334 prompt="mininet>",
1335 timeout=10 )
1336 if re.search( "no switch named", response ):
1337 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001338 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001339 elif re.search( "Error", response ):
1340 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001341 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001342 elif re.search( "usage:", response ):
1343 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001344 return main.FALSE
1345 else:
1346 return main.TRUE
1347 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001348 main.log.error( self.name + ": EOF exception found" )
1349 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001350 main.cleanup()
1351 main.exit()
1352
kelvin-onlabd3b64892015-01-20 13:26:24 -08001353 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001354 """
1355 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001356 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001357 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001358 NOTE: cannot currently specify what type of link
1359 required params:
1360 node1 = the string node name of the first endpoint of the link
1361 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001362 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001363 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001364 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001365 response = self.execute(
1366 cmd=command,
1367 prompt="mininet>",
1368 timeout=10 )
1369 if re.search( "doesnt exist!", response ):
1370 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001371 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001372 elif re.search( "Error", response ):
1373 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001374 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001375 elif re.search( "usage:", response ):
1376 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001377 return main.FALSE
1378 else:
1379 return main.TRUE
1380 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001381 main.log.error( self.name + ": EOF exception found" )
1382 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001383 main.cleanup()
1384 main.exit()
1385
kelvin-onlabd3b64892015-01-20 13:26:24 -08001386 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001387 """
1388 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001389 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001390 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001391 required params:
1392 node1 = the string node name of the first endpoint of the link
1393 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001394 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001395 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001396 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001397 response = self.execute(
1398 cmd=command,
1399 prompt="mininet>",
1400 timeout=10 )
1401 if re.search( "no node named", response ):
1402 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001403 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001404 elif re.search( "Error", response ):
1405 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001406 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001407 elif re.search( "usage:", response ):
1408 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001409 return main.FALSE
1410 else:
1411 return main.TRUE
1412 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001413 main.log.error( self.name + ": EOF exception found" )
1414 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001415 main.cleanup()
1416 main.exit()
1417
kelvin-onlabd3b64892015-01-20 13:26:24 -08001418 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001419 """
Jon Hallb1290e82014-11-18 16:17:48 -05001420 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001421 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001422 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001423 NOTE: cannot currently specify what type of host
1424 required params:
1425 hostname = the string hostname
1426 optional key-value params
1427 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001428 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001429 """
1430 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001431 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001432 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001433 response = self.execute(
1434 cmd=command,
1435 prompt="mininet>",
1436 timeout=10 )
1437 if re.search( "already exists!", response ):
1438 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001439 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001440 elif re.search( "doesnt exists!", response ):
1441 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001442 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001443 elif re.search( "Error", response ):
1444 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001445 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001446 elif re.search( "usage:", response ):
1447 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001448 return main.FALSE
1449 else:
1450 return main.TRUE
1451 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001452 main.log.error( self.name + ": EOF exception found" )
1453 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001454 main.cleanup()
1455 main.exit()
1456
kelvin-onlabd3b64892015-01-20 13:26:24 -08001457 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001458 """
1459 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001460 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001461 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001462 NOTE: this uses a custom mn function
1463 required params:
1464 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001465 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001466 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001467 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001468 response = self.execute(
1469 cmd=command,
1470 prompt="mininet>",
1471 timeout=10 )
1472 if re.search( "no host named", response ):
1473 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001474 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001475 elif re.search( "Error", response ):
1476 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001477 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001478 elif re.search( "usage:", response ):
1479 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001480 return main.FALSE
1481 else:
1482 return main.TRUE
1483 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001484 main.log.error( self.name + ": EOF exception found" )
1485 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001486 main.cleanup()
1487 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001488
Jon Hall7eb38402015-01-08 17:19:54 -08001489 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001490 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001491 Called at the end of the test to stop the mininet and
1492 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001493 """
Jon Halld80cc142015-07-06 13:36:05 -07001494 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001495 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001496 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001497 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001498 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001499 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001500 elif i == 1:
1501 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001502 # print "Disconnecting Mininet"
1503 if self.handle:
1504 self.handle.sendline( "exit" )
1505 self.handle.expect( "exit" )
1506 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001507 else:
1508 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001509 return response
1510
Jon Halld80cc142015-07-06 13:36:05 -07001511 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001512 """
Jon Hall21270ac2015-02-16 17:59:55 -08001513 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001514 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001515 main.FALSE if the pexpect handle does not exist.
1516
Jon Halld61331b2015-02-17 16:35:47 -08001517 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001518 """
Jon Halld61331b2015-02-17 16:35:47 -08001519 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001520 response = ''
1521 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001522 try:
Jon Halld80cc142015-07-06 13:36:05 -07001523 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001524 i = self.handle.expect( [ 'mininet>',
1525 '\$',
1526 pexpect.EOF,
1527 pexpect.TIMEOUT ],
1528 timeout )
1529 if i == 0:
1530 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001531 response = self.execute(
1532 cmd="exit",
1533 prompt="(.*)",
1534 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001535 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001536 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001537 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001538
kelvin-onlab56a3f462015-02-06 14:04:43 -08001539 if i == 1:
1540 main.log.info( " Mininet trying to exit while not " +
1541 "in the mininet prompt" )
1542 elif i == 2:
1543 main.log.error( "Something went wrong exiting mininet" )
1544 elif i == 3: # timeout
1545 main.log.error( "Something went wrong exiting mininet " +
1546 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001547
Hari Krishnab35c6d02015-03-18 11:13:51 -07001548 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001549 self.handle.sendline( "" )
1550 self.handle.expect( '\$' )
1551 self.handle.sendline(
1552 "sudo kill -9 \`ps -ef | grep \"" +
1553 fileName +
1554 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001555 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001556 main.log.error( self.name + ": EOF exception found" )
1557 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001558 main.cleanup()
1559 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001560 else:
1561 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001562 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001563 return response
1564
kelvin-onlabf0594d72015-05-19 17:25:12 -07001565 def arping( self, host="", ip="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001566 """
1567 Description:
1568 Sends arp message from mininet host for hosts discovery
1569 Required:
1570 host - hosts name
1571 Optional:
1572 ip - ip address that does not exist in the network so there would
1573 be no reply.
1574 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001575 if ethDevice:
1576 ethDevice = '-I ' + ethDevice + ' '
Jon Halld80cc142015-07-06 13:36:05 -07001577 cmd = " py " + host + ".cmd(\"arping -c 1 " + ethDevice + ip + "\")"
admin07529932013-11-22 14:58:28 -08001578 try:
kelvin-onlab65782a82015-05-07 14:12:13 -07001579 main.log.warn( "Sending: " + cmd )
1580 self.handle.sendline( cmd )
1581 response = self.handle.before
1582 self.handle.sendline( "" )
1583 self.handle.expect( "mininet>" )
admin07529932013-11-22 14:58:28 -08001584 return main.TRUE
kelvin-onlab65782a82015-05-07 14:12:13 -07001585
1586 except pexpect.EOF:
1587 main.log.error( self.name + ": EOF exception found" )
1588 main.log.error( self.name + ": " + self.handle.before )
1589 main.cleanup()
1590 main.exit()
admin07529932013-11-22 14:58:28 -08001591
Jon Hall7eb38402015-01-08 17:19:54 -08001592 def decToHex( self, num ):
1593 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001594
Jon Hall7eb38402015-01-08 17:19:54 -08001595 def getSwitchFlowCount( self, switch ):
1596 """
1597 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001598 if self.handle:
1599 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1600 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001601 response = self.execute(
1602 cmd=cmd,
1603 prompt="mininet>",
1604 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001605 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001606 main.log.error( self.name + ": EOF exception found" )
1607 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001608 main.cleanup()
1609 main.exit()
1610 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001611 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001612 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001613 main.log.info(
1614 "Couldn't find flows on switch %s, found: %s" %
1615 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001616 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001617 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001618 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001619 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001620
kelvin-onlabd3b64892015-01-20 13:26:24 -08001621 def checkFlows( self, sw, dumpFormat=None ):
1622 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001623 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001624 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001625 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001626 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001627 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001628 response = self.execute(
1629 cmd=command,
1630 prompt="mininet>",
1631 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001632 return response
1633 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001634 main.log.error( self.name + ": EOF exception found" )
1635 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001636 main.cleanup()
1637 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001638
kelvin-onlabd3b64892015-01-20 13:26:24 -08001639 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001640 """
Jon Hallefbd9792015-03-05 16:11:36 -08001641 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001642 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001643 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001644 self.handle.sendline( "" )
1645 self.handle.expect( "mininet>" )
1646 self.handle.sendline(
1647 "sh sudo tcpdump -n -i " +
1648 intf +
1649 " " +
1650 port +
1651 " -w " +
1652 filename.strip() +
1653 " &" )
1654 self.handle.sendline( "" )
1655 i = self.handle.expect( [ 'No\ssuch\device',
1656 'listening\son',
1657 pexpect.TIMEOUT,
1658 "mininet>" ],
1659 timeout=10 )
1660 main.log.warn( self.handle.before + self.handle.after )
1661 self.handle.sendline( "" )
1662 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001663 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001664 main.log.error(
1665 self.name +
1666 ": tcpdump - No such device exists. " +
1667 "tcpdump attempted on: " +
1668 intf )
admin2a9548d2014-06-17 14:08:07 -07001669 return main.FALSE
1670 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001671 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001672 return main.TRUE
1673 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001674 main.log.error(
1675 self.name +
1676 ": tcpdump command timed out! Check interface name," +
1677 " given interface was: " +
1678 intf )
admin2a9548d2014-06-17 14:08:07 -07001679 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001680 elif i == 3:
1681 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001682 return main.TRUE
1683 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001684 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001685 return main.FALSE
1686 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001687 main.log.error( self.name + ": EOF exception found" )
1688 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001689 main.cleanup()
1690 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001691 except Exception:
1692 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001693 main.cleanup()
1694 main.exit()
1695
kelvin-onlabd3b64892015-01-20 13:26:24 -08001696 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001697 """
1698 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001699 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001700 self.handle.sendline( "sh sudo pkill tcpdump" )
1701 self.handle.expect( "mininet>" )
1702 self.handle.sendline( "" )
1703 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001704 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001705 main.log.error( self.name + ": EOF exception found" )
1706 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001707 main.cleanup()
1708 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001709 except Exception:
1710 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001711 main.cleanup()
1712 main.exit()
1713
Jon Halld80cc142015-07-06 13:36:05 -07001714 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001715 """
1716 Read ports from a Mininet switch.
1717
1718 Returns a json structure containing information about the
1719 ports of the given switch.
1720 """
1721 response = self.getInterfaces( nodeName )
1722 # TODO: Sanity check on response. log if no such switch exists
1723 ports = []
1724 for line in response.split( "\n" ):
1725 if not line.startswith( "name=" ):
1726 continue
1727 portVars = {}
1728 for var in line.split( "," ):
1729 key, value = var.split( "=" )
1730 portVars[ key ] = value
1731 isUp = portVars.pop( 'enabled', "True" )
1732 isUp = "True" in isUp
1733 if verbose:
1734 main.log.info( "Reading switch port %s(%s)" %
1735 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1736 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001737 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001738 mac = None
1739 ips = []
1740 ip = portVars[ 'ip' ]
1741 if ip == 'None':
1742 ip = None
1743 ips.append( ip )
1744 name = portVars[ 'name' ]
1745 if name == 'None':
1746 name = None
1747 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
1748 if name == 'lo':
1749 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
1750 else:
1751 portNo = re.search( portRe, name ).group( 'port' )
1752 ports.append( { 'of_port': portNo,
1753 'mac': str( mac ).replace( '\'', '' ),
1754 'name': name,
1755 'ips': ips,
1756 'enabled': isUp } )
1757 return ports
1758
Jon Halld80cc142015-07-06 13:36:05 -07001759 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001760 """
1761 Read switches from Mininet.
1762
1763 Returns a dictionary whose keys are the switch names and the value is
1764 a dictionary containing information about the switch.
1765 """
1766 # FIXME: This currently only works with OVS Switches
1767
1768 # Regex patterns to parse dump output
1769 # Example Switch:
1770 # <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 -07001771 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Hallafa8a472015-06-12 14:02:42 -07001772 swRE = r"<OVSSwitch(\{.*\})?\s(?P<name>[^:]+)\:\s" +\
1773 "(?P<ports>([^,]+,)*[^,\s]+)"
1774 # Update mn port info
1775 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07001776 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001777 dump = self.dump().split( "\n" )
1778 for line in dump:
1779 if line.startswith( "<OVSSwitch" ):
1780 result = re.search( swRE, line, re.I )
1781 name = result.group( 'name' )
1782 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
1783 if verbose:
1784 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
1785 ports = self.getPorts( name )
1786 output[ name ] = { "dpid": dpid, "ports": ports }
1787 return output
1788
Jon Halld80cc142015-07-06 13:36:05 -07001789 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001790 """
1791 Read hosts from Mininet.
1792
1793 Returns a dictionary whose keys are the host names and the value is
1794 a dictionary containing information about the host.
1795 """
1796 # Regex patterns to parse dump output
1797 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
kelvin-onlab299ab062015-07-15 10:58:27 -07001798 # <Host h1: pid=12725>
1799 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186>
1800 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200>
1801 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198>
Jon Hallafa8a472015-06-12 14:02:42 -07001802 # NOTE: Does not correctly match hosts with multi-links
1803 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
1804 # FIXME: Fix that
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001805 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07001806 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07001807 # update mn port info
1808 self.update()
1809 # Get mininet dump
1810 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07001811 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001812 for line in dump:
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001813 if "Host" in line :
Jon Hallafa8a472015-06-12 14:02:42 -07001814 result = re.search( hostRE, line )
1815 name = result.group( 'name' )
1816 interfaces = []
1817 response = self.getInterfaces( name )
1818 # Populate interface info
1819 for line in response.split( "\n" ):
1820 if line.startswith( "name=" ):
1821 portVars = {}
1822 for var in line.split( "," ):
1823 key, value = var.split( "=" )
1824 portVars[ key ] = value
1825 isUp = portVars.pop( 'enabled', "True" )
1826 isUp = "True" in isUp
1827 if verbose:
1828 main.log.info( "Reading host port %s(%s)" %
1829 ( portVars[ 'name' ],
1830 portVars[ 'mac' ] ) )
1831 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001832 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001833 mac = None
1834 ips = []
1835 ip = portVars[ 'ip' ]
1836 if ip == 'None':
1837 ip = None
1838 ips.append( ip )
1839 intfName = portVars[ 'name' ]
1840 if name == 'None':
1841 name = None
1842 interfaces.append( {
1843 "name": intfName,
1844 "ips": ips,
1845 "mac": str( mac ),
1846 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07001847 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07001848 return hosts
1849
1850 def getLinks( self ):
1851 """
1852 Gathers information about current Mininet links. These links may not
1853 be up if one of the ports is down.
1854
1855 Returns a list of dictionaries with link endpoints.
1856
1857 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07001858 { 'node1': str( node1 name )
1859 'node2': str( node2 name )
1860 'port1': str( port1 of_port )
1861 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07001862 Note: The port number returned is the eth#, not necessarily the of_port
1863 number. In Mininet, for OVS switch, these should be the same. For
1864 hosts, this is just the eth#.
1865 """
1866 self.update()
1867 response = self.links().split( '\n' )
1868
1869 # Examples:
1870 # s1-eth3<->s2-eth1 (OK OK)
1871 # s13-eth3<->h27-eth0 (OK OK)
1872 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
1873 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
1874 links = []
1875 for line in response:
1876 match = re.search( linkRE, line )
1877 if match:
1878 node1 = match.group( 'node1' )
1879 node2 = match.group( 'node2' )
1880 port1 = match.group( 'port1' )
1881 port2 = match.group( 'port2' )
1882 links.append( { 'node1': node1,
1883 'node2': node2,
1884 'port1': port1,
1885 'port2': port2 } )
1886 return links
1887
1888 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001889 """
1890 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07001891 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001892
Jon Hallafa8a472015-06-12 14:02:42 -07001893 Dependencies:
1894 1. numpy - "sudo pip install numpy"
1895 """
1896 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04001897 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001898 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07001899 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08001900 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001901 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08001902 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001903 main.log.error(
1904 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07001905 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001906 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001907 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001908 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001909 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001910 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07001911 onosDPIDs.append(
1912 switch[ 'id' ].replace(
1913 ":",
1914 '' ).replace(
1915 "of",
1916 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001917 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04001918
Jon Hall7eb38402015-01-08 17:19:54 -08001919 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001920 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07001921 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001922 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001923 main.log.error( str( list1 ) )
1924 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001925 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001926 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001927 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001928 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001929 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001930
Jon Hall7eb38402015-01-08 17:19:54 -08001931 # FIXME: this does not look for extra ports in ONOS, only checks that
1932 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08001933 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001934
Jon Hall7eb38402015-01-08 17:19:54 -08001935 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07001936 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08001937 mnPorts = []
1938 onosPorts = []
1939 switchResult = main.TRUE
1940 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001941 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07001942 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001943 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001944 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07001945 if onosSwitch[ 'device' ][ 'id' ].replace(
1946 ':',
1947 '' ).replace(
1948 "of",
1949 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001950 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001951 if port[ 'isEnabled' ]:
1952 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001953 # onosPorts.append( 'local' )
1954 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001955 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001956 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001957 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001958 mnPorts.sort( key=float )
1959 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07001960
kelvin-onlabd3b64892015-01-20 13:26:24 -08001961 mnPortsLog = mnPorts
1962 onosPortsLog = onosPorts
1963 mnPorts = [ x for x in mnPorts ]
1964 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001965
Jon Hall7eb38402015-01-08 17:19:54 -08001966 # TODO: handle other reserved port numbers besides LOCAL
1967 # NOTE: Reserved ports
1968 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1969 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001970 for mnPort in mnPortsLog:
1971 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001972 # don't set results to true here as this is just one of
1973 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001974 mnPorts.remove( mnPort )
1975 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07001976
Jon Hall7eb38402015-01-08 17:19:54 -08001977 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001978 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001979 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001980 if 65534 in mnPorts:
1981 mnPorts.remove( 65534 )
1982 if long( uint64( -2 ) ) in onosPorts:
1983 onosPorts.remove( long( uint64( -2 ) ) )
1984 if len( mnPorts ): # the ports of this switch don't match
1985 switchResult = main.FALSE
1986 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1987 if len( onosPorts ): # the ports of this switch don't match
1988 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001989 main.log.warn(
1990 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001991 str( onosPorts ) )
1992 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07001993 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08001994 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07001995 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001996 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1997 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1998 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07001999 finalResults = finalResults and portsResults
2000 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002001
Jon Hallafa8a472015-06-12 14:02:42 -07002002 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08002003 """
2004 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08002005 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04002006
Jon Hallafa8a472015-06-12 14:02:42 -07002007 """
Jon Hall7eb38402015-01-08 17:19:54 -08002008 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08002009 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08002010 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04002011
Jon Halld80cc142015-07-06 13:36:05 -07002012 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07002013 for l in links:
2014 try:
2015 node1 = switches[ l[ 'node1' ] ]
2016 node2 = switches[ l[ 'node2' ] ]
2017 enabled = True
2018 for port in node1[ 'ports' ]:
2019 if port[ 'of_port' ] == l[ 'port1' ]:
2020 enabled = enabled and port[ 'enabled' ]
2021 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002022 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002023 enabled = enabled and port[ 'enabled' ]
2024 if enabled:
2025 mnLinks.append( l )
2026 except KeyError:
2027 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002028 if 2 * len( mnLinks ) == len( onos ):
2029 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002030 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002031 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002032 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002033 "Mininet has " + str( len( mnLinks ) ) +
2034 " bidirectional links and ONOS has " +
2035 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002036
Jon Hall7eb38402015-01-08 17:19:54 -08002037 # iterate through MN links and check if an ONOS link exists in
2038 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002039 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002040 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002041 node1 = None
2042 port1 = None
2043 node2 = None
2044 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002045 firstDir = main.FALSE
2046 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002047 for swName, switch in switches.iteritems():
2048 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002049 node1 = switch[ 'dpid' ]
2050 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002051 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002052 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002053 if node1 is not None and node2 is not None:
2054 break
Jon Hallafa8a472015-06-12 14:02:42 -07002055 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002056 node2 = switch[ 'dpid' ]
2057 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002058 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002059 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002060 if node1 is not None and node2 is not None:
2061 break
2062
kelvin-onlabd3b64892015-01-20 13:26:24 -08002063 for onosLink in onos:
2064 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002065 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002066 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002067 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002068 onosPort1 = onosLink[ 'src' ][ 'port' ]
2069 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002070
Jon Hall72cf1dc2014-10-20 21:04:50 -04002071 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002072 if str( onosNode1 ) == str( node1 ) and str(
2073 onosNode2 ) == str( node2 ):
2074 if int( onosPort1 ) == int( port1 ) and int(
2075 onosPort2 ) == int( port2 ):
2076 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002077 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002078 main.log.warn(
2079 'The port numbers do not match for ' +
2080 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002081 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002082 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002083 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002084 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002085 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002086
2087 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002088 elif ( str( onosNode1 ) == str( node2 ) and
2089 str( onosNode2 ) == str( node1 ) ):
2090 if ( int( onosPort1 ) == int( port2 )
2091 and int( onosPort2 ) == int( port1 ) ):
2092 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002093 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002094 main.log.warn(
2095 'The port numbers do not match for ' +
2096 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002097 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002098 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002099 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002100 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002101 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002102 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002103 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002104 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002105 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002106 'ONOS does not have the link %s/%s -> %s/%s' %
2107 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002108 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002109 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002110 'ONOS does not have the link %s/%s -> %s/%s' %
2111 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002112 linkResults = linkResults and firstDir and secondDir
2113 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002114
Jon Hallafa8a472015-06-12 14:02:42 -07002115 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002116 """
Jon Hallafa8a472015-06-12 14:02:42 -07002117 Compare mn and onos Hosts.
2118 Since Mininet hosts are quiet, ONOS will only know of them when they
2119 speak. For this reason, we will only check that the hosts in ONOS
2120 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002121
Jon Hallafa8a472015-06-12 14:02:42 -07002122 Arguments:
2123 hostsJson: parsed json object from the onos hosts api
2124 Returns:
2125 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002126 import json
2127 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002128 for onosHost in hostsJson:
2129 onosMAC = onosHost[ 'mac' ].lower()
2130 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002131 for mnHost, info in hosts.iteritems():
2132 for mnIntf in info[ 'interfaces' ]:
2133 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002134 match = True
2135 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002136 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002137 pass # all is well
2138 else:
2139 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002140 main.log.error( "ONOS host " +
2141 onosHost[ 'id' ] +
2142 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002143 str( onosHost[ 'ipAddresses' ] ) +
2144 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002145 str( ip ) +
2146 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002147 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002148 onosHost,
2149 sort_keys=True,
2150 indent=4,
2151 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002152 main.log.info( output )
2153 hostResults = main.FALSE
2154 if not match:
2155 hostResults = main.FALSE
2156 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2157 "corresponding Mininet host." )
2158 output = json.dumps( onosHost,
2159 sort_keys=True,
2160 indent=4,
2161 separators=( ',', ': ' ) )
2162 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002163 return hostResults
2164
Jon Hallafa8a472015-06-12 14:02:42 -07002165 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002166 """
2167 Returns a list of all hosts
2168 Don't ask questions just use it"""
2169 self.handle.sendline( "" )
2170 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002171
Jon Hall7eb38402015-01-08 17:19:54 -08002172 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2173 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002174
kelvin-onlabd3b64892015-01-20 13:26:24 -08002175 handlePy = self.handle.before
2176 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2177 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002178
Jon Hall7eb38402015-01-08 17:19:54 -08002179 self.handle.sendline( "" )
2180 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002181
kelvin-onlabd3b64892015-01-20 13:26:24 -08002182 hostStr = handlePy.replace( "]", "" )
2183 hostStr = hostStr.replace( "'", "" )
2184 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002185 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002186 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002187
kelvin-onlabd3b64892015-01-20 13:26:24 -08002188 return hostList
adminbae64d82013-08-01 10:50:15 -07002189
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002190 def getSwitch( self ):
2191 """
2192 Returns a list of all switches
2193 Again, don't ask question just use it...
2194 """
2195 # get host list...
2196 hostList = self.getHosts()
2197 # Make host set
2198 hostSet = set( hostList )
2199
2200 # Getting all the nodes in mininet
2201 self.handle.sendline( "" )
2202 self.handle.expect( "mininet>" )
2203
2204 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2205 self.handle.expect( "mininet>" )
2206
2207 handlePy = self.handle.before
2208 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2209 handlePy = handlePy.rstrip()
2210
2211 self.handle.sendline( "" )
2212 self.handle.expect( "mininet>" )
2213
2214 nodesStr = handlePy.replace( "]", "" )
2215 nodesStr = nodesStr.replace( "'", "" )
2216 nodesStr = nodesStr.replace( "[", "" )
2217 nodesStr = nodesStr.replace( " ", "" )
2218 nodesList = nodesStr.split( "," )
2219
2220 nodesSet = set( nodesList )
2221 # discarding default controller(s) node
2222 nodesSet.discard( 'c0' )
2223 nodesSet.discard( 'c1' )
2224 nodesSet.discard( 'c2' )
2225
2226 switchSet = nodesSet - hostSet
2227 switchList = list( switchSet )
2228
2229 return switchList
2230
Jon Hall7eb38402015-01-08 17:19:54 -08002231 def update( self ):
2232 """
2233 updates the port address and status information for
2234 each port in mn"""
2235 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002236 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002237 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002238 self.handle.sendline( "" )
2239 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002240
Jon Hall7eb38402015-01-08 17:19:54 -08002241 self.handle.sendline( "update" )
2242 self.handle.expect( "update" )
2243 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002244
Jon Hall7eb38402015-01-08 17:19:54 -08002245 self.handle.sendline( "" )
2246 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002247
Jon Hallb1290e82014-11-18 16:17:48 -05002248 return main.TRUE
2249 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002250 main.log.error( self.name + ": EOF exception found" )
2251 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002252 main.cleanup()
2253 main.exit()
2254
Jon Halld80cc142015-07-06 13:36:05 -07002255 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002256 """
2257 Add vlan tag to a host.
2258 Dependencies:
2259 This class depends on the "vlan" package
2260 $ sudo apt-get install vlan
2261 Configuration:
2262 Load the 8021q module into the kernel
2263 $sudo modprobe 8021q
2264
2265 To make this setup permanent:
2266 $ sudo su -c 'echo "8021q" >> /etc/modules'
2267 """
2268 if self.handle:
2269 try:
Jon Halld80cc142015-07-06 13:36:05 -07002270 # get the ip address of the host
2271 main.log.info( "Get the ip address of the host" )
2272 ipaddr = self.getIPAddress( host )
2273 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002274
Jon Halld80cc142015-07-06 13:36:05 -07002275 # remove IP from interface intf
2276 # Ex: h1 ifconfig h1-eth0 inet 0
2277 main.log.info( "Remove IP from interface " )
2278 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2279 self.handle.sendline( cmd2 )
2280 self.handle.expect( "mininet>" )
2281 response = self.handle.before
2282 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002283
Jon Halld80cc142015-07-06 13:36:05 -07002284 # create VLAN interface
2285 # Ex: h1 vconfig add h1-eth0 100
2286 main.log.info( "Create Vlan" )
2287 cmd3 = host + " vconfig add " + intf + " " + vlan
2288 self.handle.sendline( cmd3 )
2289 self.handle.expect( "mininet>" )
2290 response = self.handle.before
2291 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002292
Jon Halld80cc142015-07-06 13:36:05 -07002293 # assign the host's IP to the VLAN interface
2294 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2295 main.log.info( "Assign the host IP to the vlan interface" )
2296 vintf = intf + "." + vlan
2297 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2298 self.handle.sendline( cmd4 )
2299 self.handle.expect( "mininet>" )
2300 response = self.handle.before
2301 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002302
2303 return main.TRUE
2304 except pexpect.EOF:
2305 main.log.error( self.name + ": EOF exception found" )
2306 main.log.error( self.name + ": " + self.handle.before )
2307 return main.FALSE
2308
adminbae64d82013-08-01 10:50:15 -07002309if __name__ != "__main__":
2310 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002311 sys.modules[ __name__ ] = MininetCliDriver()