blob: bdc93078e31ca9a5750b1b64910bcd30b988a0ae [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
Jon Hall7eb38402015-01-08 17:19:54 -080038sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040039from math import pow
adminbae64d82013-08-01 10:50:15 -070040from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070041
Jon Hall7eb38402015-01-08 17:19:54 -080042
kelvin-onlab50907142015-04-01 13:37:45 -070043class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080044
45 """
46 MininetCliDriver is the basic driver which will handle
47 the Mininet functions"""
48 def __init__( self ):
49 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070050 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080051 self.name = None
Jon Hall7eb38402015-01-08 17:19:54 -080052 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070053 self.flag = 0
54
Jon Hall7eb38402015-01-08 17:19:54 -080055 def connect( self, **connectargs ):
56 """
57 Here the main is the TestON instance after creating
58 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080059 try:
60 for key in connectargs:
61 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080062
kelvin-onlaba1484582015-02-02 15:46:20 -080063 self.name = self.options[ 'name' ]
64 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070065 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080066 self ).connect(
67 user_name=self.user_name,
68 ip_address=self.ip_address,
69 port=None,
70 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080071
kelvin-onlaba1484582015-02-02 15:46:20 -080072 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080073 main.log.info( "Connection successful to the host " +
74 self.user_name +
75 "@" +
76 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080077 return main.TRUE
78 else:
79 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080080 self.user_name +
81 "@" +
82 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -080083 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -080084 return main.FALSE
85 except pexpect.EOF:
86 main.log.error( self.name + ": EOF exception found" )
87 main.log.error( self.name + ": " + self.handle.before )
88 main.cleanup()
89 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -080090 except Exception:
91 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -080092 main.cleanup()
93 main.exit()
94
kelvin-onlab10e8d392015-06-03 13:53:45 -070095 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -080096 """
kelvin-onlabf512e942015-06-08 19:42:59 -070097 Description:
98 Starts Mininet accepts a topology(.py) file and/or an optional
99 argument, to start the mininet, as a parameter.
100 Can also send regular mininet command to load up desired topology.
101 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
102 Options:
103 topoFile = file path for topology file (.py)
104 args = extra option added when starting the topology from the file
105 mnCmd = Mininet command use to start topology
106 Returns:
107 main.TRUE if the mininet starts successfully, main.FALSE
108 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800109 """
Jon Hall7eb38402015-01-08 17:19:54 -0800110 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700111 # make sure old networks are cleaned up
112 main.log.info( self.name +
113 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800114 self.handle.sendline( "sudo mn -c" )
115 i = self.handle.expect( [ 'password\sfor\s',
116 'Cleanup\scomplete',
117 pexpect.EOF,
118 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800119 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800120 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700121 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800122 main.log.info( self.name + ": Sending sudo password" )
123 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800124 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800125 '\$',
126 pexpect.EOF,
127 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800128 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800129 if i == 1:
130 main.log.info( self.name + ": Clean" )
131 elif i == 2:
132 main.log.error( self.name + ": Connection terminated" )
133 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700134 main.log.error( self.name + ": Something while cleaning " +
135 "Mininet took too long... " )
136 # Craft the string to start mininet
137 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700138 if not mnCmd:
139 if topoFile is None or topoFile == '': # If no file is given
140 main.log.info( self.name + ": building fresh Mininet" )
141 cmdString += "mn "
142 if args is None or args == '':
143 # If no args given, use args from .topo file
144 args = self.options[ 'arg1' ] +\
Jon Halld80cc142015-07-06 13:36:05 -0700145 " " + self.options[ 'arg2' ] +\
146 " --mac --controller " +\
147 self.options[ 'controller' ] + " " +\
148 self.options[ 'arg3' ]
kelvin-onlab10e8d392015-06-03 13:53:45 -0700149 else: # else only use given args
150 pass
151 # TODO: allow use of topo args and method args?
152 else: # Use given topology file
Jon Halld80cc142015-07-06 13:36:05 -0700153 main.log.info(
154 "Starting Mininet from topo file " +
155 topoFile )
kelvin-onlab10e8d392015-06-03 13:53:45 -0700156 cmdString += topoFile + " "
157 if args is None:
158 args = ''
159 # TODO: allow use of args from .topo file?
160 cmdString += args
161 else:
162 main.log.info( "Starting Mininet topology using '" + mnCmd +
163 "' command" )
164 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700165 # Send the command and check if network started
166 self.handle.sendline( "" )
167 self.handle.expect( '\$' )
168 main.log.info( "Sending '" + cmdString + "' to " + self.name )
169 self.handle.sendline( cmdString )
170 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800171 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700172 'Exception',
173 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800174 pexpect.EOF,
175 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700176 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800177 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700178 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800179 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800180 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700181 response = str( self.handle.before +
182 self.handle.after )
183 self.handle.expect( '\$' )
184 response += str( self.handle.before +
Jon Halld80cc142015-07-06 13:36:05 -0700185 self.handle.after )
Jon Hall689d8e42015-04-03 13:59:24 -0700186 main.log.error(
187 self.name +
188 ": Launching Mininet failed: " + response )
189 return main.FALSE
190 elif i == 2:
191 self.handle.expect( [ "\n",
192 pexpect.EOF,
193 pexpect.TIMEOUT ],
194 timeout )
195 main.log.info( self.handle.before )
196 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800197 main.log.error( self.name + ": Connection timeout" )
198 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700199 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800200 main.log.error(
201 self.name +
202 ": Something took too long... " )
203 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700204 # Why did we hit this part?
205 main.log.error( "startNet did not return correctly" )
206 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800207 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700208 main.log.error( self.name + ": Connection failed to the host " +
209 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800210 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700211 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800212
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800213 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400214 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800215 # In tree topology, if fanout arg is not given, by default it is 2
216 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400217 fanout = 2
218 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500219 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800220 while( k <= depth - 1 ):
221 count = count + pow( fanout, k )
222 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800223 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800224 while( k <= depth - 2 ):
225 # depth-2 gives you only core links and not considering
226 # edge links as seen by ONOS. If all the links including
227 # edge links are required, do depth-1
228 count = count + pow( fanout, k )
229 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800230 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800231 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800232 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800233
Jon Hall7eb38402015-01-08 17:19:54 -0800234 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800235 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800236 # by default it is 1
237 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400238 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800239 numSwitches = depth
240 numHostsPerSw = fanout
241 totalNumHosts = numSwitches * numHostsPerSw
242 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800243 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800244 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800245 topoDict = { "num_switches": int( numSwitches ),
246 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400247 return topoDict
248
kelvin-onlabd3b64892015-01-20 13:26:24 -0800249 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700250 """
251 Calculate the number of switches and links in a topo."""
252 # TODO: combine this function and numSwitchesNlinks
253 argList = self.options[ 'arg1' ].split( "," )
254 topoArgList = argList[ 0 ].split( " " )
255 argList = map( int, argList[ 1: ] )
256 topoArgList = topoArgList[ 1: ] + argList
257
258 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400259 return topoDict
260
Jon Halld80cc142015-07-06 13:36:05 -0700261 def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0 ):
Jon Hall7eb38402015-01-08 17:19:54 -0800262 """
263 Verifies the reachability of the hosts using pingall command.
264 Optional parameter timeout allows you to specify how long to
265 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700266 Optional:
Jon Halld80cc142015-07-06 13:36:05 -0700267 timeout( seconds ) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700268 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700269 ping
270 acceptableFailed - Set the number of acceptable failed pings for the
271 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800272 Returns:
273 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700274 otherwise main.FALSE
275 """
276 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700277 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700278 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700279 if self.handle:
280 main.log.info(
281 self.name +
282 ": Checking reachabilty to the hosts using pingall" )
283 response = ""
284 failedPings = 0
285 returnValue = main.TRUE
286 self.handle.sendline( "pingall" )
Jon Hall390696c2015-05-05 17:13:41 -0700287 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700288 while True:
Jon Halld80cc142015-07-06 13:36:05 -0700289 i = self.handle.expect( [ "mininet>", "X",
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700290 pexpect.EOF,
291 pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -0700292 timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700293 if i == 0:
Jon Halld80cc142015-07-06 13:36:05 -0700294 main.log.info( self.name + ": pingall finished" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700295 response += self.handle.before
296 break
297 elif i == 1:
298 response += self.handle.before + self.handle.after
299 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700300 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700301 returnValue = main.FALSE
302 if shortCircuit:
303 main.log.error( self.name +
304 ": Aborting pingall - "
305 + str( failedPings ) +
306 " pings failed" )
307 break
Jon Hall390696c2015-05-05 17:13:41 -0700308 if ( time.time() - startTime ) > timeout:
309 returnValue = main.FALSE
310 main.log.error( self.name +
311 ": Aborting pingall - " +
312 "Function took too long " )
313 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700314 elif i == 2:
315 main.log.error( self.name +
316 ": EOF exception found" )
317 main.log.error( self.name + ": " +
318 self.handle.before )
319 main.cleanup()
320 main.exit()
321 elif i == 3:
322 response += self.handle.before
323 main.log.error( self.name +
324 ": TIMEOUT exception found" )
325 main.log.error( self.name +
326 ": " +
327 str( response ) )
328 # NOTE: Send ctrl-c to make sure pingall is done
329 self.handle.sendline( "\x03" )
330 self.handle.expect( "Interrupt" )
331 self.handle.expect( "mininet>" )
332 break
333 pattern = "Results\:"
334 main.log.info( "Pingall output: " + str( response ) )
335 if re.search( pattern, response ):
336 main.log.info( self.name + ": Pingall finished with "
337 + str( failedPings ) + " failed pings" )
338 return returnValue
339 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700340 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700341 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700342 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700343 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700344 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700345 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700346 main.log.error( self.name + ": Connection failed to the host" )
347 main.cleanup()
348 main.exit()
349 except pexpect.TIMEOUT:
350 if response:
351 main.log.info( "Pingall output: " + str( response ) )
352 main.log.error( self.name + ": pexpect.TIMEOUT found" )
353 return main.FALSE
354 except pexpect.EOF:
355 main.log.error( self.name + ": EOF exception found" )
356 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500357 main.cleanup()
358 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700359
Jon Hall7eb38402015-01-08 17:19:54 -0800360 def fpingHost( self, **pingParams ):
361 """
362 Uses the fping package for faster pinging...
363 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800364 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800365 command = args[ "SRC" ] + \
366 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
367 self.handle.sendline( command )
368 self.handle.expect(
369 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
370 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
371 response = self.handle.before
372 if re.search( ":\s-", response ):
373 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700374 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800375 elif re.search( ":\s\d{1,2}\.\d\d", response ):
376 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700377 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800378 main.log.info( self.name + ": Install fping on mininet machine... " )
379 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700380 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800381
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400382 def pingallHosts( self, hostList, pingType='ipv4' ):
383 """
kelvin-onlab2ff57022015-05-29 10:48:51 -0700384 Ping all specified hosts with a specific ping type
385
386 Acceptable pingTypes:
387 - 'ipv4'
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400388 - 'ipv6'
kelvin-onlab2ff57022015-05-29 10:48:51 -0700389
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400390 Acceptable hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700391 - [ 'h1','h2','h3','h4' ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700392
393 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400394 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700395
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400396 Returns main.FALSE if one or more of hosts specified
397 cannot reach each other"""
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400398 if pingType == "ipv4":
kelvin-onlab2ff57022015-05-29 10:48:51 -0700399 cmd = " ping -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400400 elif pingType == "ipv6":
401 cmd = " ping6 -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400402 else:
403 main.log.warn( "Invalid pingType specified" )
404 return
405
406 try:
407 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700408
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400409 isReachable = main.TRUE
410
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400411 for host in hostList:
Jon Halld80cc142015-07-06 13:36:05 -0700412 listIndex = hostList.index( host )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400413 # List of hosts to ping other than itself
Jon Halld80cc142015-07-06 13:36:05 -0700414 pingList = hostList[ :listIndex ] + \
415 hostList[ ( listIndex + 1 ): ]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700416
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400417 for temp in pingList:
418 # Current host pings all other hosts specified
Jon Halld80cc142015-07-06 13:36:05 -0700419 pingCmd = str( host ) + cmd + str( temp )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400420 self.handle.sendline( pingCmd )
421 i = self.handle.expect( [ pingCmd, pexpect.TIMEOUT ] )
422 j = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
423 response = self.handle.before
424 if re.search( ',\s0\%\spacket\sloss', response ):
Jon Halld80cc142015-07-06 13:36:05 -0700425 main.log.info( str( host ) + " -> " + str( temp ) )
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400426 else:
Jon Halld80cc142015-07-06 13:36:05 -0700427 main.log.info(
428 str( host ) + " -> X (" + str( temp ) + ") "
429 " Destination Unreachable" )
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400430 # One of the host to host pair is unreachable
431 isReachable = main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400432
kelvin-onlab2ff57022015-05-29 10:48:51 -0700433 return isReachable
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400434
435 except pexpect.EOF:
436 main.log.error( self.name + ": EOF exception found" )
437 main.log.error( self.name + ": " + self.handle.before )
438 main.cleanup()
439 main.exit()
440
Jon Hall7eb38402015-01-08 17:19:54 -0800441 def pingHost( self, **pingParams ):
442 """
443 Ping from one mininet host to another
444 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800445 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800446 command = args[ "SRC" ] + " ping " + \
447 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700448 try:
Jon Hall61282e32015-03-19 11:34:11 -0700449 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800450 self.handle.sendline( command )
451 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700452 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800453 main.log.error(
454 self.name +
455 ": timeout when waiting for response from mininet" )
456 main.log.error( "response: " + str( self.handle.before ) )
457 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700458 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800459 main.log.error(
460 self.name +
461 ": timeout when waiting for response from mininet" )
462 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700463 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800464 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800465 main.log.error( self.name + ": EOF exception found" )
466 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700467 main.cleanup()
468 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800469 main.log.info( self.name + ": Ping Response: " + response )
470 if re.search( ',\s0\%\spacket\sloss', response ):
471 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800472 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700473 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800474 else:
475 main.log.error(
476 self.name +
477 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800478 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700479 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800480
Jon Hall7eb38402015-01-08 17:19:54 -0800481 def checkIP( self, host ):
482 """
483 Verifies the host's ip configured or not."""
484 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700485 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800486 response = self.execute(
487 cmd=host +
488 " ifconfig",
489 prompt="mininet>",
490 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800491 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800492 main.log.error( self.name + ": EOF exception found" )
493 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700494 main.cleanup()
495 main.exit()
adminbae64d82013-08-01 10:50:15 -0700496
Jon Hall7eb38402015-01-08 17:19:54 -0800497 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800498 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
499 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
500 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
501 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
502 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800503 # pattern = "inet addr:10.0.0.6"
504 if re.search( pattern, response ):
505 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700506 return main.TRUE
507 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800508 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700509 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800510 else:
511 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800512
Jon Hall7eb38402015-01-08 17:19:54 -0800513 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800514 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700515 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800516 response = self.execute(
517 cmd="h1 /usr/sbin/sshd -D&",
518 prompt="mininet>",
519 timeout=10 )
520 response = self.execute(
521 cmd="h4 /usr/sbin/sshd -D&",
522 prompt="mininet>",
523 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700524 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800525 vars( self )[ key ] = connectargs[ key ]
526 response = self.execute(
527 cmd="xterm h1 h4 ",
528 prompt="mininet>",
529 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800530 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800531 main.log.error( self.name + ": EOF exception found" )
532 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700533 main.cleanup()
534 main.exit()
adminbae64d82013-08-01 10:50:15 -0700535 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800536 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700537 if self.flag == 0:
538 self.flag = 1
539 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800540 else:
adminbae64d82013-08-01 10:50:15 -0700541 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800542
kelvin-onlaba1484582015-02-02 15:46:20 -0800543 def moveHost( self, host, oldSw, newSw, ):
544 """
545 Moves a host from one switch to another on the fly
546 Note: The intf between host and oldSw when detached
547 using detach(), will still show up in the 'net'
548 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Halld80cc142015-07-06 13:36:05 -0700549 ( which is correct behavior since the interfaces
550 haven't moved ).
kelvin-onlaba1484582015-02-02 15:46:20 -0800551 """
552 if self.handle:
553 try:
554 # Bring link between oldSw-host down
Jon Halld80cc142015-07-06 13:36:05 -0700555 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\
Jon Hallefbd9792015-03-05 16:11:36 -0800556 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800557 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800558 response = self.execute( cmd=cmd,
559 prompt="mininet>",
560 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700561
kelvin-onlaba1484582015-02-02 15:46:20 -0800562 # Determine hostintf and Oldswitchintf
563 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800564 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800565 print "cmd2= ", cmd
566 self.handle.sendline( cmd )
567 self.handle.expect( "mininet>" )
568
shahshreya73537862015-02-11 15:15:24 -0800569 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800570 cmd = "px ipaddr = hintf.IP()"
571 print "cmd3= ", cmd
572 self.handle.sendline( cmd )
573 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800574
575 cmd = "px macaddr = hintf.MAC()"
576 print "cmd3= ", cmd
577 self.handle.sendline( cmd )
578 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700579
kelvin-onlaba1484582015-02-02 15:46:20 -0800580 # Detach interface between oldSw-host
581 cmd = "px " + oldSw + ".detach( sintf )"
582 print "cmd4= ", cmd
583 self.handle.sendline( cmd )
584 self.handle.expect( "mininet>" )
585
586 # Add link between host-newSw
587 cmd = "py net.addLink(" + host + "," + newSw + ")"
588 print "cmd5= ", cmd
589 self.handle.sendline( cmd )
590 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700591
kelvin-onlaba1484582015-02-02 15:46:20 -0800592 # Determine hostintf and Newswitchintf
593 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800594 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800595 print "cmd6= ", cmd
596 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700597 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800598
599 # Attach interface between newSw-host
600 cmd = "px " + newSw + ".attach( sintf )"
601 print "cmd3= ", cmd
602 self.handle.sendline( cmd )
603 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700604
kelvin-onlaba1484582015-02-02 15:46:20 -0800605 # Set ipaddress of the host-newSw interface
606 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
607 print "cmd7 = ", cmd
608 self.handle.sendline( cmd )
609 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800610
611 # Set macaddress of the host-newSw interface
612 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
613 print "cmd8 = ", cmd
614 self.handle.sendline( cmd )
615 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700616
kelvin-onlaba1484582015-02-02 15:46:20 -0800617 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800618 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800619 self.handle.sendline( cmd )
620 self.handle.expect( "mininet>" )
621 print "output = ", self.handle.before
622
623 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800624 cmd = host + " ifconfig"
625 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800626 self.handle.sendline( cmd )
627 self.handle.expect( "mininet>" )
628 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700629
kelvin-onlaba1484582015-02-02 15:46:20 -0800630 return main.TRUE
631 except pexpect.EOF:
632 main.log.error( self.name + ": EOF exception found" )
633 main.log.error( self.name + ": " + self.handle.before )
634 return main.FALSE
635
Jon Hall7eb38402015-01-08 17:19:54 -0800636 def changeIP( self, host, intf, newIP, newNetmask ):
637 """
638 Changes the ip address of a host on the fly
639 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800640 if self.handle:
641 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800642 cmd = host + " ifconfig " + intf + " " + \
643 newIP + " " + 'netmask' + " " + newNetmask
644 self.handle.sendline( cmd )
645 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800646 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800647 main.log.info( "response = " + response )
648 main.log.info(
649 "Ip of host " +
650 host +
651 " changed to new IP " +
652 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800653 return main.TRUE
654 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800655 main.log.error( self.name + ": EOF exception found" )
656 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800657 return main.FALSE
658
Jon Hall7eb38402015-01-08 17:19:54 -0800659 def changeDefaultGateway( self, host, newGW ):
660 """
661 Changes the default gateway of a host
662 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800663 if self.handle:
664 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800665 cmd = host + " route add default gw " + newGW
666 self.handle.sendline( cmd )
667 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800668 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800669 main.log.info( "response = " + response )
670 main.log.info(
671 "Default gateway of host " +
672 host +
673 " changed to " +
674 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800675 return main.TRUE
676 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800677 main.log.error( self.name + ": EOF exception found" )
678 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800679 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800680
Jon Hall7eb38402015-01-08 17:19:54 -0800681 def addStaticMACAddress( self, host, GW, macaddr ):
682 """
Jon Hallefbd9792015-03-05 16:11:36 -0800683 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800684 if self.handle:
685 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800686 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
687 cmd = host + " arp -s " + GW + " " + macaddr
688 self.handle.sendline( cmd )
689 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800690 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800691 main.log.info( "response = " + response )
692 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800693 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800694 GW +
695 " changed to " +
696 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800697 return main.TRUE
698 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800699 main.log.error( self.name + ": EOF exception found" )
700 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800701 return main.FALSE
702
Jon Hall7eb38402015-01-08 17:19:54 -0800703 def verifyStaticGWandMAC( self, host ):
704 """
705 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800706 if self.handle:
707 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800708 # h1 arp -an
709 cmd = host + " arp -an "
710 self.handle.sendline( cmd )
711 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800712 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800713 main.log.info( host + " arp -an = " + response )
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 getMacAddress( self, host ):
721 """
722 Verifies the host's ip configured or not."""
723 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700724 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800725 response = self.execute(
726 cmd=host +
727 " ifconfig",
728 prompt="mininet>",
729 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800730 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800731 main.log.error( self.name + ": EOF exception found" )
732 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700733 main.cleanup()
734 main.exit()
adminbae64d82013-08-01 10:50:15 -0700735
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700736 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800737 macAddressSearch = re.search( pattern, response, re.I )
738 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800739 main.log.info(
740 self.name +
741 ": Mac-Address of Host " +
742 host +
743 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800744 macAddress )
745 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700746 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800747 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700748
Jon Hall7eb38402015-01-08 17:19:54 -0800749 def getInterfaceMACAddress( self, host, interface ):
750 """
751 Return the IP address of the interface on the given host"""
752 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700753 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800754 response = self.execute( cmd=host + " ifconfig " + interface,
755 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800756 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800757 main.log.error( self.name + ": EOF exception found" )
758 main.log.error( self.name + ": " + self.handle.before )
759 main.cleanup()
760 main.exit()
761
762 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800763 macAddressSearch = re.search( pattern, response, re.I )
764 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800765 main.log.info( "No mac address found in %s" % response )
766 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800767 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800768 main.log.info(
769 "Mac-Address of " +
770 host +
771 ":" +
772 interface +
773 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800774 macAddress )
775 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800776 else:
777 main.log.error( "Connection failed to the host" )
778
779 def getIPAddress( self, host ):
780 """
781 Verifies the host's ip configured or not."""
782 if self.handle:
783 try:
784 response = self.execute(
785 cmd=host +
786 " ifconfig",
787 prompt="mininet>",
788 timeout=10 )
789 except pexpect.EOF:
790 main.log.error( self.name + ": EOF exception found" )
791 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700792 main.cleanup()
793 main.exit()
adminbae64d82013-08-01 10:50:15 -0700794
795 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800796 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800797 main.log.info(
798 self.name +
799 ": IP-Address of Host " +
800 host +
801 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800802 ipAddressSearch.group( 1 ) )
803 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800804 else:
805 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800806
Jon Hall7eb38402015-01-08 17:19:54 -0800807 def getSwitchDPID( self, switch ):
808 """
809 return the datapath ID of the switch"""
810 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700811 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700812 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800813 response = self.execute(
814 cmd=cmd,
815 prompt="mininet>",
816 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800817 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800818 main.log.error( self.name + ": EOF exception found" )
819 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700820 main.cleanup()
821 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800822 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800823 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700824 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800825 main.log.info(
826 "Couldn't find DPID for switch %s, found: %s" %
827 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700828 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800829 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700830 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800831 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700832
Jon Hall7eb38402015-01-08 17:19:54 -0800833 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700834 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800835 self.handle.sendline( "" )
836 self.expect( "mininet>" )
837 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700838 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800839 response = self.execute(
840 cmd=cmd,
841 prompt="mininet>",
842 timeout=10 )
843 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700844 response = self.handle.before
845 return response
846 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800847 main.log.error( self.name + ": EOF exception found" )
848 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700849 main.cleanup()
850 main.exit()
851
Jon Hall7eb38402015-01-08 17:19:54 -0800852 def getInterfaces( self, node ):
853 """
854 return information dict about interfaces connected to the node"""
855 if self.handle:
856 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800857 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700858 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700859 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800860 response = self.execute(
861 cmd=cmd,
862 prompt="mininet>",
863 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800864 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800865 main.log.error( self.name + ": EOF exception found" )
866 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700867 main.cleanup()
868 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700869 return response
870 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800871 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700872
Jon Hall7eb38402015-01-08 17:19:54 -0800873 def dump( self ):
874 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700875 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800876 response = self.execute(
877 cmd='dump',
878 prompt='mininet>',
879 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800880 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800881 main.log.error( self.name + ": EOF exception found" )
882 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700883 main.cleanup()
884 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700885 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800886
Jon Hall7eb38402015-01-08 17:19:54 -0800887 def intfs( self ):
888 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700889 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800890 response = self.execute(
891 cmd='intfs',
892 prompt='mininet>',
893 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800894 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800895 main.log.error( self.name + ": EOF exception found" )
896 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700897 main.cleanup()
898 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700899 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800900
Jon Hall7eb38402015-01-08 17:19:54 -0800901 def net( self ):
902 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700903 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800904 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800905 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800906 main.log.error( self.name + ": EOF exception found" )
907 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700908 main.cleanup()
909 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700910 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800911
Jon Hallafa8a472015-06-12 14:02:42 -0700912 def links( self ):
913 main.log.info( self.name + ": List network links" )
914 try:
915 response = self.execute( cmd='links', prompt='mininet>',
916 timeout=10 )
917 except pexpect.EOF:
918 main.log.error( self.name + ": EOF exception found" )
919 main.log.error( self.name + ": " + self.handle.before )
920 main.cleanup()
921 main.exit()
922 return response
923
Jon Hall7eb38402015-01-08 17:19:54 -0800924 def iperf( self, host1, host2 ):
925 main.log.info(
926 self.name +
927 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700928 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800929 cmd1 = 'iperf ' + host1 + " " + host2
930 self.handle.sendline( cmd1 )
931 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800932 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800933 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800934 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800935 return main.TRUE
936 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800937 main.log.error( self.name + ": iperf test failed" )
938 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800939 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800940 main.log.error( self.name + ": EOF exception found" )
941 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800942 main.cleanup()
943 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800944
Jon Hall7eb38402015-01-08 17:19:54 -0800945 def iperfudp( self ):
946 main.log.info(
947 self.name +
948 ": Simple iperf TCP test between two " +
949 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700950 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800951 response = self.execute(
952 cmd='iperfudp',
953 prompt='mininet>',
954 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800955 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800956 main.log.error( self.name + ": EOF exception found" )
957 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700958 main.cleanup()
959 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700960 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800961
Jon Hall7eb38402015-01-08 17:19:54 -0800962 def nodes( self ):
963 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700964 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800965 response = self.execute(
966 cmd='nodes',
967 prompt='mininet>',
968 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800969 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800970 main.log.error( self.name + ": EOF exception found" )
971 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700972 main.cleanup()
973 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700974 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800975
Jon Hall7eb38402015-01-08 17:19:54 -0800976 def pingpair( self ):
977 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700978 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800979 response = self.execute(
980 cmd='pingpair',
981 prompt='mininet>',
982 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800983 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800984 main.log.error( self.name + ": EOF exception found" )
985 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700986 main.cleanup()
987 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800988
Jon Hall7eb38402015-01-08 17:19:54 -0800989 if re.search( ',\s0\%\spacket\sloss', response ):
990 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800991 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700992 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800993 else:
994 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800995 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700996 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800997
Jon Hall7eb38402015-01-08 17:19:54 -0800998 def link( self, **linkargs ):
999 """
1000 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001001 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001002 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1003 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1004 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1005 main.log.info(
1006 "Bring link between '" +
1007 end1 +
1008 "' and '" +
1009 end2 +
1010 "' '" +
1011 option +
1012 "'" )
1013 command = "link " + \
1014 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001015 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001016 self.handle.sendline( command )
1017 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001018 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001019 main.log.error( self.name + ": EOF exception found" )
1020 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001021 main.cleanup()
1022 main.exit()
adminbae64d82013-08-01 10:50:15 -07001023 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001024
Jon Hall7eb38402015-01-08 17:19:54 -08001025 def yank( self, **yankargs ):
1026 """
1027 yank a mininet switch interface to a host"""
1028 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001029 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001030 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1031 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1032 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001033 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001034 response = self.execute(
1035 cmd=command,
1036 prompt="mininet>",
1037 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001038 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001039 main.log.error( self.name + ": EOF exception found" )
1040 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001041 main.cleanup()
1042 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001043 return main.TRUE
1044
Jon Hall7eb38402015-01-08 17:19:54 -08001045 def plug( self, **plugargs ):
1046 """
1047 plug the yanked mininet switch interface to a switch"""
1048 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001049 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001050 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1051 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1052 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001053 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001054 response = self.execute(
1055 cmd=command,
1056 prompt="mininet>",
1057 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001058 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001059 main.log.error( self.name + ": EOF exception found" )
1060 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001061 main.cleanup()
1062 main.exit()
adminbae64d82013-08-01 10:50:15 -07001063 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001064
Jon Hall7eb38402015-01-08 17:19:54 -08001065 def dpctl( self, **dpctlargs ):
1066 """
1067 Run dpctl command on all switches."""
1068 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001069 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001070 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1071 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1072 command = "dpctl " + cmd + " " + str( cmdargs )
1073 try:
1074 response = self.execute(
1075 cmd=command,
1076 prompt="mininet>",
1077 timeout=10 )
1078 except pexpect.EOF:
1079 main.log.error( self.name + ": EOF exception found" )
1080 main.log.error( self.name + ": " + self.handle.before )
1081 main.cleanup()
1082 main.exit()
1083 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001084
kelvin-onlabd3b64892015-01-20 13:26:24 -08001085 def getVersion( self ):
Jon Halld80cc142015-07-06 13:36:05 -07001086 # FIXME: What uses this? This should be refactored to get
Jon Hallff6b4b22015-02-23 09:25:15 -08001087 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001088 fileInput = path + '/lib/Mininet/INSTALL'
1089 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001090 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001091 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001092 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001093 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001094 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001095 return version
adminbae64d82013-08-01 10:50:15 -07001096
kelvin-onlabd3b64892015-01-20 13:26:24 -08001097 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001098 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001099 Parameters:
1100 sw: The name of an OVS switch. Example "s1"
1101 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001102 The output of the command from the mininet cli
1103 or main.FALSE on timeout"""
1104 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001105 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001106 response = self.execute(
1107 cmd=command,
1108 prompt="mininet>",
1109 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001110 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001111 return response
admin2a9548d2014-06-17 14:08:07 -07001112 else:
1113 return main.FALSE
1114 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001115 main.log.error( self.name + ": EOF exception found" )
1116 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001117 main.cleanup()
1118 main.exit()
adminbae64d82013-08-01 10:50:15 -07001119
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001120 def assignSwController( self, sw, ip, port="6633", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001121 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001122 Description:
1123 Assign switches to the controllers ( for ovs use only )
1124 Required:
1125 sw - Name of the switch. This can be a list or a string.
1126 ip - Ip addresses of controllers. This can be a list or a string.
1127 Optional:
1128 port - ONOS use port 6633, if no list of ports is passed, then
1129 the all the controller will use 6633 as their port number
1130 ptcp - ptcp number, This can be a string or a list that has
1131 the same length as switch. This is optional and not required
1132 when using ovs switches.
1133 NOTE: If switches and ptcp are given in a list type they should have the
1134 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1135 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001136
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001137 Return:
1138 Returns main.TRUE if mininet correctly assigned switches to
1139 controllers, otherwise it will return main.FALSE or an appropriate
1140 exception(s)
1141 """
1142 assignResult = main.TRUE
1143 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001144 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001145 command = "sh ovs-vsctl set-controller "
1146 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001147 try:
1148 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001149 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001150 if isinstance( port, types.StringType ) or \
1151 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001152 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001153 elif isinstance( port, types.ListType ):
1154 main.log.error( self.name + ": Only one controller " +
1155 "assigned and a list of ports has" +
1156 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001157 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001158 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001159 main.log.error( self.name + ": Invalid controller port " +
1160 "number. Please specify correct " +
1161 "controller port" )
1162 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001163
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001164 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001165 if isinstance( port, types.StringType ) or \
1166 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001167 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001168 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1169 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001170 elif isinstance( port, types.ListType ):
1171 if ( len( ip ) != len( port ) ):
1172 main.log.error( self.name + ": Port list = " +
1173 str( len( port ) ) +
1174 "should be the same as controller" +
1175 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001176 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001177 else:
1178 onosIp = ""
1179 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001180 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1181 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001182 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001183 main.log.error( self.name + ": Invalid controller port " +
1184 "number. Please specify correct " +
1185 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001186 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001187 else:
1188 main.log.error( self.name + ": Invalid ip address" )
1189 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001190
1191 if isinstance( sw, types.StringType ):
1192 command += sw + " "
1193 if ptcp:
1194 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001195 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001196 elif isinstance( ptcp, types.ListType ):
1197 main.log.error( self.name + ": Only one switch is " +
1198 "being set and multiple PTCP is " +
1199 "being passed " )
1200 else:
1201 main.log.error( self.name + ": Invalid PTCP" )
1202 ptcp = ""
1203 command += onosIp
1204 commandList.append( command )
1205
1206 elif isinstance( sw, types.ListType ):
1207 if ptcp:
1208 if isinstance( ptcp, types.ListType ):
1209 if len( ptcp ) != len( sw ):
1210 main.log.error( self.name + ": PTCP length = " +
1211 str( len( ptcp ) ) +
1212 " is not the same as switch" +
1213 " length = " +
1214 str( len( sw ) ) )
1215 return main.FALSE
1216 else:
1217 for switch, ptcpNum in zip( sw, ptcp ):
1218 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001219 tempCmd += switch + " ptcp:" + \
Jon Halld80cc142015-07-06 13:36:05 -07001220 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001221 tempCmd += onosIp
1222 commandList.append( tempCmd )
1223 else:
1224 main.log.error( self.name + ": Invalid PTCP" )
1225 return main.FALSE
1226 else:
1227 for switch in sw:
1228 tempCmd = "sh ovs-vsctl set-controller "
1229 tempCmd += switch + " " + onosIp
1230 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001231 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001232 main.log.error( self.name + ": Invalid switch type " )
1233 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001234
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001235 for cmd in commandList:
1236 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001237 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001238 except pexpect.TIMEOUT:
1239 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1240 return main.FALSE
1241 except pexpect.EOF:
1242 main.log.error( self.name + ": EOF exception found" )
1243 main.log.error( self.name + ": " + self.handle.before )
1244 main.cleanup()
1245 main.exit()
1246 return main.TRUE
1247 except Exception:
1248 main.log.exception( self.name + ": Uncaught exception!" )
1249 main.cleanup()
1250 main.exit()
adminbae64d82013-08-01 10:50:15 -07001251
kelvin-onlabd3b64892015-01-20 13:26:24 -08001252 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001253 """
1254 Removes the controller target from sw"""
1255 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001256 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001257 response = self.execute(
1258 cmd=command,
1259 prompt="mininet>",
1260 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001261 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001262 main.log.error( self.name + ": EOF exception found" )
1263 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001264 main.cleanup()
1265 main.exit()
1266 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001267 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001268
kelvin-onlabd3b64892015-01-20 13:26:24 -08001269 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001270 """
Jon Hallb1290e82014-11-18 16:17:48 -05001271 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001272 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001273 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001274 NOTE: cannot currently specify what type of switch
1275 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001276 sw = name of the new switch as a string
1277 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001278 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001279 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001280 """
1281 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001282 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001283 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001284 response = self.execute(
1285 cmd=command,
1286 prompt="mininet>",
1287 timeout=10 )
1288 if re.search( "already exists!", response ):
1289 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001290 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001291 elif re.search( "Error", response ):
1292 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001293 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001294 elif re.search( "usage:", response ):
1295 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001296 return main.FALSE
1297 else:
1298 return main.TRUE
1299 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001300 main.log.error( self.name + ": EOF exception found" )
Jon Halld80cc142015-07-06 13:36:05 -07001301 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001302 main.cleanup()
1303 main.exit()
1304
kelvin-onlabd3b64892015-01-20 13:26:24 -08001305 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001306 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001307 delete a switch from the mininet topology
1308 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001309 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001310 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001311 sw = name of the switch as a string
1312 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001313 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001314 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001315 response = self.execute(
1316 cmd=command,
1317 prompt="mininet>",
1318 timeout=10 )
1319 if re.search( "no switch named", response ):
1320 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001321 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001322 elif re.search( "Error", response ):
1323 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001324 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001325 elif re.search( "usage:", response ):
1326 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001327 return main.FALSE
1328 else:
1329 return main.TRUE
1330 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001331 main.log.error( self.name + ": EOF exception found" )
1332 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001333 main.cleanup()
1334 main.exit()
1335
kelvin-onlabd3b64892015-01-20 13:26:24 -08001336 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001337 """
1338 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001339 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001340 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001341 NOTE: cannot currently specify what type of link
1342 required params:
1343 node1 = the string node name of the first endpoint of the link
1344 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001345 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001346 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001347 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001348 response = self.execute(
1349 cmd=command,
1350 prompt="mininet>",
1351 timeout=10 )
1352 if re.search( "doesnt exist!", response ):
1353 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001354 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001355 elif re.search( "Error", response ):
1356 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001357 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001358 elif re.search( "usage:", response ):
1359 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001360 return main.FALSE
1361 else:
1362 return main.TRUE
1363 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001364 main.log.error( self.name + ": EOF exception found" )
1365 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001366 main.cleanup()
1367 main.exit()
1368
kelvin-onlabd3b64892015-01-20 13:26:24 -08001369 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001370 """
1371 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001372 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001373 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001374 required params:
1375 node1 = the string node name of the first endpoint of the link
1376 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001377 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001378 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001379 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001380 response = self.execute(
1381 cmd=command,
1382 prompt="mininet>",
1383 timeout=10 )
1384 if re.search( "no node named", response ):
1385 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001386 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001387 elif re.search( "Error", response ):
1388 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001389 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001390 elif re.search( "usage:", response ):
1391 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001392 return main.FALSE
1393 else:
1394 return main.TRUE
1395 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001396 main.log.error( self.name + ": EOF exception found" )
1397 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001398 main.cleanup()
1399 main.exit()
1400
kelvin-onlabd3b64892015-01-20 13:26:24 -08001401 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001402 """
Jon Hallb1290e82014-11-18 16:17:48 -05001403 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001404 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001405 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001406 NOTE: cannot currently specify what type of host
1407 required params:
1408 hostname = the string hostname
1409 optional key-value params
1410 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001411 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001412 """
1413 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001414 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001415 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001416 response = self.execute(
1417 cmd=command,
1418 prompt="mininet>",
1419 timeout=10 )
1420 if re.search( "already exists!", response ):
1421 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001422 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001423 elif re.search( "doesnt exists!", response ):
1424 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001425 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001426 elif re.search( "Error", response ):
1427 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001428 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001429 elif re.search( "usage:", response ):
1430 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001431 return main.FALSE
1432 else:
1433 return main.TRUE
1434 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001435 main.log.error( self.name + ": EOF exception found" )
1436 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001437 main.cleanup()
1438 main.exit()
1439
kelvin-onlabd3b64892015-01-20 13:26:24 -08001440 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001441 """
1442 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001443 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001444 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001445 NOTE: this uses a custom mn function
1446 required params:
1447 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001448 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001449 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001450 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001451 response = self.execute(
1452 cmd=command,
1453 prompt="mininet>",
1454 timeout=10 )
1455 if re.search( "no host named", response ):
1456 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001457 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001458 elif re.search( "Error", response ):
1459 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001460 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001461 elif re.search( "usage:", response ):
1462 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001463 return main.FALSE
1464 else:
1465 return main.TRUE
1466 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001467 main.log.error( self.name + ": EOF exception found" )
1468 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001469 main.cleanup()
1470 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001471
Jon Hall7eb38402015-01-08 17:19:54 -08001472 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001473 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001474 Called at the end of the test to stop the mininet and
1475 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001476 """
Jon Halld80cc142015-07-06 13:36:05 -07001477 self.handle.sendline( '' )
Jon Halld61331b2015-02-17 16:35:47 -08001478 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Halld80cc142015-07-06 13:36:05 -07001479 timeout=2 )
Jon Hall390696c2015-05-05 17:13:41 -07001480 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001481 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001482 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001483 elif i == 1:
1484 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001485 # print "Disconnecting Mininet"
1486 if self.handle:
1487 self.handle.sendline( "exit" )
1488 self.handle.expect( "exit" )
1489 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001490 else:
1491 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001492 return response
1493
Jon Halld80cc142015-07-06 13:36:05 -07001494 def stopNet( self, fileName="", timeout=5 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001495 """
Jon Hall21270ac2015-02-16 17:59:55 -08001496 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001497 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001498 main.FALSE if the pexpect handle does not exist.
1499
Jon Halld61331b2015-02-17 16:35:47 -08001500 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001501 """
Jon Halld61331b2015-02-17 16:35:47 -08001502 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001503 response = ''
1504 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001505 try:
Jon Halld80cc142015-07-06 13:36:05 -07001506 self.handle.sendline( "" )
kelvin-onlab56a3f462015-02-06 14:04:43 -08001507 i = self.handle.expect( [ 'mininet>',
1508 '\$',
1509 pexpect.EOF,
1510 pexpect.TIMEOUT ],
1511 timeout )
1512 if i == 0:
1513 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001514 response = self.execute(
1515 cmd="exit",
1516 prompt="(.*)",
1517 timeout=120 )
Jon Halld80cc142015-07-06 13:36:05 -07001518 main.log.info( self.name + ": Stopped" )
Jon Hall7eb38402015-01-08 17:19:54 -08001519 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001520 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001521
kelvin-onlab56a3f462015-02-06 14:04:43 -08001522 if i == 1:
1523 main.log.info( " Mininet trying to exit while not " +
1524 "in the mininet prompt" )
1525 elif i == 2:
1526 main.log.error( "Something went wrong exiting mininet" )
1527 elif i == 3: # timeout
1528 main.log.error( "Something went wrong exiting mininet " +
1529 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001530
Hari Krishnab35c6d02015-03-18 11:13:51 -07001531 if fileName:
Jon Halld80cc142015-07-06 13:36:05 -07001532 self.handle.sendline( "" )
1533 self.handle.expect( '\$' )
1534 self.handle.sendline(
1535 "sudo kill -9 \`ps -ef | grep \"" +
1536 fileName +
1537 "\" | grep -v grep | awk '{print $2}'\`" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001538 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001539 main.log.error( self.name + ": EOF exception found" )
1540 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001541 main.cleanup()
1542 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001543 else:
1544 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001545 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001546 return response
1547
kelvin-onlabf0594d72015-05-19 17:25:12 -07001548 def arping( self, host="", ip="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001549 """
1550 Description:
1551 Sends arp message from mininet host for hosts discovery
1552 Required:
1553 host - hosts name
1554 Optional:
1555 ip - ip address that does not exist in the network so there would
1556 be no reply.
1557 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001558 if ethDevice:
1559 ethDevice = '-I ' + ethDevice + ' '
Jon Halld80cc142015-07-06 13:36:05 -07001560 cmd = " py " + host + ".cmd(\"arping -c 1 " + ethDevice + ip + "\")"
admin07529932013-11-22 14:58:28 -08001561 try:
kelvin-onlab65782a82015-05-07 14:12:13 -07001562 main.log.warn( "Sending: " + cmd )
1563 self.handle.sendline( cmd )
1564 response = self.handle.before
1565 self.handle.sendline( "" )
1566 self.handle.expect( "mininet>" )
admin07529932013-11-22 14:58:28 -08001567 return main.TRUE
kelvin-onlab65782a82015-05-07 14:12:13 -07001568
1569 except pexpect.EOF:
1570 main.log.error( self.name + ": EOF exception found" )
1571 main.log.error( self.name + ": " + self.handle.before )
1572 main.cleanup()
1573 main.exit()
admin07529932013-11-22 14:58:28 -08001574
Jon Hall7eb38402015-01-08 17:19:54 -08001575 def decToHex( self, num ):
1576 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001577
Jon Hall7eb38402015-01-08 17:19:54 -08001578 def getSwitchFlowCount( self, switch ):
1579 """
1580 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001581 if self.handle:
1582 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1583 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001584 response = self.execute(
1585 cmd=cmd,
1586 prompt="mininet>",
1587 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001588 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001589 main.log.error( self.name + ": EOF exception found" )
1590 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001591 main.cleanup()
1592 main.exit()
1593 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001594 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001595 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001596 main.log.info(
1597 "Couldn't find flows on switch %s, found: %s" %
1598 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001599 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001600 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001601 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001602 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001603
kelvin-onlabd3b64892015-01-20 13:26:24 -08001604 def checkFlows( self, sw, dumpFormat=None ):
1605 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001606 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001607 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001608 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001610 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001611 response = self.execute(
1612 cmd=command,
1613 prompt="mininet>",
1614 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001615 return response
1616 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001617 main.log.error( self.name + ": EOF exception found" )
1618 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001619 main.cleanup()
1620 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001621
kelvin-onlabd3b64892015-01-20 13:26:24 -08001622 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001623 """
Jon Hallefbd9792015-03-05 16:11:36 -08001624 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001625 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001626 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001627 self.handle.sendline( "" )
1628 self.handle.expect( "mininet>" )
1629 self.handle.sendline(
1630 "sh sudo tcpdump -n -i " +
1631 intf +
1632 " " +
1633 port +
1634 " -w " +
1635 filename.strip() +
1636 " &" )
1637 self.handle.sendline( "" )
1638 i = self.handle.expect( [ 'No\ssuch\device',
1639 'listening\son',
1640 pexpect.TIMEOUT,
1641 "mininet>" ],
1642 timeout=10 )
1643 main.log.warn( self.handle.before + self.handle.after )
1644 self.handle.sendline( "" )
1645 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001646 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001647 main.log.error(
1648 self.name +
1649 ": tcpdump - No such device exists. " +
1650 "tcpdump attempted on: " +
1651 intf )
admin2a9548d2014-06-17 14:08:07 -07001652 return main.FALSE
1653 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001654 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001655 return main.TRUE
1656 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001657 main.log.error(
1658 self.name +
1659 ": tcpdump command timed out! Check interface name," +
1660 " given interface was: " +
1661 intf )
admin2a9548d2014-06-17 14:08:07 -07001662 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001663 elif i == 3:
1664 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001665 return main.TRUE
1666 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001667 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001668 return main.FALSE
1669 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001670 main.log.error( self.name + ": EOF exception found" )
1671 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001672 main.cleanup()
1673 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001674 except Exception:
1675 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001676 main.cleanup()
1677 main.exit()
1678
kelvin-onlabd3b64892015-01-20 13:26:24 -08001679 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001680 """
1681 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001682 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001683 self.handle.sendline( "sh sudo pkill tcpdump" )
1684 self.handle.expect( "mininet>" )
1685 self.handle.sendline( "" )
1686 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001687 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001688 main.log.error( self.name + ": EOF exception found" )
1689 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001690 main.cleanup()
1691 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001692 except Exception:
1693 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001694 main.cleanup()
1695 main.exit()
1696
Jon Halld80cc142015-07-06 13:36:05 -07001697 def getPorts( self, nodeName, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001698 """
1699 Read ports from a Mininet switch.
1700
1701 Returns a json structure containing information about the
1702 ports of the given switch.
1703 """
1704 response = self.getInterfaces( nodeName )
1705 # TODO: Sanity check on response. log if no such switch exists
1706 ports = []
1707 for line in response.split( "\n" ):
1708 if not line.startswith( "name=" ):
1709 continue
1710 portVars = {}
1711 for var in line.split( "," ):
1712 key, value = var.split( "=" )
1713 portVars[ key ] = value
1714 isUp = portVars.pop( 'enabled', "True" )
1715 isUp = "True" in isUp
1716 if verbose:
1717 main.log.info( "Reading switch port %s(%s)" %
1718 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1719 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001720 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001721 mac = None
1722 ips = []
1723 ip = portVars[ 'ip' ]
1724 if ip == 'None':
1725 ip = None
1726 ips.append( ip )
1727 name = portVars[ 'name' ]
1728 if name == 'None':
1729 name = None
1730 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
1731 if name == 'lo':
1732 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
1733 else:
1734 portNo = re.search( portRe, name ).group( 'port' )
1735 ports.append( { 'of_port': portNo,
1736 'mac': str( mac ).replace( '\'', '' ),
1737 'name': name,
1738 'ips': ips,
1739 'enabled': isUp } )
1740 return ports
1741
Jon Halld80cc142015-07-06 13:36:05 -07001742 def getSwitches( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001743 """
1744 Read switches from Mininet.
1745
1746 Returns a dictionary whose keys are the switch names and the value is
1747 a dictionary containing information about the switch.
1748 """
1749 # FIXME: This currently only works with OVS Switches
1750
1751 # Regex patterns to parse dump output
1752 # Example Switch:
1753 # <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 -07001754 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
Jon Hallafa8a472015-06-12 14:02:42 -07001755 swRE = r"<OVSSwitch(\{.*\})?\s(?P<name>[^:]+)\:\s" +\
1756 "(?P<ports>([^,]+,)*[^,\s]+)"
1757 # Update mn port info
1758 self.update()
Jon Halld80cc142015-07-06 13:36:05 -07001759 output = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001760 dump = self.dump().split( "\n" )
1761 for line in dump:
1762 if line.startswith( "<OVSSwitch" ):
1763 result = re.search( swRE, line, re.I )
1764 name = result.group( 'name' )
1765 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
1766 if verbose:
1767 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
1768 ports = self.getPorts( name )
1769 output[ name ] = { "dpid": dpid, "ports": ports }
1770 return output
1771
Jon Halld80cc142015-07-06 13:36:05 -07001772 def getHosts( self, verbose=False ):
Jon Hallafa8a472015-06-12 14:02:42 -07001773 """
1774 Read hosts from Mininet.
1775
1776 Returns a dictionary whose keys are the host names and the value is
1777 a dictionary containing information about the host.
1778 """
1779 # Regex patterns to parse dump output
1780 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
1781 # or <Host h1: pid=12725>
1782 # NOTE: Does not correctly match hosts with multi-links
1783 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
1784 # FIXME: Fix that
1785 hostRE = r"<Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
Jon Halld80cc142015-07-06 13:36:05 -07001786 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
Jon Hallafa8a472015-06-12 14:02:42 -07001787 # update mn port info
1788 self.update()
1789 # Get mininet dump
1790 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07001791 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001792 for line in dump:
1793 if line.startswith( "<Host" ):
1794 result = re.search( hostRE, line )
1795 name = result.group( 'name' )
1796 interfaces = []
1797 response = self.getInterfaces( name )
1798 # Populate interface info
1799 for line in response.split( "\n" ):
1800 if line.startswith( "name=" ):
1801 portVars = {}
1802 for var in line.split( "," ):
1803 key, value = var.split( "=" )
1804 portVars[ key ] = value
1805 isUp = portVars.pop( 'enabled', "True" )
1806 isUp = "True" in isUp
1807 if verbose:
1808 main.log.info( "Reading host port %s(%s)" %
1809 ( portVars[ 'name' ],
1810 portVars[ 'mac' ] ) )
1811 mac = portVars[ 'mac' ]
Jon Halld80cc142015-07-06 13:36:05 -07001812 if mac == 'None':
Jon Hallafa8a472015-06-12 14:02:42 -07001813 mac = None
1814 ips = []
1815 ip = portVars[ 'ip' ]
1816 if ip == 'None':
1817 ip = None
1818 ips.append( ip )
1819 intfName = portVars[ 'name' ]
1820 if name == 'None':
1821 name = None
1822 interfaces.append( {
1823 "name": intfName,
1824 "ips": ips,
1825 "mac": str( mac ),
1826 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07001827 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07001828 return hosts
1829
1830 def getLinks( self ):
1831 """
1832 Gathers information about current Mininet links. These links may not
1833 be up if one of the ports is down.
1834
1835 Returns a list of dictionaries with link endpoints.
1836
1837 The dictionary structure is:
Jon Halld80cc142015-07-06 13:36:05 -07001838 { 'node1': str( node1 name )
1839 'node2': str( node2 name )
1840 'port1': str( port1 of_port )
1841 'port2': str( port2 of_port ) }
Jon Hallafa8a472015-06-12 14:02:42 -07001842 Note: The port number returned is the eth#, not necessarily the of_port
1843 number. In Mininet, for OVS switch, these should be the same. For
1844 hosts, this is just the eth#.
1845 """
1846 self.update()
1847 response = self.links().split( '\n' )
1848
1849 # Examples:
1850 # s1-eth3<->s2-eth1 (OK OK)
1851 # s13-eth3<->h27-eth0 (OK OK)
1852 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
1853 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
1854 links = []
1855 for line in response:
1856 match = re.search( linkRE, line )
1857 if match:
1858 node1 = match.group( 'node1' )
1859 node2 = match.group( 'node2' )
1860 port1 = match.group( 'port1' )
1861 port2 = match.group( 'port2' )
1862 links.append( { 'node1': node1,
1863 'node2': node2,
1864 'port1': port1,
1865 'port2': port2 } )
1866 return links
1867
1868 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001869 """
1870 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07001871 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001872
Jon Hallafa8a472015-06-12 14:02:42 -07001873 Dependencies:
1874 1. numpy - "sudo pip install numpy"
1875 """
1876 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04001877 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001878 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07001879 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08001880 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001881 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08001882 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001883 main.log.error(
1884 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07001885 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001886 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001887 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001888 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001889 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001890 if switch[ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07001891 onosDPIDs.append(
1892 switch[ 'id' ].replace(
1893 ":",
1894 '' ).replace(
1895 "of",
1896 '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001897 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04001898
Jon Hall7eb38402015-01-08 17:19:54 -08001899 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001900 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07001901 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001902 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001903 main.log.error( str( list1 ) )
1904 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001905 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001906 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001907 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001908 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001909 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001910
Jon Hall7eb38402015-01-08 17:19:54 -08001911 # FIXME: this does not look for extra ports in ONOS, only checks that
1912 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08001913 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001914
Jon Hall7eb38402015-01-08 17:19:54 -08001915 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07001916 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08001917 mnPorts = []
1918 onosPorts = []
1919 switchResult = main.TRUE
1920 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001921 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07001922 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001923 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001924 if onosSwitch[ 'device' ][ 'available' ]:
Jon Halld80cc142015-07-06 13:36:05 -07001925 if onosSwitch[ 'device' ][ 'id' ].replace(
1926 ':',
1927 '' ).replace(
1928 "of",
1929 '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001930 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001931 if port[ 'isEnabled' ]:
1932 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001933 # onosPorts.append( 'local' )
1934 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001935 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001936 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001937 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001938 mnPorts.sort( key=float )
1939 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07001940
kelvin-onlabd3b64892015-01-20 13:26:24 -08001941 mnPortsLog = mnPorts
1942 onosPortsLog = onosPorts
1943 mnPorts = [ x for x in mnPorts ]
1944 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001945
Jon Hall7eb38402015-01-08 17:19:54 -08001946 # TODO: handle other reserved port numbers besides LOCAL
1947 # NOTE: Reserved ports
1948 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1949 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001950 for mnPort in mnPortsLog:
1951 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001952 # don't set results to true here as this is just one of
1953 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001954 mnPorts.remove( mnPort )
1955 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07001956
Jon Hall7eb38402015-01-08 17:19:54 -08001957 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001958 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001959 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001960 if 65534 in mnPorts:
1961 mnPorts.remove( 65534 )
1962 if long( uint64( -2 ) ) in onosPorts:
1963 onosPorts.remove( long( uint64( -2 ) ) )
1964 if len( mnPorts ): # the ports of this switch don't match
1965 switchResult = main.FALSE
1966 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1967 if len( onosPorts ): # the ports of this switch don't match
1968 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001969 main.log.warn(
1970 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001971 str( onosPorts ) )
1972 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07001973 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08001974 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07001975 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001976 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1977 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1978 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07001979 finalResults = finalResults and portsResults
1980 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001981
Jon Hallafa8a472015-06-12 14:02:42 -07001982 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001983 """
1984 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08001985 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001986
Jon Hallafa8a472015-06-12 14:02:42 -07001987 """
Jon Hall7eb38402015-01-08 17:19:54 -08001988 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08001989 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08001990 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04001991
Jon Halld80cc142015-07-06 13:36:05 -07001992 mnLinks = []
Jon Hallafa8a472015-06-12 14:02:42 -07001993 for l in links:
1994 try:
1995 node1 = switches[ l[ 'node1' ] ]
1996 node2 = switches[ l[ 'node2' ] ]
1997 enabled = True
1998 for port in node1[ 'ports' ]:
1999 if port[ 'of_port' ] == l[ 'port1' ]:
2000 enabled = enabled and port[ 'enabled' ]
2001 for port in node2[ 'ports' ]:
Jon Halld80cc142015-07-06 13:36:05 -07002002 if port[ 'of_port' ] == l[ 'port2' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002003 enabled = enabled and port[ 'enabled' ]
2004 if enabled:
2005 mnLinks.append( l )
2006 except KeyError:
2007 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002008 if 2 * len( mnLinks ) == len( onos ):
2009 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002010 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002011 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002012 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002013 "Mininet has " + str( len( mnLinks ) ) +
2014 " bidirectional links and ONOS has " +
2015 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002016
Jon Hall7eb38402015-01-08 17:19:54 -08002017 # iterate through MN links and check if an ONOS link exists in
2018 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002019 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002020 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002021 node1 = None
2022 port1 = None
2023 node2 = None
2024 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002025 firstDir = main.FALSE
2026 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002027 for swName, switch in switches.iteritems():
2028 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002029 node1 = switch[ 'dpid' ]
2030 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002031 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002032 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002033 if node1 is not None and node2 is not None:
2034 break
Jon Hallafa8a472015-06-12 14:02:42 -07002035 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002036 node2 = switch[ 'dpid' ]
2037 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002038 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002039 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002040 if node1 is not None and node2 is not None:
2041 break
2042
kelvin-onlabd3b64892015-01-20 13:26:24 -08002043 for onosLink in onos:
2044 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002045 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002046 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002047 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002048 onosPort1 = onosLink[ 'src' ][ 'port' ]
2049 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002050
Jon Hall72cf1dc2014-10-20 21:04:50 -04002051 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002052 if str( onosNode1 ) == str( node1 ) and str(
2053 onosNode2 ) == str( node2 ):
2054 if int( onosPort1 ) == int( port1 ) and int(
2055 onosPort2 ) == int( port2 ):
2056 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002057 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002058 main.log.warn(
2059 'The port numbers do not match for ' +
2060 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002061 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002062 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002063 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002064 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002065 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002066
2067 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002068 elif ( str( onosNode1 ) == str( node2 ) and
2069 str( onosNode2 ) == str( node1 ) ):
2070 if ( int( onosPort1 ) == int( port2 )
2071 and int( onosPort2 ) == int( port1 ) ):
2072 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002073 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002074 main.log.warn(
2075 'The port numbers do not match for ' +
2076 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002077 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002078 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002079 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002080 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002081 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002082 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002083 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002084 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002085 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002086 'ONOS does not have the link %s/%s -> %s/%s' %
2087 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002088 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002089 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002090 'ONOS does not have the link %s/%s -> %s/%s' %
2091 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002092 linkResults = linkResults and firstDir and secondDir
2093 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002094
Jon Hallafa8a472015-06-12 14:02:42 -07002095 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002096 """
Jon Hallafa8a472015-06-12 14:02:42 -07002097 Compare mn and onos Hosts.
2098 Since Mininet hosts are quiet, ONOS will only know of them when they
2099 speak. For this reason, we will only check that the hosts in ONOS
2100 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002101
Jon Hallafa8a472015-06-12 14:02:42 -07002102 Arguments:
2103 hostsJson: parsed json object from the onos hosts api
2104 Returns:
2105 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002106 import json
2107 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002108 for onosHost in hostsJson:
2109 onosMAC = onosHost[ 'mac' ].lower()
2110 match = False
Jon Halld80cc142015-07-06 13:36:05 -07002111 for mnHost, info in hosts.iteritems():
2112 for mnIntf in info[ 'interfaces' ]:
2113 if onosMAC == mnIntf[ 'mac' ].lower():
Jon Hallff6b4b22015-02-23 09:25:15 -08002114 match = True
2115 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002116 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002117 pass # all is well
2118 else:
2119 # misssing ip
Jon Halld80cc142015-07-06 13:36:05 -07002120 main.log.error( "ONOS host " +
2121 onosHost[ 'id' ] +
2122 " has a different IP(" +
Jon Hallafa8a472015-06-12 14:02:42 -07002123 str( onosHost[ 'ipAddresses' ] ) +
2124 ") than the Mininet host(" +
Jon Halld80cc142015-07-06 13:36:05 -07002125 str( ip ) +
2126 ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002127 output = json.dumps(
Jon Halld80cc142015-07-06 13:36:05 -07002128 onosHost,
2129 sort_keys=True,
2130 indent=4,
2131 separators=( ',', ': ' ) )
Jon Hallff6b4b22015-02-23 09:25:15 -08002132 main.log.info( output )
2133 hostResults = main.FALSE
2134 if not match:
2135 hostResults = main.FALSE
2136 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2137 "corresponding Mininet host." )
2138 output = json.dumps( onosHost,
2139 sort_keys=True,
2140 indent=4,
2141 separators=( ',', ': ' ) )
2142 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002143 return hostResults
2144
Jon Hallafa8a472015-06-12 14:02:42 -07002145 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002146 """
2147 Returns a list of all hosts
2148 Don't ask questions just use it"""
2149 self.handle.sendline( "" )
2150 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002151
Jon Hall7eb38402015-01-08 17:19:54 -08002152 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2153 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002154
kelvin-onlabd3b64892015-01-20 13:26:24 -08002155 handlePy = self.handle.before
2156 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2157 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002158
Jon Hall7eb38402015-01-08 17:19:54 -08002159 self.handle.sendline( "" )
2160 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002161
kelvin-onlabd3b64892015-01-20 13:26:24 -08002162 hostStr = handlePy.replace( "]", "" )
2163 hostStr = hostStr.replace( "'", "" )
2164 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002165 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002166 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002167
kelvin-onlabd3b64892015-01-20 13:26:24 -08002168 return hostList
adminbae64d82013-08-01 10:50:15 -07002169
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002170 def getSwitch( self ):
2171 """
2172 Returns a list of all switches
2173 Again, don't ask question just use it...
2174 """
2175 # get host list...
2176 hostList = self.getHosts()
2177 # Make host set
2178 hostSet = set( hostList )
2179
2180 # Getting all the nodes in mininet
2181 self.handle.sendline( "" )
2182 self.handle.expect( "mininet>" )
2183
2184 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2185 self.handle.expect( "mininet>" )
2186
2187 handlePy = self.handle.before
2188 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2189 handlePy = handlePy.rstrip()
2190
2191 self.handle.sendline( "" )
2192 self.handle.expect( "mininet>" )
2193
2194 nodesStr = handlePy.replace( "]", "" )
2195 nodesStr = nodesStr.replace( "'", "" )
2196 nodesStr = nodesStr.replace( "[", "" )
2197 nodesStr = nodesStr.replace( " ", "" )
2198 nodesList = nodesStr.split( "," )
2199
2200 nodesSet = set( nodesList )
2201 # discarding default controller(s) node
2202 nodesSet.discard( 'c0' )
2203 nodesSet.discard( 'c1' )
2204 nodesSet.discard( 'c2' )
2205
2206 switchSet = nodesSet - hostSet
2207 switchList = list( switchSet )
2208
2209 return switchList
2210
Jon Hall7eb38402015-01-08 17:19:54 -08002211 def update( self ):
2212 """
2213 updates the port address and status information for
2214 each port in mn"""
2215 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002216 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002217 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002218 self.handle.sendline( "" )
2219 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002220
Jon Hall7eb38402015-01-08 17:19:54 -08002221 self.handle.sendline( "update" )
2222 self.handle.expect( "update" )
2223 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002224
Jon Hall7eb38402015-01-08 17:19:54 -08002225 self.handle.sendline( "" )
2226 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002227
Jon Hallb1290e82014-11-18 16:17:48 -05002228 return main.TRUE
2229 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002230 main.log.error( self.name + ": EOF exception found" )
2231 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002232 main.cleanup()
2233 main.exit()
2234
Jon Halld80cc142015-07-06 13:36:05 -07002235 def assignVLAN( self, host, intf, vlan ):
kaouthera3f13ca22015-05-05 15:01:41 -07002236 """
2237 Add vlan tag to a host.
2238 Dependencies:
2239 This class depends on the "vlan" package
2240 $ sudo apt-get install vlan
2241 Configuration:
2242 Load the 8021q module into the kernel
2243 $sudo modprobe 8021q
2244
2245 To make this setup permanent:
2246 $ sudo su -c 'echo "8021q" >> /etc/modules'
2247 """
2248 if self.handle:
2249 try:
Jon Halld80cc142015-07-06 13:36:05 -07002250 # get the ip address of the host
2251 main.log.info( "Get the ip address of the host" )
2252 ipaddr = self.getIPAddress( host )
2253 print repr( ipaddr )
kaouthera3f13ca22015-05-05 15:01:41 -07002254
Jon Halld80cc142015-07-06 13:36:05 -07002255 # remove IP from interface intf
2256 # Ex: h1 ifconfig h1-eth0 inet 0
2257 main.log.info( "Remove IP from interface " )
2258 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2259 self.handle.sendline( cmd2 )
2260 self.handle.expect( "mininet>" )
2261 response = self.handle.before
2262 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002263
Jon Halld80cc142015-07-06 13:36:05 -07002264 # create VLAN interface
2265 # Ex: h1 vconfig add h1-eth0 100
2266 main.log.info( "Create Vlan" )
2267 cmd3 = host + " vconfig add " + intf + " " + vlan
2268 self.handle.sendline( cmd3 )
2269 self.handle.expect( "mininet>" )
2270 response = self.handle.before
2271 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002272
Jon Halld80cc142015-07-06 13:36:05 -07002273 # assign the host's IP to the VLAN interface
2274 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2275 main.log.info( "Assign the host IP to the vlan interface" )
2276 vintf = intf + "." + vlan
2277 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2278 self.handle.sendline( cmd4 )
2279 self.handle.expect( "mininet>" )
2280 response = self.handle.before
2281 main.log.info( "====> %s ", response )
kaouthera3f13ca22015-05-05 15:01:41 -07002282
2283 return main.TRUE
2284 except pexpect.EOF:
2285 main.log.error( self.name + ": EOF exception found" )
2286 main.log.error( self.name + ": " + self.handle.before )
2287 return main.FALSE
2288
adminbae64d82013-08-01 10:50:15 -07002289if __name__ != "__main__":
2290 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002291 sys.modules[ __name__ ] = MininetCliDriver()