blob: ce6e02d594c2f9cac1ce9aefc0c5056d6a153198 [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
21
Jon Hallbe6dfc42015-01-12 17:37:25 -080022MininetCliDriver is the basic driver which will handle the Mininet functions
23
Jon Hall272a4db2015-01-12 17:43:48 -080024Some functions rely on STS module. To install this,
25 git clone https://github.com/jhall11/sts.git
26
Jon Hallbe6dfc42015-01-12 17:37:25 -080027Some functions rely on a modified version of Mininet. These functions
28should all be noted in the comments. To get this MN version run these commands
29from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080030 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080032 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080033 git pull
34
Jon Hall272a4db2015-01-12 17:43:48 -080035
36 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080037changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070038import pexpect
adminbae64d82013-08-01 10:50:15 -070039import re
40import sys
Jon Hall7eb38402015-01-08 17:19:54 -080041sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070044
Jon Hall7eb38402015-01-08 17:19:54 -080045
kelvin-onlab50907142015-04-01 13:37:45 -070046class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080047
48 """
49 MininetCliDriver is the basic driver which will handle
50 the Mininet functions"""
51 def __init__( self ):
52 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070053 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080054 self.name = None
Jon Hall7eb38402015-01-08 17:19:54 -080055 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070056 self.flag = 0
57
Jon Hall7eb38402015-01-08 17:19:54 -080058 def connect( self, **connectargs ):
59 """
60 Here the main is the TestON instance after creating
61 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080062 try:
63 for key in connectargs:
64 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080065
kelvin-onlaba1484582015-02-02 15:46:20 -080066 self.name = self.options[ 'name' ]
67 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070068 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080069 self ).connect(
70 user_name=self.user_name,
71 ip_address=self.ip_address,
72 port=None,
73 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080074
kelvin-onlaba1484582015-02-02 15:46:20 -080075 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080076 main.log.info( "Connection successful to the host " +
77 self.user_name +
78 "@" +
79 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080080 return main.TRUE
81 else:
82 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080083 self.user_name +
84 "@" +
85 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -080086 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -080087 return main.FALSE
88 except pexpect.EOF:
89 main.log.error( self.name + ": EOF exception found" )
90 main.log.error( self.name + ": " + self.handle.before )
91 main.cleanup()
92 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -080093 except Exception:
94 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -080095 main.cleanup()
96 main.exit()
97
Jon Hallefbd9792015-03-05 16:11:36 -080098 def startNet( self, topoFile='', args='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -080099 """
100 Starts Mininet accepts a topology(.py) file and/or an optional
Jon Hallefbd9792015-03-05 16:11:36 -0800101 argument ,to start the mininet, as a parameter.
Jon Hall21270ac2015-02-16 17:59:55 -0800102 Returns main.TRUE if the mininet starts successfully and
103 main.FALSE otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800104 """
Jon Hall7eb38402015-01-08 17:19:54 -0800105 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700106 # make sure old networks are cleaned up
107 main.log.info( self.name +
108 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800109 self.handle.sendline( "sudo mn -c" )
110 i = self.handle.expect( [ 'password\sfor\s',
111 'Cleanup\scomplete',
112 pexpect.EOF,
113 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800114 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800115 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700116 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800117 main.log.info( self.name + ": Sending sudo password" )
118 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800119 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800120 '\$',
121 pexpect.EOF,
122 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800123 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800124 if i == 1:
125 main.log.info( self.name + ": Clean" )
126 elif i == 2:
127 main.log.error( self.name + ": Connection terminated" )
128 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700129 main.log.error( self.name + ": Something while cleaning " +
130 "Mininet took too long... " )
131 # Craft the string to start mininet
132 cmdString = "sudo "
133 if topoFile is None or topoFile == '': # If no file is given
134 main.log.info( self.name + ": building fresh Mininet" )
135 cmdString += "mn "
136 if args is None or args == '':
137 # If no args given, use args from .topo file
138 args = self.options[ 'arg1' ] +\
139 " " + self.options[ 'arg2' ] +\
140 " --mac --controller " +\
141 self.options[ 'controller' ] + " " +\
142 self.options[ 'arg3' ]
143 else: # else only use given args
144 pass
145 # TODO: allow use of topo args and method args?
146 else: # Use given topology file
147 main.log.info( "Starting Mininet from topo file " + topoFile )
148 cmdString += topoFile + " "
Jon Hallefbd9792015-03-05 16:11:36 -0800149 if args is None:
kelvin-onlaba1484582015-02-02 15:46:20 -0800150 args = ''
Jon Hall689d8e42015-04-03 13:59:24 -0700151 # TODO: allow use of args from .topo file?
152 cmdString += args
153 # Send the command and check if network started
154 self.handle.sendline( "" )
155 self.handle.expect( '\$' )
156 main.log.info( "Sending '" + cmdString + "' to " + self.name )
157 self.handle.sendline( cmdString )
158 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800159 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700160 'Exception',
161 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800162 pexpect.EOF,
163 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700164 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800165 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700166 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800167 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800168 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700169 response = str( self.handle.before +
170 self.handle.after )
171 self.handle.expect( '\$' )
172 response += str( self.handle.before +
173 self.handle.after )
174 main.log.error(
175 self.name +
176 ": Launching Mininet failed: " + response )
177 return main.FALSE
178 elif i == 2:
179 self.handle.expect( [ "\n",
180 pexpect.EOF,
181 pexpect.TIMEOUT ],
182 timeout )
183 main.log.info( self.handle.before )
184 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800185 main.log.error( self.name + ": Connection timeout" )
186 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700187 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800188 main.log.error(
189 self.name +
190 ": Something took too long... " )
191 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700192 # Why did we hit this part?
193 main.log.error( "startNet did not return correctly" )
194 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800195 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700196 main.log.error( self.name + ": Connection failed to the host " +
197 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800198 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700199 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800200
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800201 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400202 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800203 # In tree topology, if fanout arg is not given, by default it is 2
204 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400205 fanout = 2
206 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500207 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800208 while( k <= depth - 1 ):
209 count = count + pow( fanout, k )
210 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800211 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800212 while( k <= depth - 2 ):
213 # depth-2 gives you only core links and not considering
214 # edge links as seen by ONOS. If all the links including
215 # edge links are required, do depth-1
216 count = count + pow( fanout, k )
217 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800218 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800219 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800220 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800221
Jon Hall7eb38402015-01-08 17:19:54 -0800222 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800223 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800224 # by default it is 1
225 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400226 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800227 numSwitches = depth
228 numHostsPerSw = fanout
229 totalNumHosts = numSwitches * numHostsPerSw
230 numLinks = totalNumHosts + ( numSwitches - 1 )
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 Hallefbd9792015-03-05 16:11:36 -0800233 topoDict = { "num_switches": int( numSwitches ),
234 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400235 return topoDict
236
kelvin-onlabd3b64892015-01-20 13:26:24 -0800237 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700238 """
239 Calculate the number of switches and links in a topo."""
240 # TODO: combine this function and numSwitchesNlinks
241 argList = self.options[ 'arg1' ].split( "," )
242 topoArgList = argList[ 0 ].split( " " )
243 argList = map( int, argList[ 1: ] )
244 topoArgList = topoArgList[ 1: ] + argList
245
246 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400247 return topoDict
248
kelvin-onlabc44f0192015-04-02 22:08:41 -0700249 def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0):
Jon Hall7eb38402015-01-08 17:19:54 -0800250 """
251 Verifies the reachability of the hosts using pingall command.
252 Optional parameter timeout allows you to specify how long to
253 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700254 Optional:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700255 timeout(seconds) - This is the pexpect timeout; The function will
256 timeout if the amount of time between failed
257 pings exceedes this time and pingall is still
258 running
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700259 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700260 ping
261 acceptableFailed - Set the number of acceptable failed pings for the
262 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800263 Returns:
264 main.TRUE if pingall completes with no pings dropped
265 otherwise main.FALSE"""
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700266 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700267 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700268 if self.handle:
269 main.log.info(
270 self.name +
271 ": Checking reachabilty to the hosts using pingall" )
272 response = ""
273 failedPings = 0
274 returnValue = main.TRUE
275 self.handle.sendline( "pingall" )
276 while True:
277 i = self.handle.expect( [ "mininet>","X",
278 pexpect.EOF,
279 pexpect.TIMEOUT ],
280 timeout )
281 if i == 0:
282 main.log.info( self.name + ": pingall finished")
283 response += self.handle.before
284 break
285 elif i == 1:
286 response += self.handle.before + self.handle.after
287 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700288 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700289 returnValue = main.FALSE
290 if shortCircuit:
291 main.log.error( self.name +
292 ": Aborting pingall - "
293 + str( failedPings ) +
294 " pings failed" )
295 break
296 elif i == 2:
297 main.log.error( self.name +
298 ": EOF exception found" )
299 main.log.error( self.name + ": " +
300 self.handle.before )
301 main.cleanup()
302 main.exit()
303 elif i == 3:
304 response += self.handle.before
305 main.log.error( self.name +
306 ": TIMEOUT exception found" )
307 main.log.error( self.name +
308 ": " +
309 str( response ) )
310 # NOTE: Send ctrl-c to make sure pingall is done
311 self.handle.sendline( "\x03" )
312 self.handle.expect( "Interrupt" )
313 self.handle.expect( "mininet>" )
314 break
315 pattern = "Results\:"
316 main.log.info( "Pingall output: " + str( response ) )
317 if re.search( pattern, response ):
318 main.log.info( self.name + ": Pingall finished with "
319 + str( failedPings ) + " failed pings" )
320 return returnValue
321 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700322 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700323 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700324 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700325 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700326 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700327 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700328 main.log.error( self.name + ": Connection failed to the host" )
329 main.cleanup()
330 main.exit()
331 except pexpect.TIMEOUT:
332 if response:
333 main.log.info( "Pingall output: " + str( response ) )
334 main.log.error( self.name + ": pexpect.TIMEOUT found" )
335 return main.FALSE
336 except pexpect.EOF:
337 main.log.error( self.name + ": EOF exception found" )
338 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500339 main.cleanup()
340 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700341
Jon Hall7eb38402015-01-08 17:19:54 -0800342 def fpingHost( self, **pingParams ):
343 """
344 Uses the fping package for faster pinging...
345 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800346 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800347 command = args[ "SRC" ] + \
348 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
349 self.handle.sendline( command )
350 self.handle.expect(
351 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
352 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
353 response = self.handle.before
354 if re.search( ":\s-", response ):
355 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700356 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800357 elif re.search( ":\s\d{1,2}\.\d\d", response ):
358 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700359 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800360 main.log.info( self.name + ": Install fping on mininet machine... " )
361 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700362 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800363
Jon Hall7eb38402015-01-08 17:19:54 -0800364 def pingHost( self, **pingParams ):
365 """
366 Ping from one mininet host to another
367 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800368 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800369 command = args[ "SRC" ] + " ping " + \
370 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700371 try:
Jon Hall61282e32015-03-19 11:34:11 -0700372 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800373 self.handle.sendline( command )
374 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700375 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800376 main.log.error(
377 self.name +
378 ": timeout when waiting for response from mininet" )
379 main.log.error( "response: " + str( self.handle.before ) )
380 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700381 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800382 main.log.error(
383 self.name +
384 ": timeout when waiting for response from mininet" )
385 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700386 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800387 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800388 main.log.error( self.name + ": EOF exception found" )
389 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700390 main.cleanup()
391 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800392 main.log.info( self.name + ": Ping Response: " + response )
393 if re.search( ',\s0\%\spacket\sloss', response ):
394 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800395 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700396 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800397 else:
398 main.log.error(
399 self.name +
400 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800401 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700402 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800403
Jon Hall7eb38402015-01-08 17:19:54 -0800404 def checkIP( self, host ):
405 """
406 Verifies the host's ip configured or not."""
407 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700408 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800409 response = self.execute(
410 cmd=host +
411 " ifconfig",
412 prompt="mininet>",
413 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800414 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800415 main.log.error( self.name + ": EOF exception found" )
416 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700417 main.cleanup()
418 main.exit()
adminbae64d82013-08-01 10:50:15 -0700419
Jon Hall7eb38402015-01-08 17:19:54 -0800420 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800421 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
422 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
423 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
424 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
425 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800426 # pattern = "inet addr:10.0.0.6"
427 if re.search( pattern, response ):
428 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700429 return main.TRUE
430 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800431 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700432 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800433 else:
434 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800435
Jon Hall7eb38402015-01-08 17:19:54 -0800436 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800437 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700438 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800439 response = self.execute(
440 cmd="h1 /usr/sbin/sshd -D&",
441 prompt="mininet>",
442 timeout=10 )
443 response = self.execute(
444 cmd="h4 /usr/sbin/sshd -D&",
445 prompt="mininet>",
446 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700447 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800448 vars( self )[ key ] = connectargs[ key ]
449 response = self.execute(
450 cmd="xterm h1 h4 ",
451 prompt="mininet>",
452 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800453 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800454 main.log.error( self.name + ": EOF exception found" )
455 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700456 main.cleanup()
457 main.exit()
adminbae64d82013-08-01 10:50:15 -0700458 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800459 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700460 if self.flag == 0:
461 self.flag = 1
462 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800463 else:
adminbae64d82013-08-01 10:50:15 -0700464 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800465
kelvin-onlaba1484582015-02-02 15:46:20 -0800466 def moveHost( self, host, oldSw, newSw, ):
467 """
468 Moves a host from one switch to another on the fly
469 Note: The intf between host and oldSw when detached
470 using detach(), will still show up in the 'net'
471 cmd, because switch.detach() doesn't affect switch.intfs[]
472 (which is correct behavior since the interfaces
473 haven't moved).
474 """
475 if self.handle:
476 try:
477 # Bring link between oldSw-host down
Jon Hallefbd9792015-03-05 16:11:36 -0800478 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'"+ host +\
479 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800480 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800481 response = self.execute( cmd=cmd,
482 prompt="mininet>",
483 timeout=10 )
kelvin-onlaba1484582015-02-02 15:46:20 -0800484
485 # Determine hostintf and Oldswitchintf
486 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800487 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800488 print "cmd2= ", cmd
489 self.handle.sendline( cmd )
490 self.handle.expect( "mininet>" )
491
shahshreya73537862015-02-11 15:15:24 -0800492 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800493 cmd = "px ipaddr = hintf.IP()"
494 print "cmd3= ", cmd
495 self.handle.sendline( cmd )
496 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800497
498 cmd = "px macaddr = hintf.MAC()"
499 print "cmd3= ", cmd
500 self.handle.sendline( cmd )
501 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800502
503 # Detach interface between oldSw-host
504 cmd = "px " + oldSw + ".detach( sintf )"
505 print "cmd4= ", cmd
506 self.handle.sendline( cmd )
507 self.handle.expect( "mininet>" )
508
509 # Add link between host-newSw
510 cmd = "py net.addLink(" + host + "," + newSw + ")"
511 print "cmd5= ", cmd
512 self.handle.sendline( cmd )
513 self.handle.expect( "mininet>" )
514
515 # Determine hostintf and Newswitchintf
516 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800517 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800518 print "cmd6= ", cmd
519 self.handle.sendline( cmd )
520 self.handle.expect( "mininet>" )
521
522 # Attach interface between newSw-host
523 cmd = "px " + newSw + ".attach( sintf )"
524 print "cmd3= ", cmd
525 self.handle.sendline( cmd )
526 self.handle.expect( "mininet>" )
527
528 # Set ipaddress of the host-newSw interface
529 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
530 print "cmd7 = ", cmd
531 self.handle.sendline( cmd )
532 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800533
534 # Set macaddress of the host-newSw interface
535 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
536 print "cmd8 = ", cmd
537 self.handle.sendline( cmd )
538 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800539
540 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800541 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800542 self.handle.sendline( cmd )
543 self.handle.expect( "mininet>" )
544 print "output = ", self.handle.before
545
546 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800547 cmd = host + " ifconfig"
548 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800549 self.handle.sendline( cmd )
550 self.handle.expect( "mininet>" )
551 print "ifconfig o/p = ", self.handle.before
552
553 return main.TRUE
554 except pexpect.EOF:
555 main.log.error( self.name + ": EOF exception found" )
556 main.log.error( self.name + ": " + self.handle.before )
557 return main.FALSE
558
Jon Hall7eb38402015-01-08 17:19:54 -0800559 def changeIP( self, host, intf, newIP, newNetmask ):
560 """
561 Changes the ip address of a host on the fly
562 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800563 if self.handle:
564 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800565 cmd = host + " ifconfig " + intf + " " + \
566 newIP + " " + 'netmask' + " " + newNetmask
567 self.handle.sendline( cmd )
568 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800569 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800570 main.log.info( "response = " + response )
571 main.log.info(
572 "Ip of host " +
573 host +
574 " changed to new IP " +
575 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800576 return main.TRUE
577 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800578 main.log.error( self.name + ": EOF exception found" )
579 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800580 return main.FALSE
581
Jon Hall7eb38402015-01-08 17:19:54 -0800582 def changeDefaultGateway( self, host, newGW ):
583 """
584 Changes the default gateway of a host
585 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800586 if self.handle:
587 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800588 cmd = host + " route add default gw " + newGW
589 self.handle.sendline( cmd )
590 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800591 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800592 main.log.info( "response = " + response )
593 main.log.info(
594 "Default gateway of host " +
595 host +
596 " changed to " +
597 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800598 return main.TRUE
599 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800600 main.log.error( self.name + ": EOF exception found" )
601 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800602 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800603
Jon Hall7eb38402015-01-08 17:19:54 -0800604 def addStaticMACAddress( self, host, GW, macaddr ):
605 """
Jon Hallefbd9792015-03-05 16:11:36 -0800606 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800607 if self.handle:
608 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800609 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
610 cmd = host + " arp -s " + GW + " " + macaddr
611 self.handle.sendline( cmd )
612 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800613 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800614 main.log.info( "response = " + response )
615 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800616 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800617 GW +
618 " changed to " +
619 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800620 return main.TRUE
621 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800622 main.log.error( self.name + ": EOF exception found" )
623 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800624 return main.FALSE
625
Jon Hall7eb38402015-01-08 17:19:54 -0800626 def verifyStaticGWandMAC( self, host ):
627 """
628 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800629 if self.handle:
630 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800631 # h1 arp -an
632 cmd = host + " arp -an "
633 self.handle.sendline( cmd )
634 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800635 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800636 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800637 return main.TRUE
638 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800639 main.log.error( self.name + ": EOF exception found" )
640 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800641 return main.FALSE
642
Jon Hall7eb38402015-01-08 17:19:54 -0800643 def getMacAddress( self, host ):
644 """
645 Verifies the host's ip configured or not."""
646 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700647 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800648 response = self.execute(
649 cmd=host +
650 " ifconfig",
651 prompt="mininet>",
652 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800653 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800654 main.log.error( self.name + ": EOF exception found" )
655 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700656 main.cleanup()
657 main.exit()
adminbae64d82013-08-01 10:50:15 -0700658
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700659 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800660 macAddressSearch = re.search( pattern, response, re.I )
661 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800662 main.log.info(
663 self.name +
664 ": Mac-Address of Host " +
665 host +
666 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800667 macAddress )
668 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700669 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800670 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700671
Jon Hall7eb38402015-01-08 17:19:54 -0800672 def getInterfaceMACAddress( self, host, interface ):
673 """
674 Return the IP address of the interface on the given host"""
675 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700676 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800677 response = self.execute( cmd=host + " ifconfig " + interface,
678 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800679 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800680 main.log.error( self.name + ": EOF exception found" )
681 main.log.error( self.name + ": " + self.handle.before )
682 main.cleanup()
683 main.exit()
684
685 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800686 macAddressSearch = re.search( pattern, response, re.I )
687 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800688 main.log.info( "No mac address found in %s" % response )
689 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800690 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800691 main.log.info(
692 "Mac-Address of " +
693 host +
694 ":" +
695 interface +
696 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800697 macAddress )
698 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800699 else:
700 main.log.error( "Connection failed to the host" )
701
702 def getIPAddress( self, host ):
703 """
704 Verifies the host's ip configured or not."""
705 if self.handle:
706 try:
707 response = self.execute(
708 cmd=host +
709 " ifconfig",
710 prompt="mininet>",
711 timeout=10 )
712 except pexpect.EOF:
713 main.log.error( self.name + ": EOF exception found" )
714 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700715 main.cleanup()
716 main.exit()
adminbae64d82013-08-01 10:50:15 -0700717
718 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800719 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800720 main.log.info(
721 self.name +
722 ": IP-Address of Host " +
723 host +
724 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800725 ipAddressSearch.group( 1 ) )
726 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800727 else:
728 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800729
Jon Hall7eb38402015-01-08 17:19:54 -0800730 def getSwitchDPID( self, switch ):
731 """
732 return the datapath ID of the switch"""
733 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700734 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700735 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800736 response = self.execute(
737 cmd=cmd,
738 prompt="mininet>",
739 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800740 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800741 main.log.error( self.name + ": EOF exception found" )
742 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700743 main.cleanup()
744 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800745 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800746 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700747 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800748 main.log.info(
749 "Couldn't find DPID for switch %s, found: %s" %
750 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700751 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800752 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700753 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800754 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700755
Jon Hall7eb38402015-01-08 17:19:54 -0800756 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700757 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800758 self.handle.sendline( "" )
759 self.expect( "mininet>" )
760 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700761 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800762 response = self.execute(
763 cmd=cmd,
764 prompt="mininet>",
765 timeout=10 )
766 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700767 response = self.handle.before
768 return response
769 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800770 main.log.error( self.name + ": EOF exception found" )
771 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700772 main.cleanup()
773 main.exit()
774
Jon Hall7eb38402015-01-08 17:19:54 -0800775 def getInterfaces( self, node ):
776 """
777 return information dict about interfaces connected to the node"""
778 if self.handle:
779 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800780 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700781 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700782 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800783 response = self.execute(
784 cmd=cmd,
785 prompt="mininet>",
786 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800787 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800788 main.log.error( self.name + ": EOF exception found" )
789 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700790 main.cleanup()
791 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700792 return response
793 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800794 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700795
Jon Hall7eb38402015-01-08 17:19:54 -0800796 def dump( self ):
797 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700798 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800799 response = self.execute(
800 cmd='dump',
801 prompt='mininet>',
802 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800803 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800804 main.log.error( self.name + ": EOF exception found" )
805 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700806 main.cleanup()
807 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700808 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800809
Jon Hall7eb38402015-01-08 17:19:54 -0800810 def intfs( self ):
811 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700812 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800813 response = self.execute(
814 cmd='intfs',
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 Hall668ed802014-04-08 17:17:59 -0700822 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800823
Jon Hall7eb38402015-01-08 17:19:54 -0800824 def net( self ):
825 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700826 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800827 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800828 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800829 main.log.error( self.name + ": EOF exception found" )
830 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700831 main.cleanup()
832 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700833 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800834
835 def iperf( self, host1, host2 ):
836 main.log.info(
837 self.name +
838 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700839 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800840 cmd1 = 'iperf ' + host1 + " " + host2
841 self.handle.sendline( cmd1 )
842 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800843 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800844 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800845 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800846 return main.TRUE
847 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800848 main.log.error( self.name + ": iperf test failed" )
849 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800850 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800851 main.log.error( self.name + ": EOF exception found" )
852 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800853 main.cleanup()
854 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800855
Jon Hall7eb38402015-01-08 17:19:54 -0800856 def iperfudp( self ):
857 main.log.info(
858 self.name +
859 ": Simple iperf TCP test between two " +
860 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700861 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800862 response = self.execute(
863 cmd='iperfudp',
864 prompt='mininet>',
865 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800866 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800867 main.log.error( self.name + ": EOF exception found" )
868 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700869 main.cleanup()
870 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700871 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800872
Jon Hall7eb38402015-01-08 17:19:54 -0800873 def nodes( self ):
874 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700875 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800876 response = self.execute(
877 cmd='nodes',
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()
Jon Hall668ed802014-04-08 17:17:59 -0700885 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800886
Jon Hall7eb38402015-01-08 17:19:54 -0800887 def pingpair( self ):
888 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700889 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800890 response = self.execute(
891 cmd='pingpair',
892 prompt='mininet>',
893 timeout=20 )
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 Hallfbc828e2015-01-06 17:30:19 -0800899
Jon Hall7eb38402015-01-08 17:19:54 -0800900 if re.search( ',\s0\%\spacket\sloss', response ):
901 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800902 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700903 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800904 else:
905 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800906 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700907 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800908
Jon Hall7eb38402015-01-08 17:19:54 -0800909 def link( self, **linkargs ):
910 """
911 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800912 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800913 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
914 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
915 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
916 main.log.info(
917 "Bring link between '" +
918 end1 +
919 "' and '" +
920 end2 +
921 "' '" +
922 option +
923 "'" )
924 command = "link " + \
925 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -0700926 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800927 self.handle.sendline( command )
928 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800929 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800930 main.log.error( self.name + ": EOF exception found" )
931 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700932 main.cleanup()
933 main.exit()
adminbae64d82013-08-01 10:50:15 -0700934 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800935
Jon Hall7eb38402015-01-08 17:19:54 -0800936 def yank( self, **yankargs ):
937 """
938 yank a mininet switch interface to a host"""
939 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800940 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800941 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
942 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
943 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700944 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800945 response = self.execute(
946 cmd=command,
947 prompt="mininet>",
948 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800949 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800950 main.log.error( self.name + ": EOF exception found" )
951 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700952 main.cleanup()
953 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700954 return main.TRUE
955
Jon Hall7eb38402015-01-08 17:19:54 -0800956 def plug( self, **plugargs ):
957 """
958 plug the yanked mininet switch interface to a switch"""
959 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800960 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800961 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
962 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
963 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700964 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800965 response = self.execute(
966 cmd=command,
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()
adminbae64d82013-08-01 10:50:15 -0700974 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800975
Jon Hall7eb38402015-01-08 17:19:54 -0800976 def dpctl( self, **dpctlargs ):
977 """
978 Run dpctl command on all switches."""
979 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800980 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800981 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
982 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
983 command = "dpctl " + cmd + " " + str( cmdargs )
984 try:
985 response = self.execute(
986 cmd=command,
987 prompt="mininet>",
988 timeout=10 )
989 except pexpect.EOF:
990 main.log.error( self.name + ": EOF exception found" )
991 main.log.error( self.name + ": " + self.handle.before )
992 main.cleanup()
993 main.exit()
994 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800995
kelvin-onlabd3b64892015-01-20 13:26:24 -0800996 def getVersion( self ):
Jon Hallff6b4b22015-02-23 09:25:15 -0800997 #FIXME: What uses this? This should be refactored to get
998 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -0800999 fileInput = path + '/lib/Mininet/INSTALL'
1000 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001001 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001002 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001003 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001004 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001005 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001006 return version
adminbae64d82013-08-01 10:50:15 -07001007
kelvin-onlabd3b64892015-01-20 13:26:24 -08001008 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001009 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001010 Parameters:
1011 sw: The name of an OVS switch. Example "s1"
1012 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001013 The output of the command from the mininet cli
1014 or main.FALSE on timeout"""
1015 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001016 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001017 response = self.execute(
1018 cmd=command,
1019 prompt="mininet>",
1020 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001021 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001022 return response
admin2a9548d2014-06-17 14:08:07 -07001023 else:
1024 return main.FALSE
1025 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001026 main.log.error( self.name + ": EOF exception found" )
1027 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001028 main.cleanup()
1029 main.exit()
adminbae64d82013-08-01 10:50:15 -07001030
kelvin-onlabd3b64892015-01-20 13:26:24 -08001031 def assignSwController( self, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001032 """
1033 count is only needed if there is more than 1 controller"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001034 args = utilities.parse_args( [ "COUNT" ], **kwargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001035 count = args[ "COUNT" ] if args != {} else 1
Jon Hallf89c8552014-04-02 13:14:06 -07001036
1037 argstring = "SW"
Jon Hall7eb38402015-01-08 17:19:54 -08001038 for j in range( count ):
1039 argstring = argstring + ",IP" + \
1040 str( j + 1 ) + ",PORT" + str( j + 1 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001041 args = utilities.parse_args( argstring.split( "," ), **kwargs )
Jon Hallf89c8552014-04-02 13:14:06 -07001042
Jon Hall7eb38402015-01-08 17:19:54 -08001043 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1044 ptcpA = int( args[ "PORT1" ] ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001045 int( sw ) if args[ "PORT1" ] is not None else ""
Jon Hall7eb38402015-01-08 17:19:54 -08001046 ptcpB = "ptcp:" + str( ptcpA ) if ptcpA != "" else ""
Jon Hallfbc828e2015-01-06 17:30:19 -08001047
Jon Hall7eb38402015-01-08 17:19:54 -08001048 command = "sh ovs-vsctl set-controller s" + \
1049 str( sw ) + " " + ptcpB + " "
1050 for j in range( count ):
1051 i = j + 1
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001052 args = utilities.parse_args(
Jon Hall7eb38402015-01-08 17:19:54 -08001053 [ "IP" + str( i ), "PORT" + str( i ) ], **kwargs )
1054 ip = args[
1055 "IP" +
1056 str( i ) ] if args[
1057 "IP" +
1058 str( i ) ] is not None else ""
1059 port = args[
1060 "PORT" +
1061 str( i ) ] if args[
1062 "PORT" +
1063 str( i ) ] is not None else ""
1064 tcp = "tcp:" + str( ip ) + ":" + str( port ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001065 " " if ip != "" else ""
Jon Hallf89c8552014-04-02 13:14:06 -07001066 command = command + tcp
Jon Hall6094a362014-04-11 14:46:56 -07001067 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001068 self.execute( cmd=command, prompt="mininet>", timeout=5 )
Jon Hall6094a362014-04-11 14:46:56 -07001069 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001070 main.log.error( self.name + ": EOF exception found" )
1071 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001072 main.cleanup()
1073 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001074 except Exception:
1075 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall6094a362014-04-11 14:46:56 -07001076 main.cleanup()
1077 main.exit()
adminbae64d82013-08-01 10:50:15 -07001078
kelvin-onlabd3b64892015-01-20 13:26:24 -08001079 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001080 """
1081 Removes the controller target from sw"""
1082 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001083 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001084 response = self.execute(
1085 cmd=command,
1086 prompt="mininet>",
1087 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001088 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001089 main.log.error( self.name + ": EOF exception found" )
1090 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001091 main.cleanup()
1092 main.exit()
1093 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001094 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001095
kelvin-onlabd3b64892015-01-20 13:26:24 -08001096 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001097 """
Jon Hallb1290e82014-11-18 16:17:48 -05001098 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001099 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001100 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001101 NOTE: cannot currently specify what type of switch
1102 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001103 sw = name of the new switch as a string
1104 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001105 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001106 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001107 """
1108 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001109 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001110 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001111 response = self.execute(
1112 cmd=command,
1113 prompt="mininet>",
1114 timeout=10 )
1115 if re.search( "already exists!", response ):
1116 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001117 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001118 elif re.search( "Error", response ):
1119 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001120 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001121 elif re.search( "usage:", response ):
1122 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001123 return main.FALSE
1124 else:
1125 return main.TRUE
1126 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001127 main.log.error( self.name + ": EOF exception found" )
1128 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001129 main.cleanup()
1130 main.exit()
1131
kelvin-onlabd3b64892015-01-20 13:26:24 -08001132 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001133 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001134 delete a switch from the mininet topology
1135 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001136 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001137 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001138 sw = name of the switch as a string
1139 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001140 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001141 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001142 response = self.execute(
1143 cmd=command,
1144 prompt="mininet>",
1145 timeout=10 )
1146 if re.search( "no switch named", response ):
1147 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001148 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001149 elif re.search( "Error", response ):
1150 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001151 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001152 elif re.search( "usage:", response ):
1153 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001154 return main.FALSE
1155 else:
1156 return main.TRUE
1157 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001158 main.log.error( self.name + ": EOF exception found" )
1159 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001160 main.cleanup()
1161 main.exit()
1162
kelvin-onlabd3b64892015-01-20 13:26:24 -08001163 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001164 """
1165 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001166 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001167 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001168 NOTE: cannot currently specify what type of link
1169 required params:
1170 node1 = the string node name of the first endpoint of the link
1171 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001172 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001173 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001174 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001175 response = self.execute(
1176 cmd=command,
1177 prompt="mininet>",
1178 timeout=10 )
1179 if re.search( "doesnt exist!", response ):
1180 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001181 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001182 elif re.search( "Error", response ):
1183 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001184 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001185 elif re.search( "usage:", response ):
1186 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001187 return main.FALSE
1188 else:
1189 return main.TRUE
1190 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001191 main.log.error( self.name + ": EOF exception found" )
1192 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001193 main.cleanup()
1194 main.exit()
1195
kelvin-onlabd3b64892015-01-20 13:26:24 -08001196 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001197 """
1198 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001199 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001200 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001201 required params:
1202 node1 = the string node name of the first endpoint of the link
1203 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001204 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001205 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001206 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001207 response = self.execute(
1208 cmd=command,
1209 prompt="mininet>",
1210 timeout=10 )
1211 if re.search( "no node named", response ):
1212 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001213 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001214 elif re.search( "Error", response ):
1215 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001216 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001217 elif re.search( "usage:", response ):
1218 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001219 return main.FALSE
1220 else:
1221 return main.TRUE
1222 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001223 main.log.error( self.name + ": EOF exception found" )
1224 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001225 main.cleanup()
1226 main.exit()
1227
kelvin-onlabd3b64892015-01-20 13:26:24 -08001228 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001229 """
Jon Hallb1290e82014-11-18 16:17:48 -05001230 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001231 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001232 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001233 NOTE: cannot currently specify what type of host
1234 required params:
1235 hostname = the string hostname
1236 optional key-value params
1237 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001238 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001239 """
1240 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001241 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001242 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001243 response = self.execute(
1244 cmd=command,
1245 prompt="mininet>",
1246 timeout=10 )
1247 if re.search( "already exists!", response ):
1248 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001249 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001250 elif re.search( "doesnt exists!", response ):
1251 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001252 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001253 elif re.search( "Error", response ):
1254 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001255 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001256 elif re.search( "usage:", response ):
1257 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001258 return main.FALSE
1259 else:
1260 return main.TRUE
1261 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 Hallb1290e82014-11-18 16:17:48 -05001264 main.cleanup()
1265 main.exit()
1266
kelvin-onlabd3b64892015-01-20 13:26:24 -08001267 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001268 """
1269 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001270 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001271 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001272 NOTE: this uses a custom mn function
1273 required params:
1274 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001275 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001276 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001277 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001278 response = self.execute(
1279 cmd=command,
1280 prompt="mininet>",
1281 timeout=10 )
1282 if re.search( "no host named", response ):
1283 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001284 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001285 elif re.search( "Error", response ):
1286 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001287 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001288 elif re.search( "usage:", response ):
1289 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001290 return main.FALSE
1291 else:
1292 return main.TRUE
1293 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001294 main.log.error( self.name + ": EOF exception found" )
1295 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001296 main.cleanup()
1297 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001298
Jon Hall7eb38402015-01-08 17:19:54 -08001299 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001300 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001301 Called at the end of the test to stop the mininet and
1302 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001303 """
1304 self.handle.sendline('')
Jon Halld61331b2015-02-17 16:35:47 -08001305 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Hallefbd9792015-03-05 16:11:36 -08001306 timeout=2)
kelvin-onlaba1484582015-02-02 15:46:20 -08001307 if i == 0:
1308 self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001309 elif i == 1:
1310 return main.TRUE
1311 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001312 # print "Disconnecting Mininet"
1313 if self.handle:
1314 self.handle.sendline( "exit" )
1315 self.handle.expect( "exit" )
1316 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001317 else:
1318 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001319 return response
1320
Hari Krishnab35c6d02015-03-18 11:13:51 -07001321 def stopNet( self, fileName = "", timeout=5):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001322 """
Jon Hall21270ac2015-02-16 17:59:55 -08001323 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001324 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001325 main.FALSE if the pexpect handle does not exist.
1326
Jon Halld61331b2015-02-17 16:35:47 -08001327 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001328 """
Jon Hall21270ac2015-02-16 17:59:55 -08001329
Jon Halld61331b2015-02-17 16:35:47 -08001330 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001331 response = ''
1332 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001333 try:
kelvin-onlab26bc17f2015-02-06 14:08:59 -08001334 self.handle.sendline("")
kelvin-onlab56a3f462015-02-06 14:04:43 -08001335 i = self.handle.expect( [ 'mininet>',
1336 '\$',
1337 pexpect.EOF,
1338 pexpect.TIMEOUT ],
1339 timeout )
1340 if i == 0:
1341 main.log.info( "Exiting mininet..." )
1342
Jon Hall7eb38402015-01-08 17:19:54 -08001343 response = self.execute(
1344 cmd="exit",
1345 prompt="(.*)",
1346 timeout=120 )
Jon Halld61331b2015-02-17 16:35:47 -08001347 main.log.info( self.name + ": Stopped")
Jon Hall7eb38402015-01-08 17:19:54 -08001348 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001349 response = main.TRUE
Hari Krishnab35c6d02015-03-18 11:13:51 -07001350
kelvin-onlab56a3f462015-02-06 14:04:43 -08001351 if i == 1:
1352 main.log.info( " Mininet trying to exit while not " +
1353 "in the mininet prompt" )
1354 elif i == 2:
1355 main.log.error( "Something went wrong exiting mininet" )
1356 elif i == 3: # timeout
1357 main.log.error( "Something went wrong exiting mininet " +
1358 "TIMEOUT" )
1359
Hari Krishnab35c6d02015-03-18 11:13:51 -07001360 if fileName:
1361 self.handle.sendline("")
1362 self.handle.expect('\$')
1363 self.handle.sendline("sudo kill -9 \`ps -ef | grep \""+ fileName +"\" | grep -v grep | awk '{print $2}'\`")
Jon Hallfbc828e2015-01-06 17:30:19 -08001364 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001365 main.log.error( self.name + ": EOF exception found" )
1366 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001367 main.cleanup()
1368 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001369 else:
1370 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001371 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001372 return response
1373
Jon Hall7eb38402015-01-08 17:19:54 -08001374 def arping( self, src, dest, destmac ):
1375 self.handle.sendline( '' )
1376 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001377
Jon Hall7eb38402015-01-08 17:19:54 -08001378 self.handle.sendline( src + ' arping ' + dest )
admin07529932013-11-22 14:58:28 -08001379 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001380 self.handle.expect( [ destmac, pexpect.EOF, pexpect.TIMEOUT ] )
1381 main.log.info( self.name + ": ARP successful" )
1382 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001383 return main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -08001384 except Exception:
Jon Hall7eb38402015-01-08 17:19:54 -08001385 main.log.warn( self.name + ": ARP FAILURE" )
1386 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001387 return main.FALSE
1388
Jon Hall7eb38402015-01-08 17:19:54 -08001389 def decToHex( self, num ):
1390 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001391
Jon Hall7eb38402015-01-08 17:19:54 -08001392 def getSwitchFlowCount( self, switch ):
1393 """
1394 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001395 if self.handle:
1396 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1397 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001398 response = self.execute(
1399 cmd=cmd,
1400 prompt="mininet>",
1401 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001402 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001403 main.log.error( self.name + ": EOF exception found" )
1404 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001405 main.cleanup()
1406 main.exit()
1407 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001408 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001409 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001410 main.log.info(
1411 "Couldn't find flows on switch %s, found: %s" %
1412 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001413 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001414 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001415 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001416 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001417
kelvin-onlabd3b64892015-01-20 13:26:24 -08001418 def checkFlows( self, sw, dumpFormat=None ):
1419 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001420 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001421 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001422 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001423 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001424 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001425 response = self.execute(
1426 cmd=command,
1427 prompt="mininet>",
1428 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001429 return response
1430 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001431 main.log.error( self.name + ": EOF exception found" )
1432 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001433 main.cleanup()
1434 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001435
kelvin-onlabd3b64892015-01-20 13:26:24 -08001436 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001437 """
Jon Hallefbd9792015-03-05 16:11:36 -08001438 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001439 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001440 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001441 self.handle.sendline( "" )
1442 self.handle.expect( "mininet>" )
1443 self.handle.sendline(
1444 "sh sudo tcpdump -n -i " +
1445 intf +
1446 " " +
1447 port +
1448 " -w " +
1449 filename.strip() +
1450 " &" )
1451 self.handle.sendline( "" )
1452 i = self.handle.expect( [ 'No\ssuch\device',
1453 'listening\son',
1454 pexpect.TIMEOUT,
1455 "mininet>" ],
1456 timeout=10 )
1457 main.log.warn( self.handle.before + self.handle.after )
1458 self.handle.sendline( "" )
1459 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001460 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001461 main.log.error(
1462 self.name +
1463 ": tcpdump - No such device exists. " +
1464 "tcpdump attempted on: " +
1465 intf )
admin2a9548d2014-06-17 14:08:07 -07001466 return main.FALSE
1467 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001468 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001469 return main.TRUE
1470 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001471 main.log.error(
1472 self.name +
1473 ": tcpdump command timed out! Check interface name," +
1474 " given interface was: " +
1475 intf )
admin2a9548d2014-06-17 14:08:07 -07001476 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001477 elif i == 3:
1478 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001479 return main.TRUE
1480 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001481 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001482 return main.FALSE
1483 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001484 main.log.error( self.name + ": EOF exception found" )
1485 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001486 main.cleanup()
1487 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001488 except Exception:
1489 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001490 main.cleanup()
1491 main.exit()
1492
kelvin-onlabd3b64892015-01-20 13:26:24 -08001493 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001494 """
1495 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001496 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001497 self.handle.sendline( "sh sudo pkill tcpdump" )
1498 self.handle.expect( "mininet>" )
1499 self.handle.sendline( "" )
1500 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001501 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001502 main.log.error( self.name + ": EOF exception found" )
1503 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001504 main.cleanup()
1505 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001506 except Exception:
1507 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001508 main.cleanup()
1509 main.exit()
1510
kelvin-onlabd3b64892015-01-20 13:26:24 -08001511 def compareSwitches( self, topo, switchesJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001512 """
1513 Compare mn and onos switches
1514 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001515 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001516
Jon Hall7eb38402015-01-08 17:19:54 -08001517 This uses the sts TestONTopology object"""
kelvin-onlabd3b64892015-01-20 13:26:24 -08001518 # main.log.debug( "Switches_json string: ", switchesJson )
Jon Hall7eb38402015-01-08 17:19:54 -08001519 output = { "switches": [] }
1520 # iterate through the MN topology and pull out switches and and port
1521 # info
1522 for switch in topo.graph.switches:
Jon Hall3d87d502014-10-17 18:37:42 -04001523 ports = []
1524 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001525 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001526 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001527 'name': port.name } )
1528 output[ 'switches' ].append( {
1529 "name": switch.name,
1530 "dpid": str( switch.dpid ).zfill( 16 ),
1531 "ports": ports } )
Jon Hall3d87d502014-10-17 18:37:42 -04001532
Jon Hall7eb38402015-01-08 17:19:54 -08001533 # print "mn"
1534 # print json.dumps( output,
Jon Hallff6b4b22015-02-23 09:25:15 -08001535 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001536 # indent=4,
1537 # separators=( ',', ': ' ) )
1538 # print "onos"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001539 # print json.dumps( switchesJson,
Jon Hallff6b4b22015-02-23 09:25:15 -08001540 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001541 # indent=4,
1542 # separators=( ',', ': ' ) )
Jon Hall3d87d502014-10-17 18:37:42 -04001543
1544 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001545 mnDPIDs = []
1546 for switch in output[ 'switches' ]:
1547 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001548 mnDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001549 # print "List of Mininet switch DPID's"
1550 # print mnDPIDs
kelvin-onlabd3b64892015-01-20 13:26:24 -08001551 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001552 main.log.error(
1553 self.name +
1554 ".compare_switches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001555 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001556 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001557 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001558 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001559 if switch[ 'available' ]:
1560 onosDPIDs.append(
1561 switch[ 'id' ].replace(
1562 ":",
1563 '' ).replace(
1564 "of",
1565 '' ).lower() )
1566 # else:
1567 # print "Switch is unavailable:"
1568 # print switch
Jon Hall3d87d502014-10-17 18:37:42 -04001569 onosDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001570 # print "List of ONOS switch DPID's"
1571 # print onosDPIDs
Jon Hall3d87d502014-10-17 18:37:42 -04001572
Jon Hall7eb38402015-01-08 17:19:54 -08001573 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001574 switchResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001575 main.log.report( "Switches in MN but not in ONOS:" )
1576 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
1577 main.log.report( str( list1 ) )
1578 main.log.report( "Switches in ONOS but not in MN:" )
1579 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
kelvin-onlabedcff052015-01-16 12:53:55 -08001580 main.log.report( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001581 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001582 switchResults = main.TRUE
1583 return switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001584
kelvin-onlabd3b64892015-01-20 13:26:24 -08001585 def comparePorts( self, topo, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001586 """
Jon Hall72cf1dc2014-10-20 21:04:50 -04001587 Compare mn and onos ports
1588 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001589 portsJson: parsed json object from the onos ports api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001590
Jon Hallfbc828e2015-01-06 17:30:19 -08001591 Dependencies:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001592 1. This uses the sts TestONTopology object
1593 2. numpy - "sudo pip install numpy"
1594
Jon Hall7eb38402015-01-08 17:19:54 -08001595 """
1596 # FIXME: this does not look for extra ports in ONOS, only checks that
1597 # ONOS has what is in MN
Jon Hall72cf1dc2014-10-20 21:04:50 -04001598 from numpy import uint64
kelvin-onlabd3b64892015-01-20 13:26:24 -08001599 portsResults = main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001600 output = { "switches": [] }
1601 # iterate through the MN topology and pull out switches and and port
1602 # info
1603 for switch in topo.graph.switches:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001604 ports = []
1605 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001606 # print port.hw_addr.toStr( separator='' )
Jon Hallefbd9792015-03-05 16:11:36 -08001607 tmpPort = { 'of_port': port.port_no,
1608 'mac': str( port.hw_addr ).replace( '\'', '' ),
1609 'name': port.name,
1610 'enabled': port.enabled }
Jon Hall39f29df2014-11-04 19:30:21 -05001611
kelvin-onlabd3b64892015-01-20 13:26:24 -08001612 ports.append( tmpPort )
Jon Hallefbd9792015-03-05 16:11:36 -08001613 tmpSwitch = { 'name': switch.name,
1614 'dpid': str( switch.dpid ).zfill( 16 ),
1615 'ports': ports }
Jon Hall39f29df2014-11-04 19:30:21 -05001616
kelvin-onlabd3b64892015-01-20 13:26:24 -08001617 output[ 'switches' ].append( tmpSwitch )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001618
Jon Hall7eb38402015-01-08 17:19:54 -08001619 # PORTS
kelvin-onlabd3b64892015-01-20 13:26:24 -08001620 for mnSwitch in output[ 'switches' ]:
1621 mnPorts = []
1622 onosPorts = []
1623 switchResult = main.TRUE
1624 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001625 if port[ 'enabled' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001626 mnPorts.append( port[ 'of_port' ] )
1627 for onosSwitch in portsJson:
Jon Hall7eb38402015-01-08 17:19:54 -08001628 # print "Iterating through a new switch as seen by ONOS"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001629 # print onosSwitch
1630 if onosSwitch[ 'device' ][ 'available' ]:
1631 if onosSwitch[ 'device' ][ 'id' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001632 ':',
1633 '' ).replace(
1634 "of",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001635 '' ) == mnSwitch[ 'dpid' ]:
1636 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001637 if port[ 'isEnabled' ]:
1638 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001639 # onosPorts.append( 'local' )
1640 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001641 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001642 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001643 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001644 mnPorts.sort( key=float )
1645 onosPorts.sort( key=float )
1646 # print "\nPorts for Switch %s:" % ( mnSwitch[ 'name' ] )
1647 # print "\tmn_ports[] = ", mnPorts
1648 # print "\tonos_ports[] = ", onosPorts
1649 mnPortsLog = mnPorts
1650 onosPortsLog = onosPorts
1651 mnPorts = [ x for x in mnPorts ]
1652 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001653
Jon Hall7eb38402015-01-08 17:19:54 -08001654 # TODO: handle other reserved port numbers besides LOCAL
1655 # NOTE: Reserved ports
1656 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1657 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001658 for mnPort in mnPortsLog:
1659 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001660 # don't set results to true here as this is just one of
1661 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001662 mnPorts.remove( mnPort )
1663 onosPorts.remove( mnPort )
Jon Hall7eb38402015-01-08 17:19:54 -08001664 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001665 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001666 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001667 if 65534 in mnPorts:
1668 mnPorts.remove( 65534 )
1669 if long( uint64( -2 ) ) in onosPorts:
1670 onosPorts.remove( long( uint64( -2 ) ) )
1671 if len( mnPorts ): # the ports of this switch don't match
1672 switchResult = main.FALSE
1673 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1674 if len( onosPorts ): # the ports of this switch don't match
1675 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001676 main.log.warn(
1677 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001678 str( onosPorts ) )
1679 if switchResult == main.FALSE:
Jon Hall7eb38402015-01-08 17:19:54 -08001680 main.log.report(
1681 "The list of ports for switch %s(%s) does not match:" %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001682 ( mnSwitch[ 'name' ], mnSwitch[ 'dpid' ] ) )
1683 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1684 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1685 portsResults = portsResults and switchResult
1686 return portsResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001687
kelvin-onlabd3b64892015-01-20 13:26:24 -08001688 def compareLinks( self, topo, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001689 """
1690 Compare mn and onos links
1691 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001692 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001693
Jon Hall7eb38402015-01-08 17:19:54 -08001694 This uses the sts TestONTopology object"""
1695 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08001696 # ONOS has what is in MN
Jon Hall7eb38402015-01-08 17:19:54 -08001697 output = { "switches": [] }
kelvin-onlabd3b64892015-01-20 13:26:24 -08001698 onos = linksJson
Jon Hall7eb38402015-01-08 17:19:54 -08001699 # iterate through the MN topology and pull out switches and and port
1700 # info
1701 for switch in topo.graph.switches:
Jon Hall38481722014-11-04 16:50:05 -05001702 # print "Iterating though switches as seen by Mininet"
1703 # print switch
Jon Hall72cf1dc2014-10-20 21:04:50 -04001704 ports = []
1705 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001706 # print port.hw_addr.toStr( separator='' )
1707 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001708 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001709 'name': port.name } )
1710 output[ 'switches' ].append( {
1711 "name": switch.name,
1712 "dpid": str( switch.dpid ).zfill( 16 ),
1713 "ports": ports } )
1714 # LINKS
Jon Hall72cf1dc2014-10-20 21:04:50 -04001715
kelvin-onlabd3b64892015-01-20 13:26:24 -08001716 mnLinks = [
kelvin-onlab9592d132015-01-20 17:18:02 -08001717 link for link in topo.patch_panel.network_links if (
Jon Hall7eb38402015-01-08 17:19:54 -08001718 link.port1.enabled and link.port2.enabled ) ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08001719 if 2 * len( mnLinks ) == len( onos ):
1720 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001721 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001722 linkResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001723 main.log.report(
Jon Hall328ddca2015-01-28 15:57:15 -08001724 "Mininet has " + str( len( mnLinks ) ) +
1725 " bidirectional links and ONOS has " +
1726 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001727
Jon Hall7eb38402015-01-08 17:19:54 -08001728 # iterate through MN links and check if an ONOS link exists in
1729 # both directions
1730 # NOTE: Will currently only show mn links as down if they are
1731 # cut through STS. We can either do everything through STS or
kelvin-onlabd3b64892015-01-20 13:26:24 -08001732 # wait for upNetworkLinks and downNetworkLinks to be
Jon Hall7eb38402015-01-08 17:19:54 -08001733 # fully implemented.
kelvin-onlabd3b64892015-01-20 13:26:24 -08001734 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08001735 # print "Link: %s" % link
1736 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04001737 node1 = None
1738 port1 = None
1739 node2 = None
1740 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08001741 firstDir = main.FALSE
1742 secondDir = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001743 for switch in output[ 'switches' ]:
1744 # print "Switch: %s" % switch[ 'name' ]
1745 if switch[ 'name' ] == link.node1.name:
1746 node1 = switch[ 'dpid' ]
1747 for port in switch[ 'ports' ]:
1748 if str( port[ 'name' ] ) == str( link.port1 ):
1749 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001750 if node1 is not None and node2 is not None:
1751 break
Jon Hall7eb38402015-01-08 17:19:54 -08001752 if switch[ 'name' ] == link.node2.name:
1753 node2 = switch[ 'dpid' ]
1754 for port in switch[ 'ports' ]:
1755 if str( port[ 'name' ] ) == str( link.port2 ):
1756 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001757 if node1 is not None and node2 is not None:
1758 break
1759
kelvin-onlabd3b64892015-01-20 13:26:24 -08001760 for onosLink in onos:
1761 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001762 ":",
1763 '' ).replace(
1764 "of",
1765 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001766 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001767 ":",
1768 '' ).replace(
1769 "of",
1770 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001771 onosPort1 = onosLink[ 'src' ][ 'port' ]
1772 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001773
Jon Hall72cf1dc2014-10-20 21:04:50 -04001774 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08001775 if str( onosNode1 ) == str( node1 ) and str(
1776 onosNode2 ) == str( node2 ):
1777 if int( onosPort1 ) == int( port1 ) and int(
1778 onosPort2 ) == int( port2 ):
1779 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001780 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001781 main.log.warn(
1782 'The port numbers do not match for ' +
1783 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001784 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001785 'link %s/%s -> %s/%s' %
1786 ( node1,
1787 port1,
1788 node2,
1789 port2 ) +
1790 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001791 ( onosNode1,
1792 onosPort1,
1793 onosNode2,
1794 onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001795
1796 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08001797 elif ( str( onosNode1 ) == str( node2 ) and
1798 str( onosNode2 ) == str( node1 ) ):
1799 if ( int( onosPort1 ) == int( port2 )
1800 and int( onosPort2 ) == int( port1 ) ):
1801 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001802 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001803 main.log.warn(
1804 'The port numbers do not match for ' +
1805 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001806 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001807 'link %s/%s -> %s/%s' %
1808 ( node2,
1809 port2,
1810 node1,
1811 port1 ) +
1812 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001813 ( onosNode2,
1814 onosPort2,
1815 onosNode1,
1816 onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001817 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04001818 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08001819 if not firstDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001820 main.log.report(
1821 'ONOS does not have the link %s/%s -> %s/%s' %
1822 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001823 if not secondDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001824 main.log.report(
1825 'ONOS does not have the link %s/%s -> %s/%s' %
1826 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001827 linkResults = linkResults and firstDir and secondDir
1828 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001829
Jon Hallff6b4b22015-02-23 09:25:15 -08001830 def compareHosts( self, topo, hostsJson ):
1831 """
1832 Compare mn and onos Hosts.
1833 Since Mininet hosts are quiet, ONOS will only know of them when they
1834 speak. For this reason, we will only check that the hosts in ONOS
1835 stores are in Mininet, and not vice versa.
1836 topo: sts TestONTopology object
1837 hostsJson: parsed json object from the onos hosts api
1838
1839 This uses the sts TestONTopology object"""
1840 import json
1841 hostResults = main.TRUE
1842 hosts = []
1843 # iterate through the MN topology and pull out hosts
1844 for mnHost in topo.graph.hosts:
1845 interfaces = []
1846 for intf in mnHost.interfaces:
1847 interfaces.append( {
1848 "name": intf.name, # str
1849 "ips": [ str( ip ) for ip in intf.ips ], # list of IPAddrs
1850 # hw_addr is of type EthAddr, Not JSON serializable
1851 "hw_addr": str( intf.hw_addr ) } )
1852 hosts.append( {
1853 "name": mnHost.name, # str
1854 "interfaces": interfaces } ) # list
1855 for onosHost in hostsJson:
1856 onosMAC = onosHost[ 'mac' ].lower()
1857 match = False
1858 for mnHost in hosts:
1859 for mnIntf in mnHost[ 'interfaces' ]:
1860 if onosMAC == mnIntf[ 'hw_addr' ].lower() :
1861 match = True
1862 for ip in mnIntf[ 'ips' ]:
1863 if ip in onosHost[ 'ips' ]:
1864 pass # all is well
1865 else:
1866 # misssing ip
1867 main.log.error( "ONOS host " + onosHost[ 'id' ]
1868 + " has a different IP than " +
1869 "the Mininet host." )
1870 output = json.dumps(
1871 onosHost,
1872 sort_keys=True,
1873 indent=4,
1874 separators=( ',', ': ' ) )
1875 main.log.info( output )
1876 hostResults = main.FALSE
1877 if not match:
1878 hostResults = main.FALSE
1879 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
1880 "corresponding Mininet host." )
1881 output = json.dumps( onosHost,
1882 sort_keys=True,
1883 indent=4,
1884 separators=( ',', ': ' ) )
1885 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08001886 return hostResults
1887
kelvin-onlabd3b64892015-01-20 13:26:24 -08001888 def getHosts( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08001889 """
1890 Returns a list of all hosts
1891 Don't ask questions just use it"""
1892 self.handle.sendline( "" )
1893 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001894
Jon Hall7eb38402015-01-08 17:19:54 -08001895 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
1896 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001897
kelvin-onlabd3b64892015-01-20 13:26:24 -08001898 handlePy = self.handle.before
1899 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
1900 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07001901
Jon Hall7eb38402015-01-08 17:19:54 -08001902 self.handle.sendline( "" )
1903 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001904
kelvin-onlabd3b64892015-01-20 13:26:24 -08001905 hostStr = handlePy.replace( "]", "" )
1906 hostStr = hostStr.replace( "'", "" )
1907 hostStr = hostStr.replace( "[", "" )
1908 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001909
kelvin-onlabd3b64892015-01-20 13:26:24 -08001910 return hostList
adminbae64d82013-08-01 10:50:15 -07001911
Jon Hall7eb38402015-01-08 17:19:54 -08001912 def update( self ):
1913 """
1914 updates the port address and status information for
1915 each port in mn"""
1916 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08001917 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05001918 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001919 self.handle.sendline( "" )
1920 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001921
Jon Hall7eb38402015-01-08 17:19:54 -08001922 self.handle.sendline( "update" )
1923 self.handle.expect( "update" )
1924 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001925
Jon Hall7eb38402015-01-08 17:19:54 -08001926 self.handle.sendline( "" )
1927 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001928
Jon Hallb1290e82014-11-18 16:17:48 -05001929 return main.TRUE
1930 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001931 main.log.error( self.name + ": EOF exception found" )
1932 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001933 main.cleanup()
1934 main.exit()
1935
adminbae64d82013-08-01 10:50:15 -07001936if __name__ != "__main__":
1937 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07001938 sys.modules[ __name__ ] = MininetCliDriver()