blob: 23acb4686166f3b77d6a7b064e23c0789301b2b0 [file] [log] [blame]
kaouthera3f13ca22015-05-05 15:01:41 -07001
adminbae64d82013-08-01 10:50:15 -07002#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08003"""
adminbae64d82013-08-01 10:50:15 -07004Created on 26-Oct-2012
5
Jon Hallbe6dfc42015-01-12 17:37:25 -08006author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07007
8
Jon Hall7eb38402015-01-08 17:19:54 -08009TestON is free software: you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation, either version 2 of the License, or
12( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070013
Jon Hall7eb38402015-01-08 17:19:54 -080014TestON is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070018
Jon Hall7eb38402015-01-08 17:19:54 -080019You should have received a copy of the GNU General Public License
20along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070021
Jon Hallb87f3db2015-07-06 03:10:27 -070022
Jon Hallbe6dfc42015-01-12 17:37:25 -080023MininetCliDriver is the basic driver which will handle the Mininet functions
24
Jon Hallb87f3db2015-07-06 03:10:27 -070025Some functions rely on STS module. To install this,
26 git clone https://github.com/jhall11/sts.git
27
Jon Hallbe6dfc42015-01-12 17:37:25 -080028Some functions rely on a modified version of Mininet. These functions
29should all be noted in the comments. To get this MN version run these commands
30from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080031 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080032 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080033 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080034 git pull
35
Jon Hall272a4db2015-01-12 17:43:48 -080036
37 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080038changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070039import pexpect
adminbae64d82013-08-01 10:50:15 -070040import re
41import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070042import types
Jon Hall7eb38402015-01-08 17:19:54 -080043sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040044from math import pow
adminbae64d82013-08-01 10:50:15 -070045from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070046
Jon Hall7eb38402015-01-08 17:19:54 -080047
kelvin-onlab50907142015-04-01 13:37:45 -070048class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080049
50 """
51 MininetCliDriver is the basic driver which will handle
52 the Mininet functions"""
53 def __init__( self ):
54 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070055 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080056 self.name = None
Jon Hall7eb38402015-01-08 17:19:54 -080057 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070058 self.flag = 0
59
Jon Hall7eb38402015-01-08 17:19:54 -080060 def connect( self, **connectargs ):
61 """
62 Here the main is the TestON instance after creating
63 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080064 try:
65 for key in connectargs:
66 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080067
kelvin-onlaba1484582015-02-02 15:46:20 -080068 self.name = self.options[ 'name' ]
69 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070070 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080071 self ).connect(
72 user_name=self.user_name,
73 ip_address=self.ip_address,
74 port=None,
75 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080076
kelvin-onlaba1484582015-02-02 15:46:20 -080077 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080078 main.log.info( "Connection successful to the host " +
79 self.user_name +
80 "@" +
81 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080082 return main.TRUE
83 else:
84 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080085 self.user_name +
86 "@" +
87 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -080088 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -080089 return main.FALSE
90 except pexpect.EOF:
91 main.log.error( self.name + ": EOF exception found" )
92 main.log.error( self.name + ": " + self.handle.before )
93 main.cleanup()
94 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -080095 except Exception:
96 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -080097 main.cleanup()
98 main.exit()
99
kelvin-onlab10e8d392015-06-03 13:53:45 -0700100 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800101 """
kelvin-onlabf512e942015-06-08 19:42:59 -0700102 Description:
103 Starts Mininet accepts a topology(.py) file and/or an optional
104 argument, to start the mininet, as a parameter.
105 Can also send regular mininet command to load up desired topology.
106 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
107 Options:
108 topoFile = file path for topology file (.py)
109 args = extra option added when starting the topology from the file
110 mnCmd = Mininet command use to start topology
111 Returns:
112 main.TRUE if the mininet starts successfully, main.FALSE
113 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800114 """
Jon Hall7eb38402015-01-08 17:19:54 -0800115 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700116 # make sure old networks are cleaned up
117 main.log.info( self.name +
118 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800119 self.handle.sendline( "sudo mn -c" )
120 i = self.handle.expect( [ 'password\sfor\s',
121 'Cleanup\scomplete',
122 pexpect.EOF,
123 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800124 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800125 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700126 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800127 main.log.info( self.name + ": Sending sudo password" )
128 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800129 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800130 '\$',
131 pexpect.EOF,
132 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800133 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800134 if i == 1:
135 main.log.info( self.name + ": Clean" )
136 elif i == 2:
137 main.log.error( self.name + ": Connection terminated" )
138 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700139 main.log.error( self.name + ": Something while cleaning " +
140 "Mininet took too long... " )
141 # Craft the string to start mininet
142 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700143 if not mnCmd:
144 if topoFile is None or topoFile == '': # If no file is given
145 main.log.info( self.name + ": building fresh Mininet" )
146 cmdString += "mn "
147 if args is None or args == '':
148 # If no args given, use args from .topo file
149 args = self.options[ 'arg1' ] +\
150 " " + self.options[ 'arg2' ] +\
151 " --mac --controller " +\
152 self.options[ 'controller' ] + " " +\
153 self.options[ 'arg3' ]
154 else: # else only use given args
155 pass
156 # TODO: allow use of topo args and method args?
157 else: # Use given topology file
158 main.log.info( "Starting Mininet from topo file " + topoFile )
159 cmdString += topoFile + " "
160 if args is None:
161 args = ''
162 # TODO: allow use of args from .topo file?
163 cmdString += args
164 else:
165 main.log.info( "Starting Mininet topology using '" + mnCmd +
166 "' command" )
167 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700168 # Send the command and check if network started
169 self.handle.sendline( "" )
170 self.handle.expect( '\$' )
171 main.log.info( "Sending '" + cmdString + "' to " + self.name )
172 self.handle.sendline( cmdString )
173 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800174 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700175 'Exception',
176 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800177 pexpect.EOF,
178 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700179 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800180 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700181 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800182 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800183 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700184 response = str( self.handle.before +
185 self.handle.after )
186 self.handle.expect( '\$' )
187 response += str( self.handle.before +
188 self.handle.after )
189 main.log.error(
190 self.name +
191 ": Launching Mininet failed: " + response )
192 return main.FALSE
193 elif i == 2:
194 self.handle.expect( [ "\n",
195 pexpect.EOF,
196 pexpect.TIMEOUT ],
197 timeout )
198 main.log.info( self.handle.before )
199 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800200 main.log.error( self.name + ": Connection timeout" )
201 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700202 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800203 main.log.error(
204 self.name +
205 ": Something took too long... " )
206 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700207 # Why did we hit this part?
208 main.log.error( "startNet did not return correctly" )
209 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800210 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700211 main.log.error( self.name + ": Connection failed to the host " +
212 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800213 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700214 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800215
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800216 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400217 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800218 # In tree topology, if fanout arg is not given, by default it is 2
219 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400220 fanout = 2
221 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500222 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800223 while( k <= depth - 1 ):
224 count = count + pow( fanout, k )
225 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800226 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800227 while( k <= depth - 2 ):
228 # depth-2 gives you only core links and not considering
229 # edge links as seen by ONOS. If all the links including
230 # edge links are required, do depth-1
231 count = count + pow( fanout, k )
232 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800233 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800234 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800235 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800236
Jon Hall7eb38402015-01-08 17:19:54 -0800237 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800238 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800239 # by default it is 1
240 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400241 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800242 numSwitches = depth
243 numHostsPerSw = fanout
244 totalNumHosts = numSwitches * numHostsPerSw
245 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800246 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800247 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800248 topoDict = { "num_switches": int( numSwitches ),
249 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400250 return topoDict
251
kelvin-onlabd3b64892015-01-20 13:26:24 -0800252 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700253 """
254 Calculate the number of switches and links in a topo."""
255 # TODO: combine this function and numSwitchesNlinks
256 argList = self.options[ 'arg1' ].split( "," )
257 topoArgList = argList[ 0 ].split( " " )
258 argList = map( int, argList[ 1: ] )
259 topoArgList = topoArgList[ 1: ] + argList
260
261 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400262 return topoDict
263
kelvin-onlabc44f0192015-04-02 22:08:41 -0700264 def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0):
Jon Hall7eb38402015-01-08 17:19:54 -0800265 """
266 Verifies the reachability of the hosts using pingall command.
267 Optional parameter timeout allows you to specify how long to
268 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700269 Optional:
Jon Hall390696c2015-05-05 17:13:41 -0700270 timeout(seconds) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700271 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700272 ping
273 acceptableFailed - Set the number of acceptable failed pings for the
274 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800275 Returns:
276 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700277 otherwise main.FALSE
278 """
279 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700280 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700281 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700282 if self.handle:
283 main.log.info(
284 self.name +
285 ": Checking reachabilty to the hosts using pingall" )
286 response = ""
287 failedPings = 0
288 returnValue = main.TRUE
289 self.handle.sendline( "pingall" )
Jon Hall390696c2015-05-05 17:13:41 -0700290 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700291 while True:
292 i = self.handle.expect( [ "mininet>","X",
293 pexpect.EOF,
294 pexpect.TIMEOUT ],
295 timeout )
296 if i == 0:
297 main.log.info( self.name + ": pingall finished")
298 response += self.handle.before
299 break
300 elif i == 1:
301 response += self.handle.before + self.handle.after
302 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700303 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700304 returnValue = main.FALSE
305 if shortCircuit:
306 main.log.error( self.name +
307 ": Aborting pingall - "
308 + str( failedPings ) +
309 " pings failed" )
310 break
Jon Hall390696c2015-05-05 17:13:41 -0700311 if ( time.time() - startTime ) > timeout:
312 returnValue = main.FALSE
313 main.log.error( self.name +
314 ": Aborting pingall - " +
315 "Function took too long " )
316 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700317 elif i == 2:
318 main.log.error( self.name +
319 ": EOF exception found" )
320 main.log.error( self.name + ": " +
321 self.handle.before )
322 main.cleanup()
323 main.exit()
324 elif i == 3:
325 response += self.handle.before
326 main.log.error( self.name +
327 ": TIMEOUT exception found" )
328 main.log.error( self.name +
329 ": " +
330 str( response ) )
331 # NOTE: Send ctrl-c to make sure pingall is done
332 self.handle.sendline( "\x03" )
333 self.handle.expect( "Interrupt" )
334 self.handle.expect( "mininet>" )
335 break
336 pattern = "Results\:"
337 main.log.info( "Pingall output: " + str( response ) )
338 if re.search( pattern, response ):
339 main.log.info( self.name + ": Pingall finished with "
340 + str( failedPings ) + " failed pings" )
341 return returnValue
342 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700343 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700344 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700345 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700346 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700347 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700348 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700349 main.log.error( self.name + ": Connection failed to the host" )
350 main.cleanup()
351 main.exit()
352 except pexpect.TIMEOUT:
353 if response:
354 main.log.info( "Pingall output: " + str( response ) )
355 main.log.error( self.name + ": pexpect.TIMEOUT found" )
356 return main.FALSE
357 except pexpect.EOF:
358 main.log.error( self.name + ": EOF exception found" )
359 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500360 main.cleanup()
361 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700362
Jon Hall7eb38402015-01-08 17:19:54 -0800363 def fpingHost( self, **pingParams ):
364 """
365 Uses the fping package for faster pinging...
366 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800367 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800368 command = args[ "SRC" ] + \
369 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
370 self.handle.sendline( command )
371 self.handle.expect(
372 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
373 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
374 response = self.handle.before
375 if re.search( ":\s-", response ):
376 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700377 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800378 elif re.search( ":\s\d{1,2}\.\d\d", response ):
379 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700380 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800381 main.log.info( self.name + ": Install fping on mininet machine... " )
382 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700383 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800384
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400385 def pingallHosts( self, hostList, pingType='ipv4' ):
386 """
kelvin-onlab2ff57022015-05-29 10:48:51 -0700387 Ping all specified hosts with a specific ping type
388
389 Acceptable pingTypes:
390 - 'ipv4'
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400391 - 'ipv6'
kelvin-onlab2ff57022015-05-29 10:48:51 -0700392
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400393 Acceptable hostList:
394 - ['h1','h2','h3','h4']
kelvin-onlab2ff57022015-05-29 10:48:51 -0700395
396 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400397 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700398
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400399 Returns main.FALSE if one or more of hosts specified
400 cannot reach each other"""
kelvin-onlab2ff57022015-05-29 10:48:51 -0700401
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400402 if pingType == "ipv4":
kelvin-onlab2ff57022015-05-29 10:48:51 -0700403 cmd = " ping -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400404 elif pingType == "ipv6":
405 cmd = " ping6 -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400406 else:
407 main.log.warn( "Invalid pingType specified" )
408 return
409
410 try:
411 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700412
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400413 isReachable = main.TRUE
414
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400415 for host in hostList:
416 listIndex = hostList.index(host)
417 # List of hosts to ping other than itself
418 pingList = hostList[:listIndex] + hostList[(listIndex+1):]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700419
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400420 for temp in pingList:
421 # Current host pings all other hosts specified
kelvin-onlab2ff57022015-05-29 10:48:51 -0700422 pingCmd = str(host) + cmd + str(temp)
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400423 self.handle.sendline( pingCmd )
424 i = self.handle.expect( [ pingCmd, pexpect.TIMEOUT ] )
425 j = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
426 response = self.handle.before
427 if re.search( ',\s0\%\spacket\sloss', response ):
428 main.log.info( str(host) + " -> " + str(temp) )
429 else:
430 main.log.info( str(host) + " -> X ("+str(temp)+") "
kelvin-onlab2ff57022015-05-29 10:48:51 -0700431 " Destination Unreachable" )
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400432 # One of the host to host pair is unreachable
433 isReachable = main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400434
kelvin-onlab2ff57022015-05-29 10:48:51 -0700435 return isReachable
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400436
437 except pexpect.EOF:
438 main.log.error( self.name + ": EOF exception found" )
439 main.log.error( self.name + ": " + self.handle.before )
440 main.cleanup()
441 main.exit()
442
Jon Hall7eb38402015-01-08 17:19:54 -0800443 def pingHost( self, **pingParams ):
444 """
445 Ping from one mininet host to another
446 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800447 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800448 command = args[ "SRC" ] + " ping " + \
449 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700450 try:
Jon Hall61282e32015-03-19 11:34:11 -0700451 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800452 self.handle.sendline( command )
453 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700454 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800455 main.log.error(
456 self.name +
457 ": timeout when waiting for response from mininet" )
458 main.log.error( "response: " + str( self.handle.before ) )
459 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700460 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800461 main.log.error(
462 self.name +
463 ": timeout when waiting for response from mininet" )
464 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700465 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800466 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800467 main.log.error( self.name + ": EOF exception found" )
468 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700469 main.cleanup()
470 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800471 main.log.info( self.name + ": Ping Response: " + response )
472 if re.search( ',\s0\%\spacket\sloss', response ):
473 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800474 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700475 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800476 else:
477 main.log.error(
478 self.name +
479 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800480 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700481 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800482
Jon Hall7eb38402015-01-08 17:19:54 -0800483 def checkIP( self, host ):
484 """
485 Verifies the host's ip configured or not."""
486 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700487 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800488 response = self.execute(
489 cmd=host +
490 " ifconfig",
491 prompt="mininet>",
492 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800493 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800494 main.log.error( self.name + ": EOF exception found" )
495 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700496 main.cleanup()
497 main.exit()
adminbae64d82013-08-01 10:50:15 -0700498
Jon Hall7eb38402015-01-08 17:19:54 -0800499 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800500 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
501 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
502 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
503 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
504 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800505 # pattern = "inet addr:10.0.0.6"
506 if re.search( pattern, response ):
507 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700508 return main.TRUE
509 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800510 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700511 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800512 else:
513 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800514
Jon Hall7eb38402015-01-08 17:19:54 -0800515 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800516 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700517 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800518 response = self.execute(
519 cmd="h1 /usr/sbin/sshd -D&",
520 prompt="mininet>",
521 timeout=10 )
522 response = self.execute(
523 cmd="h4 /usr/sbin/sshd -D&",
524 prompt="mininet>",
525 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700526 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800527 vars( self )[ key ] = connectargs[ key ]
528 response = self.execute(
529 cmd="xterm h1 h4 ",
530 prompt="mininet>",
531 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800532 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800533 main.log.error( self.name + ": EOF exception found" )
534 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700535 main.cleanup()
536 main.exit()
adminbae64d82013-08-01 10:50:15 -0700537 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800538 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700539 if self.flag == 0:
540 self.flag = 1
541 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800542 else:
adminbae64d82013-08-01 10:50:15 -0700543 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800544
kelvin-onlaba1484582015-02-02 15:46:20 -0800545 def moveHost( self, host, oldSw, newSw, ):
546 """
547 Moves a host from one switch to another on the fly
548 Note: The intf between host and oldSw when detached
549 using detach(), will still show up in the 'net'
550 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Hallafa8a472015-06-12 14:02:42 -0700551 (which is correct behavior since the interfaces
kelvin-onlaba1484582015-02-02 15:46:20 -0800552 haven't moved).
553 """
554 if self.handle:
555 try:
556 # Bring link between oldSw-host down
Jon Hallefbd9792015-03-05 16:11:36 -0800557 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'"+ host +\
558 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800559 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800560 response = self.execute( cmd=cmd,
561 prompt="mininet>",
562 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700563
kelvin-onlaba1484582015-02-02 15:46:20 -0800564 # Determine hostintf and Oldswitchintf
565 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800566 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800567 print "cmd2= ", cmd
568 self.handle.sendline( cmd )
569 self.handle.expect( "mininet>" )
570
shahshreya73537862015-02-11 15:15:24 -0800571 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800572 cmd = "px ipaddr = hintf.IP()"
573 print "cmd3= ", cmd
574 self.handle.sendline( cmd )
575 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800576
577 cmd = "px macaddr = hintf.MAC()"
578 print "cmd3= ", cmd
579 self.handle.sendline( cmd )
580 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700581
kelvin-onlaba1484582015-02-02 15:46:20 -0800582 # Detach interface between oldSw-host
583 cmd = "px " + oldSw + ".detach( sintf )"
584 print "cmd4= ", cmd
585 self.handle.sendline( cmd )
586 self.handle.expect( "mininet>" )
587
588 # Add link between host-newSw
589 cmd = "py net.addLink(" + host + "," + newSw + ")"
590 print "cmd5= ", cmd
591 self.handle.sendline( cmd )
592 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700593
kelvin-onlaba1484582015-02-02 15:46:20 -0800594 # Determine hostintf and Newswitchintf
595 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800596 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800597 print "cmd6= ", cmd
598 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700599 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800600
601 # Attach interface between newSw-host
602 cmd = "px " + newSw + ".attach( sintf )"
603 print "cmd3= ", cmd
604 self.handle.sendline( cmd )
605 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700606
kelvin-onlaba1484582015-02-02 15:46:20 -0800607 # Set ipaddress of the host-newSw interface
608 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
609 print "cmd7 = ", cmd
610 self.handle.sendline( cmd )
611 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800612
613 # Set macaddress of the host-newSw interface
614 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
615 print "cmd8 = ", cmd
616 self.handle.sendline( cmd )
617 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700618
kelvin-onlaba1484582015-02-02 15:46:20 -0800619 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800620 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800621 self.handle.sendline( cmd )
622 self.handle.expect( "mininet>" )
623 print "output = ", self.handle.before
624
625 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800626 cmd = host + " ifconfig"
627 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800628 self.handle.sendline( cmd )
629 self.handle.expect( "mininet>" )
630 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700631
kelvin-onlaba1484582015-02-02 15:46:20 -0800632 return main.TRUE
633 except pexpect.EOF:
634 main.log.error( self.name + ": EOF exception found" )
635 main.log.error( self.name + ": " + self.handle.before )
636 return main.FALSE
637
Jon Hall7eb38402015-01-08 17:19:54 -0800638 def changeIP( self, host, intf, newIP, newNetmask ):
639 """
640 Changes the ip address of a host on the fly
641 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800642 if self.handle:
643 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800644 cmd = host + " ifconfig " + intf + " " + \
645 newIP + " " + 'netmask' + " " + newNetmask
646 self.handle.sendline( cmd )
647 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800648 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800649 main.log.info( "response = " + response )
650 main.log.info(
651 "Ip of host " +
652 host +
653 " changed to new IP " +
654 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800655 return main.TRUE
656 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800657 main.log.error( self.name + ": EOF exception found" )
658 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800659 return main.FALSE
660
Jon Hall7eb38402015-01-08 17:19:54 -0800661 def changeDefaultGateway( self, host, newGW ):
662 """
663 Changes the default gateway of a host
664 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800665 if self.handle:
666 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800667 cmd = host + " route add default gw " + newGW
668 self.handle.sendline( cmd )
669 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800670 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800671 main.log.info( "response = " + response )
672 main.log.info(
673 "Default gateway of host " +
674 host +
675 " changed to " +
676 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800677 return main.TRUE
678 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800679 main.log.error( self.name + ": EOF exception found" )
680 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800681 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800682
Jon Hall7eb38402015-01-08 17:19:54 -0800683 def addStaticMACAddress( self, host, GW, macaddr ):
684 """
Jon Hallefbd9792015-03-05 16:11:36 -0800685 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800686 if self.handle:
687 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800688 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
689 cmd = host + " arp -s " + GW + " " + macaddr
690 self.handle.sendline( cmd )
691 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800692 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800693 main.log.info( "response = " + response )
694 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800695 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800696 GW +
697 " changed to " +
698 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800699 return main.TRUE
700 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800701 main.log.error( self.name + ": EOF exception found" )
702 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800703 return main.FALSE
704
Jon Hall7eb38402015-01-08 17:19:54 -0800705 def verifyStaticGWandMAC( self, host ):
706 """
707 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800708 if self.handle:
709 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800710 # h1 arp -an
711 cmd = host + " arp -an "
712 self.handle.sendline( cmd )
713 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800714 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800715 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800716 return main.TRUE
717 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800718 main.log.error( self.name + ": EOF exception found" )
719 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800720 return main.FALSE
721
Jon Hall7eb38402015-01-08 17:19:54 -0800722 def getMacAddress( self, host ):
723 """
724 Verifies the host's ip configured or not."""
725 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700726 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800727 response = self.execute(
728 cmd=host +
729 " ifconfig",
730 prompt="mininet>",
731 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800732 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800733 main.log.error( self.name + ": EOF exception found" )
734 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700735 main.cleanup()
736 main.exit()
adminbae64d82013-08-01 10:50:15 -0700737
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700738 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800739 macAddressSearch = re.search( pattern, response, re.I )
740 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800741 main.log.info(
742 self.name +
743 ": Mac-Address of Host " +
744 host +
745 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800746 macAddress )
747 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700748 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800749 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700750
Jon Hall7eb38402015-01-08 17:19:54 -0800751 def getInterfaceMACAddress( self, host, interface ):
752 """
753 Return the IP address of the interface on the given host"""
754 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700755 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800756 response = self.execute( cmd=host + " ifconfig " + interface,
757 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800758 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800759 main.log.error( self.name + ": EOF exception found" )
760 main.log.error( self.name + ": " + self.handle.before )
761 main.cleanup()
762 main.exit()
763
764 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800765 macAddressSearch = re.search( pattern, response, re.I )
766 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800767 main.log.info( "No mac address found in %s" % response )
768 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800769 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800770 main.log.info(
771 "Mac-Address of " +
772 host +
773 ":" +
774 interface +
775 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800776 macAddress )
777 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800778 else:
779 main.log.error( "Connection failed to the host" )
780
781 def getIPAddress( self, host ):
782 """
783 Verifies the host's ip configured or not."""
784 if self.handle:
785 try:
786 response = self.execute(
787 cmd=host +
788 " ifconfig",
789 prompt="mininet>",
790 timeout=10 )
791 except pexpect.EOF:
792 main.log.error( self.name + ": EOF exception found" )
793 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700794 main.cleanup()
795 main.exit()
adminbae64d82013-08-01 10:50:15 -0700796
797 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800798 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800799 main.log.info(
800 self.name +
801 ": IP-Address of Host " +
802 host +
803 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800804 ipAddressSearch.group( 1 ) )
805 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800806 else:
807 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800808
Jon Hall7eb38402015-01-08 17:19:54 -0800809 def getSwitchDPID( self, switch ):
810 """
811 return the datapath ID of the switch"""
812 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700813 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700814 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800815 response = self.execute(
816 cmd=cmd,
817 prompt="mininet>",
818 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800819 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800820 main.log.error( self.name + ": EOF exception found" )
821 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700822 main.cleanup()
823 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800824 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800825 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700826 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800827 main.log.info(
828 "Couldn't find DPID for switch %s, found: %s" %
829 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700830 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800831 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700832 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800833 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700834
Jon Hall7eb38402015-01-08 17:19:54 -0800835 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700836 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800837 self.handle.sendline( "" )
838 self.expect( "mininet>" )
839 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700840 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800841 response = self.execute(
842 cmd=cmd,
843 prompt="mininet>",
844 timeout=10 )
845 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700846 response = self.handle.before
847 return response
848 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800849 main.log.error( self.name + ": EOF exception found" )
850 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700851 main.cleanup()
852 main.exit()
853
Jon Hall7eb38402015-01-08 17:19:54 -0800854 def getInterfaces( self, node ):
855 """
856 return information dict about interfaces connected to the node"""
857 if self.handle:
858 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800859 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700860 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700861 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800862 response = self.execute(
863 cmd=cmd,
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()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700871 return response
872 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800873 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700874
Jon Hall7eb38402015-01-08 17:19:54 -0800875 def dump( self ):
876 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700877 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800878 response = self.execute(
879 cmd='dump',
880 prompt='mininet>',
881 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800882 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800883 main.log.error( self.name + ": EOF exception found" )
884 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700885 main.cleanup()
886 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700887 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800888
Jon Hall7eb38402015-01-08 17:19:54 -0800889 def intfs( self ):
890 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700891 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800892 response = self.execute(
893 cmd='intfs',
894 prompt='mininet>',
895 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800896 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800897 main.log.error( self.name + ": EOF exception found" )
898 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700899 main.cleanup()
900 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700901 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800902
Jon Hall7eb38402015-01-08 17:19:54 -0800903 def net( self ):
904 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700905 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800906 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800907 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800908 main.log.error( self.name + ": EOF exception found" )
909 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700910 main.cleanup()
911 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700912 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800913
Jon Hallafa8a472015-06-12 14:02:42 -0700914 def links( self ):
915 main.log.info( self.name + ": List network links" )
916 try:
917 response = self.execute( cmd='links', prompt='mininet>',
918 timeout=10 )
919 except pexpect.EOF:
920 main.log.error( self.name + ": EOF exception found" )
921 main.log.error( self.name + ": " + self.handle.before )
922 main.cleanup()
923 main.exit()
924 return response
925
Jon Hall7eb38402015-01-08 17:19:54 -0800926 def iperf( self, host1, host2 ):
927 main.log.info(
928 self.name +
929 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700930 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800931 cmd1 = 'iperf ' + host1 + " " + host2
932 self.handle.sendline( cmd1 )
933 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800934 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800935 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800936 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800937 return main.TRUE
938 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800939 main.log.error( self.name + ": iperf test failed" )
940 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800941 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800942 main.log.error( self.name + ": EOF exception found" )
943 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800944 main.cleanup()
945 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800946
Jon Hall7eb38402015-01-08 17:19:54 -0800947 def iperfudp( self ):
948 main.log.info(
949 self.name +
950 ": Simple iperf TCP test between two " +
951 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700952 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800953 response = self.execute(
954 cmd='iperfudp',
955 prompt='mininet>',
956 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800957 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800958 main.log.error( self.name + ": EOF exception found" )
959 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700960 main.cleanup()
961 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700962 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800963
Jon Hall7eb38402015-01-08 17:19:54 -0800964 def nodes( self ):
965 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700966 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800967 response = self.execute(
968 cmd='nodes',
969 prompt='mininet>',
970 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800971 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800972 main.log.error( self.name + ": EOF exception found" )
973 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700974 main.cleanup()
975 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700976 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800977
Jon Hall7eb38402015-01-08 17:19:54 -0800978 def pingpair( self ):
979 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700980 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800981 response = self.execute(
982 cmd='pingpair',
983 prompt='mininet>',
984 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800985 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800986 main.log.error( self.name + ": EOF exception found" )
987 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700988 main.cleanup()
989 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800990
Jon Hall7eb38402015-01-08 17:19:54 -0800991 if re.search( ',\s0\%\spacket\sloss', response ):
992 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800993 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700994 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800995 else:
996 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800997 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700998 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800999
Jon Hall7eb38402015-01-08 17:19:54 -08001000 def link( self, **linkargs ):
1001 """
1002 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001003 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001004 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1005 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1006 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1007 main.log.info(
1008 "Bring link between '" +
1009 end1 +
1010 "' and '" +
1011 end2 +
1012 "' '" +
1013 option +
1014 "'" )
1015 command = "link " + \
1016 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001017 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001018 self.handle.sendline( command )
1019 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001020 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001021 main.log.error( self.name + ": EOF exception found" )
1022 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001023 main.cleanup()
1024 main.exit()
adminbae64d82013-08-01 10:50:15 -07001025 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001026
Jon Hall7eb38402015-01-08 17:19:54 -08001027 def yank( self, **yankargs ):
1028 """
1029 yank a mininet switch interface to a host"""
1030 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001031 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001032 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1033 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1034 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001035 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001036 response = self.execute(
1037 cmd=command,
1038 prompt="mininet>",
1039 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001040 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001041 main.log.error( self.name + ": EOF exception found" )
1042 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001043 main.cleanup()
1044 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001045 return main.TRUE
1046
Jon Hall7eb38402015-01-08 17:19:54 -08001047 def plug( self, **plugargs ):
1048 """
1049 plug the yanked mininet switch interface to a switch"""
1050 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001051 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001052 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1053 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1054 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001055 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001056 response = self.execute(
1057 cmd=command,
1058 prompt="mininet>",
1059 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001060 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001061 main.log.error( self.name + ": EOF exception found" )
1062 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001063 main.cleanup()
1064 main.exit()
adminbae64d82013-08-01 10:50:15 -07001065 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001066
Jon Hall7eb38402015-01-08 17:19:54 -08001067 def dpctl( self, **dpctlargs ):
1068 """
1069 Run dpctl command on all switches."""
1070 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001071 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001072 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1073 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1074 command = "dpctl " + cmd + " " + str( cmdargs )
1075 try:
1076 response = self.execute(
1077 cmd=command,
1078 prompt="mininet>",
1079 timeout=10 )
1080 except pexpect.EOF:
1081 main.log.error( self.name + ": EOF exception found" )
1082 main.log.error( self.name + ": " + self.handle.before )
1083 main.cleanup()
1084 main.exit()
1085 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001086
kelvin-onlabd3b64892015-01-20 13:26:24 -08001087 def getVersion( self ):
Jon Hallff6b4b22015-02-23 09:25:15 -08001088 #FIXME: What uses this? This should be refactored to get
1089 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001090 fileInput = path + '/lib/Mininet/INSTALL'
1091 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001092 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001093 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001094 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001095 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001096 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001097 return version
adminbae64d82013-08-01 10:50:15 -07001098
kelvin-onlabd3b64892015-01-20 13:26:24 -08001099 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001100 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001101 Parameters:
1102 sw: The name of an OVS switch. Example "s1"
1103 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001104 The output of the command from the mininet cli
1105 or main.FALSE on timeout"""
1106 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001107 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001108 response = self.execute(
1109 cmd=command,
1110 prompt="mininet>",
1111 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001112 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001113 return response
admin2a9548d2014-06-17 14:08:07 -07001114 else:
1115 return main.FALSE
1116 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001117 main.log.error( self.name + ": EOF exception found" )
1118 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001119 main.cleanup()
1120 main.exit()
adminbae64d82013-08-01 10:50:15 -07001121
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001122 def assignSwController( self, sw, ip, port="6633", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001123 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001124 Description:
1125 Assign switches to the controllers ( for ovs use only )
1126 Required:
1127 sw - Name of the switch. This can be a list or a string.
1128 ip - Ip addresses of controllers. This can be a list or a string.
1129 Optional:
1130 port - ONOS use port 6633, if no list of ports is passed, then
1131 the all the controller will use 6633 as their port number
1132 ptcp - ptcp number, This can be a string or a list that has
1133 the same length as switch. This is optional and not required
1134 when using ovs switches.
1135 NOTE: If switches and ptcp are given in a list type they should have the
1136 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1137 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001138
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001139 Return:
1140 Returns main.TRUE if mininet correctly assigned switches to
1141 controllers, otherwise it will return main.FALSE or an appropriate
1142 exception(s)
1143 """
1144 assignResult = main.TRUE
1145 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001146 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001147 command = "sh ovs-vsctl set-controller "
1148 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001149 try:
1150 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001151 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001152 if isinstance( port, types.StringType ) or \
1153 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001154 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001155 elif isinstance( port, types.ListType ):
1156 main.log.error( self.name + ": Only one controller " +
1157 "assigned and a list of ports has" +
1158 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001159 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001160 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001161 main.log.error( self.name + ": Invalid controller port " +
1162 "number. Please specify correct " +
1163 "controller port" )
1164 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001165
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001166 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001167 if isinstance( port, types.StringType ) or \
1168 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001169 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001170 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1171 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001172 elif isinstance( port, types.ListType ):
1173 if ( len( ip ) != len( port ) ):
1174 main.log.error( self.name + ": Port list = " +
1175 str( len( port ) ) +
1176 "should be the same as controller" +
1177 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001178 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001179 else:
1180 onosIp = ""
1181 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001182 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1183 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001184 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001185 main.log.error( self.name + ": Invalid controller port " +
1186 "number. Please specify correct " +
1187 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001188 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001189 else:
1190 main.log.error( self.name + ": Invalid ip address" )
1191 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001192
1193 if isinstance( sw, types.StringType ):
1194 command += sw + " "
1195 if ptcp:
1196 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001197 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001198 elif isinstance( ptcp, types.ListType ):
1199 main.log.error( self.name + ": Only one switch is " +
1200 "being set and multiple PTCP is " +
1201 "being passed " )
1202 else:
1203 main.log.error( self.name + ": Invalid PTCP" )
1204 ptcp = ""
1205 command += onosIp
1206 commandList.append( command )
1207
1208 elif isinstance( sw, types.ListType ):
1209 if ptcp:
1210 if isinstance( ptcp, types.ListType ):
1211 if len( ptcp ) != len( sw ):
1212 main.log.error( self.name + ": PTCP length = " +
1213 str( len( ptcp ) ) +
1214 " is not the same as switch" +
1215 " length = " +
1216 str( len( sw ) ) )
1217 return main.FALSE
1218 else:
1219 for switch, ptcpNum in zip( sw, ptcp ):
1220 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001221 tempCmd += switch + " ptcp:" + \
1222 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001223 tempCmd += onosIp
1224 commandList.append( tempCmd )
1225 else:
1226 main.log.error( self.name + ": Invalid PTCP" )
1227 return main.FALSE
1228 else:
1229 for switch in sw:
1230 tempCmd = "sh ovs-vsctl set-controller "
1231 tempCmd += switch + " " + onosIp
1232 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001233 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001234 main.log.error( self.name + ": Invalid switch type " )
1235 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001236
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001237 for cmd in commandList:
1238 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001239 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001240 except pexpect.TIMEOUT:
1241 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1242 return main.FALSE
1243 except pexpect.EOF:
1244 main.log.error( self.name + ": EOF exception found" )
1245 main.log.error( self.name + ": " + self.handle.before )
1246 main.cleanup()
1247 main.exit()
1248 return main.TRUE
1249 except Exception:
1250 main.log.exception( self.name + ": Uncaught exception!" )
1251 main.cleanup()
1252 main.exit()
adminbae64d82013-08-01 10:50:15 -07001253
kelvin-onlabd3b64892015-01-20 13:26:24 -08001254 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001255 """
1256 Removes the controller target from sw"""
1257 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001258 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001259 response = self.execute(
1260 cmd=command,
1261 prompt="mininet>",
1262 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001263 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001264 main.log.error( self.name + ": EOF exception found" )
1265 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001266 main.cleanup()
1267 main.exit()
1268 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001269 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001270
kelvin-onlabd3b64892015-01-20 13:26:24 -08001271 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001272 """
Jon Hallb1290e82014-11-18 16:17:48 -05001273 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001274 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001275 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001276 NOTE: cannot currently specify what type of switch
1277 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001278 sw = name of the new switch as a string
1279 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001280 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001281 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001282 """
1283 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001284 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001285 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001286 response = self.execute(
1287 cmd=command,
1288 prompt="mininet>",
1289 timeout=10 )
1290 if re.search( "already exists!", response ):
1291 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001292 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001293 elif re.search( "Error", response ):
1294 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001295 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001296 elif re.search( "usage:", response ):
1297 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001298 return main.FALSE
1299 else:
1300 return main.TRUE
1301 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001302 main.log.error( self.name + ": EOF exception found" )
kaouthera3f13ca22015-05-05 15:01:41 -07001303 main.log.error(self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001304 main.cleanup()
1305 main.exit()
1306
kelvin-onlabd3b64892015-01-20 13:26:24 -08001307 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001308 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001309 delete a switch from the mininet topology
1310 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001311 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001312 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001313 sw = name of the switch as a string
1314 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001315 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001316 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001317 response = self.execute(
1318 cmd=command,
1319 prompt="mininet>",
1320 timeout=10 )
1321 if re.search( "no switch named", response ):
1322 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001323 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001324 elif re.search( "Error", response ):
1325 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001326 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001327 elif re.search( "usage:", response ):
1328 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001329 return main.FALSE
1330 else:
1331 return main.TRUE
1332 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001333 main.log.error( self.name + ": EOF exception found" )
1334 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001335 main.cleanup()
1336 main.exit()
1337
kelvin-onlabd3b64892015-01-20 13:26:24 -08001338 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001339 """
1340 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001341 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001342 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001343 NOTE: cannot currently specify what type of link
1344 required params:
1345 node1 = the string node name of the first endpoint of the link
1346 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001347 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001348 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001349 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001350 response = self.execute(
1351 cmd=command,
1352 prompt="mininet>",
1353 timeout=10 )
1354 if re.search( "doesnt exist!", response ):
1355 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001356 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001357 elif re.search( "Error", response ):
1358 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001359 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001360 elif re.search( "usage:", response ):
1361 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001362 return main.FALSE
1363 else:
1364 return main.TRUE
1365 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001366 main.log.error( self.name + ": EOF exception found" )
1367 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001368 main.cleanup()
1369 main.exit()
1370
kelvin-onlabd3b64892015-01-20 13:26:24 -08001371 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001372 """
1373 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001374 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001375 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001376 required params:
1377 node1 = the string node name of the first endpoint of the link
1378 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001379 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001380 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001381 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001382 response = self.execute(
1383 cmd=command,
1384 prompt="mininet>",
1385 timeout=10 )
1386 if re.search( "no node named", response ):
1387 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001388 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001389 elif re.search( "Error", response ):
1390 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001391 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001392 elif re.search( "usage:", response ):
1393 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001394 return main.FALSE
1395 else:
1396 return main.TRUE
1397 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001398 main.log.error( self.name + ": EOF exception found" )
1399 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001400 main.cleanup()
1401 main.exit()
1402
kelvin-onlabd3b64892015-01-20 13:26:24 -08001403 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001404 """
Jon Hallb1290e82014-11-18 16:17:48 -05001405 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001406 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001407 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001408 NOTE: cannot currently specify what type of host
1409 required params:
1410 hostname = the string hostname
1411 optional key-value params
1412 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001413 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001414 """
1415 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001416 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001417 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001418 response = self.execute(
1419 cmd=command,
1420 prompt="mininet>",
1421 timeout=10 )
1422 if re.search( "already exists!", response ):
1423 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001424 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001425 elif re.search( "doesnt exists!", response ):
1426 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001427 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001428 elif re.search( "Error", response ):
1429 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001430 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001431 elif re.search( "usage:", response ):
1432 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001433 return main.FALSE
1434 else:
1435 return main.TRUE
1436 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001437 main.log.error( self.name + ": EOF exception found" )
1438 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001439 main.cleanup()
1440 main.exit()
1441
kelvin-onlabd3b64892015-01-20 13:26:24 -08001442 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001443 """
1444 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001445 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001446 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001447 NOTE: this uses a custom mn function
1448 required params:
1449 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001450 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001451 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001452 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001453 response = self.execute(
1454 cmd=command,
1455 prompt="mininet>",
1456 timeout=10 )
1457 if re.search( "no host named", response ):
1458 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001459 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001460 elif re.search( "Error", response ):
1461 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001462 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001463 elif re.search( "usage:", response ):
1464 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001465 return main.FALSE
1466 else:
1467 return main.TRUE
1468 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001469 main.log.error( self.name + ": EOF exception found" )
1470 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001471 main.cleanup()
1472 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001473
Jon Hall7eb38402015-01-08 17:19:54 -08001474 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001475 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001476 Called at the end of the test to stop the mininet and
1477 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001478 """
1479 self.handle.sendline('')
Jon Halld61331b2015-02-17 16:35:47 -08001480 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Hallefbd9792015-03-05 16:11:36 -08001481 timeout=2)
Jon Hall390696c2015-05-05 17:13:41 -07001482 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001483 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001484 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001485 elif i == 1:
1486 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001487 # print "Disconnecting Mininet"
1488 if self.handle:
1489 self.handle.sendline( "exit" )
1490 self.handle.expect( "exit" )
1491 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001492 else:
1493 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001494 return response
1495
Hari Krishnab35c6d02015-03-18 11:13:51 -07001496 def stopNet( self, fileName = "", timeout=5):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001497 """
Jon Hall21270ac2015-02-16 17:59:55 -08001498 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001499 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001500 main.FALSE if the pexpect handle does not exist.
1501
Jon Halld61331b2015-02-17 16:35:47 -08001502 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001503 """
Jon Hall21270ac2015-02-16 17:59:55 -08001504
Jon Halld61331b2015-02-17 16:35:47 -08001505 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001506 response = ''
1507 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001508 try:
kelvin-onlab26bc17f2015-02-06 14:08:59 -08001509 self.handle.sendline("")
kelvin-onlab56a3f462015-02-06 14:04:43 -08001510 i = self.handle.expect( [ 'mininet>',
1511 '\$',
1512 pexpect.EOF,
1513 pexpect.TIMEOUT ],
1514 timeout )
1515 if i == 0:
1516 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001517 response = self.execute(
1518 cmd="exit",
1519 prompt="(.*)",
1520 timeout=120 )
Jon Halld61331b2015-02-17 16:35:47 -08001521 main.log.info( self.name + ": Stopped")
Jon Hall7eb38402015-01-08 17:19:54 -08001522 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001523 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001524
kelvin-onlab56a3f462015-02-06 14:04:43 -08001525 if i == 1:
1526 main.log.info( " Mininet trying to exit while not " +
1527 "in the mininet prompt" )
1528 elif i == 2:
1529 main.log.error( "Something went wrong exiting mininet" )
1530 elif i == 3: # timeout
1531 main.log.error( "Something went wrong exiting mininet " +
1532 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001533
Hari Krishnab35c6d02015-03-18 11:13:51 -07001534 if fileName:
1535 self.handle.sendline("")
1536 self.handle.expect('\$')
1537 self.handle.sendline("sudo kill -9 \`ps -ef | grep \""+ fileName +"\" | grep -v grep | awk '{print $2}'\`")
Jon Hallfbc828e2015-01-06 17:30:19 -08001538 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001539 main.log.error( self.name + ": EOF exception found" )
1540 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001541 main.cleanup()
1542 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001543 else:
1544 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001545 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001546 return response
1547
kelvin-onlabf0594d72015-05-19 17:25:12 -07001548 def arping( self, host="", ip="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001549 """
1550 Description:
1551 Sends arp message from mininet host for hosts discovery
1552 Required:
1553 host - hosts name
1554 Optional:
1555 ip - ip address that does not exist in the network so there would
1556 be no reply.
1557 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001558 if ethDevice:
1559 ethDevice = '-I ' + ethDevice + ' '
1560 cmd = " py " + host + ".cmd(\"arping -c 1 " + ethDevice + ip + "\")"
admin07529932013-11-22 14:58:28 -08001561 try:
kelvin-onlab65782a82015-05-07 14:12:13 -07001562 main.log.warn( "Sending: " + cmd )
1563 self.handle.sendline( cmd )
1564 response = self.handle.before
1565 self.handle.sendline( "" )
1566 self.handle.expect( "mininet>" )
admin07529932013-11-22 14:58:28 -08001567 return main.TRUE
kelvin-onlab65782a82015-05-07 14:12:13 -07001568
1569 except pexpect.EOF:
1570 main.log.error( self.name + ": EOF exception found" )
1571 main.log.error( self.name + ": " + self.handle.before )
1572 main.cleanup()
1573 main.exit()
admin07529932013-11-22 14:58:28 -08001574
Jon Hall7eb38402015-01-08 17:19:54 -08001575 def decToHex( self, num ):
1576 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001577
Jon Hall7eb38402015-01-08 17:19:54 -08001578 def getSwitchFlowCount( self, switch ):
1579 """
1580 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001581 if self.handle:
1582 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1583 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001584 response = self.execute(
1585 cmd=cmd,
1586 prompt="mininet>",
1587 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001588 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001589 main.log.error( self.name + ": EOF exception found" )
1590 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001591 main.cleanup()
1592 main.exit()
1593 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001594 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001595 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001596 main.log.info(
1597 "Couldn't find flows on switch %s, found: %s" %
1598 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001599 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001600 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001601 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001602 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001603
kelvin-onlabd3b64892015-01-20 13:26:24 -08001604 def checkFlows( self, sw, dumpFormat=None ):
1605 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001606 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001607 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001608 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001609 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001610 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001611 response = self.execute(
1612 cmd=command,
1613 prompt="mininet>",
1614 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001615 return response
1616 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001617 main.log.error( self.name + ": EOF exception found" )
1618 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001619 main.cleanup()
1620 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001621
kelvin-onlabd3b64892015-01-20 13:26:24 -08001622 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001623 """
Jon Hallefbd9792015-03-05 16:11:36 -08001624 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001625 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001626 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001627 self.handle.sendline( "" )
1628 self.handle.expect( "mininet>" )
1629 self.handle.sendline(
1630 "sh sudo tcpdump -n -i " +
1631 intf +
1632 " " +
1633 port +
1634 " -w " +
1635 filename.strip() +
1636 " &" )
1637 self.handle.sendline( "" )
1638 i = self.handle.expect( [ 'No\ssuch\device',
1639 'listening\son',
1640 pexpect.TIMEOUT,
1641 "mininet>" ],
1642 timeout=10 )
1643 main.log.warn( self.handle.before + self.handle.after )
1644 self.handle.sendline( "" )
1645 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001646 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001647 main.log.error(
1648 self.name +
1649 ": tcpdump - No such device exists. " +
1650 "tcpdump attempted on: " +
1651 intf )
admin2a9548d2014-06-17 14:08:07 -07001652 return main.FALSE
1653 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001654 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001655 return main.TRUE
1656 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001657 main.log.error(
1658 self.name +
1659 ": tcpdump command timed out! Check interface name," +
1660 " given interface was: " +
1661 intf )
admin2a9548d2014-06-17 14:08:07 -07001662 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001663 elif i == 3:
1664 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001665 return main.TRUE
1666 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001667 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001668 return main.FALSE
1669 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001670 main.log.error( self.name + ": EOF exception found" )
1671 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001672 main.cleanup()
1673 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001674 except Exception:
1675 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001676 main.cleanup()
1677 main.exit()
1678
kelvin-onlabd3b64892015-01-20 13:26:24 -08001679 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001680 """
1681 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001682 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001683 self.handle.sendline( "sh sudo pkill tcpdump" )
1684 self.handle.expect( "mininet>" )
1685 self.handle.sendline( "" )
1686 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001687 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001688 main.log.error( self.name + ": EOF exception found" )
1689 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001690 main.cleanup()
1691 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001692 except Exception:
1693 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001694 main.cleanup()
1695 main.exit()
1696
Jon Hallafa8a472015-06-12 14:02:42 -07001697 def getPorts(self, nodeName, verbose=False ):
1698 """
1699 Read ports from a Mininet switch.
1700
1701 Returns a json structure containing information about the
1702 ports of the given switch.
1703 """
1704 response = self.getInterfaces( nodeName )
1705 # TODO: Sanity check on response. log if no such switch exists
1706 ports = []
1707 for line in response.split( "\n" ):
1708 if not line.startswith( "name=" ):
1709 continue
1710 portVars = {}
1711 for var in line.split( "," ):
1712 key, value = var.split( "=" )
1713 portVars[ key ] = value
1714 isUp = portVars.pop( 'enabled', "True" )
1715 isUp = "True" in isUp
1716 if verbose:
1717 main.log.info( "Reading switch port %s(%s)" %
1718 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1719 mac = portVars[ 'mac' ]
1720 if mac== 'None':
1721 mac = None
1722 ips = []
1723 ip = portVars[ 'ip' ]
1724 if ip == 'None':
1725 ip = None
1726 ips.append( ip )
1727 name = portVars[ 'name' ]
1728 if name == 'None':
1729 name = None
1730 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
1731 if name == 'lo':
1732 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
1733 else:
1734 portNo = re.search( portRe, name ).group( 'port' )
1735 ports.append( { 'of_port': portNo,
1736 'mac': str( mac ).replace( '\'', '' ),
1737 'name': name,
1738 'ips': ips,
1739 'enabled': isUp } )
1740 return ports
1741
1742 def getSwitches(self, verbose=False ):
1743 """
1744 Read switches from Mininet.
1745
1746 Returns a dictionary whose keys are the switch names and the value is
1747 a dictionary containing information about the switch.
1748 """
1749 # FIXME: This currently only works with OVS Switches
1750
1751 # Regex patterns to parse dump output
1752 # Example Switch:
1753 # <OVSSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=5238>
1754 # <OVSSwitch{'protocols': 'OpenFlow10'} s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
1755 swRE = r"<OVSSwitch(\{.*\})?\s(?P<name>[^:]+)\:\s" +\
1756 "(?P<ports>([^,]+,)*[^,\s]+)"
1757 # Update mn port info
1758 self.update()
1759 output = { }
1760 dump = self.dump().split( "\n" )
1761 for line in dump:
1762 if line.startswith( "<OVSSwitch" ):
1763 result = re.search( swRE, line, re.I )
1764 name = result.group( 'name' )
1765 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
1766 if verbose:
1767 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
1768 ports = self.getPorts( name )
1769 output[ name ] = { "dpid": dpid, "ports": ports }
1770 return output
1771
1772 def getHosts(self, verbose=False):
1773 """
1774 Read hosts from Mininet.
1775
1776 Returns a dictionary whose keys are the host names and the value is
1777 a dictionary containing information about the host.
1778 """
1779 # Regex patterns to parse dump output
1780 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
1781 # or <Host h1: pid=12725>
1782 # NOTE: Does not correctly match hosts with multi-links
1783 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
1784 # FIXME: Fix that
1785 hostRE = r"<Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
1786 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
1787 # update mn port info
1788 self.update()
1789 # Get mininet dump
1790 dump = self.dump().split( "\n" )
1791 hosts = []
1792 for line in dump:
1793 if line.startswith( "<Host" ):
1794 result = re.search( hostRE, line )
1795 name = result.group( 'name' )
1796 interfaces = []
1797 response = self.getInterfaces( name )
1798 # Populate interface info
1799 for line in response.split( "\n" ):
1800 if line.startswith( "name=" ):
1801 portVars = {}
1802 for var in line.split( "," ):
1803 key, value = var.split( "=" )
1804 portVars[ key ] = value
1805 isUp = portVars.pop( 'enabled', "True" )
1806 isUp = "True" in isUp
1807 if verbose:
1808 main.log.info( "Reading host port %s(%s)" %
1809 ( portVars[ 'name' ],
1810 portVars[ 'mac' ] ) )
1811 mac = portVars[ 'mac' ]
1812 if mac== 'None':
1813 mac = None
1814 ips = []
1815 ip = portVars[ 'ip' ]
1816 if ip == 'None':
1817 ip = None
1818 ips.append( ip )
1819 intfName = portVars[ 'name' ]
1820 if name == 'None':
1821 name = None
1822 interfaces.append( {
1823 "name": intfName,
1824 "ips": ips,
1825 "mac": str( mac ),
1826 "isUp": isUp } )
1827 hosts.append( {
1828 "name": name,
1829 "interfaces": interfaces } )
1830 return hosts
1831
1832 def getLinks( self ):
1833 """
1834 Gathers information about current Mininet links. These links may not
1835 be up if one of the ports is down.
1836
1837 Returns a list of dictionaries with link endpoints.
1838
1839 The dictionary structure is:
1840 { 'node1': str(node1 name)
1841 'node2': str(node2 name)
1842 'port1': str(port1 of_port)
1843 'port2': str(port2 of_port) }
1844 Note: The port number returned is the eth#, not necessarily the of_port
1845 number. In Mininet, for OVS switch, these should be the same. For
1846 hosts, this is just the eth#.
1847 """
1848 self.update()
1849 response = self.links().split( '\n' )
1850
1851 # Examples:
1852 # s1-eth3<->s2-eth1 (OK OK)
1853 # s13-eth3<->h27-eth0 (OK OK)
1854 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
1855 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
1856 links = []
1857 for line in response:
1858 match = re.search( linkRE, line )
1859 if match:
1860 node1 = match.group( 'node1' )
1861 node2 = match.group( 'node2' )
1862 port1 = match.group( 'port1' )
1863 port2 = match.group( 'port2' )
1864 links.append( { 'node1': node1,
1865 'node2': node2,
1866 'port1': port1,
1867 'port2': port2 } )
1868 return links
1869
1870 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001871 """
1872 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07001873 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001874
Jon Hallafa8a472015-06-12 14:02:42 -07001875 Dependencies:
1876 1. numpy - "sudo pip install numpy"
1877 """
1878 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04001879 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001880 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07001881 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08001882 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001883 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08001884 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001885 main.log.error(
1886 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07001887 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001888 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001889 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001890 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001891 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001892 if switch[ 'available' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07001893 onosDPIDs.append( switch[ 'id' ].replace( ":", ''
1894 ).replace( "of", '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001895 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04001896
Jon Hall7eb38402015-01-08 17:19:54 -08001897 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001898 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07001899 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001900 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001901 main.log.error( str( list1 ) )
1902 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001903 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001904 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001905 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001906 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001907 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001908
Jon Hall7eb38402015-01-08 17:19:54 -08001909 # FIXME: this does not look for extra ports in ONOS, only checks that
1910 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08001911 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001912
Jon Hall7eb38402015-01-08 17:19:54 -08001913 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07001914 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08001915 mnPorts = []
1916 onosPorts = []
1917 switchResult = main.TRUE
1918 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001919 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07001920 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001921 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001922 if onosSwitch[ 'device' ][ 'available' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07001923 if onosSwitch[ 'device' ][ 'id' ].replace( ':',''
1924 ).replace( "of", '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001925 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001926 if port[ 'isEnabled' ]:
1927 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001928 # onosPorts.append( 'local' )
1929 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001930 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001931 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001932 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001933 mnPorts.sort( key=float )
1934 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07001935
kelvin-onlabd3b64892015-01-20 13:26:24 -08001936 mnPortsLog = mnPorts
1937 onosPortsLog = onosPorts
1938 mnPorts = [ x for x in mnPorts ]
1939 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001940
Jon Hall7eb38402015-01-08 17:19:54 -08001941 # TODO: handle other reserved port numbers besides LOCAL
1942 # NOTE: Reserved ports
1943 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1944 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001945 for mnPort in mnPortsLog:
1946 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001947 # don't set results to true here as this is just one of
1948 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001949 mnPorts.remove( mnPort )
1950 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07001951
Jon Hall7eb38402015-01-08 17:19:54 -08001952 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001953 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001954 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001955 if 65534 in mnPorts:
1956 mnPorts.remove( 65534 )
1957 if long( uint64( -2 ) ) in onosPorts:
1958 onosPorts.remove( long( uint64( -2 ) ) )
1959 if len( mnPorts ): # the ports of this switch don't match
1960 switchResult = main.FALSE
1961 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1962 if len( onosPorts ): # the ports of this switch don't match
1963 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001964 main.log.warn(
1965 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001966 str( onosPorts ) )
1967 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07001968 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08001969 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07001970 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001971 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1972 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1973 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07001974 finalResults = finalResults and portsResults
1975 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001976
Jon Hallafa8a472015-06-12 14:02:42 -07001977 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001978 """
1979 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08001980 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001981
Jon Hallafa8a472015-06-12 14:02:42 -07001982 """
Jon Hall7eb38402015-01-08 17:19:54 -08001983 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08001984 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08001985 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04001986
Jon Hallafa8a472015-06-12 14:02:42 -07001987 mnLinks = [ ]
1988 for l in links:
1989 try:
1990 node1 = switches[ l[ 'node1' ] ]
1991 node2 = switches[ l[ 'node2' ] ]
1992 enabled = True
1993 for port in node1[ 'ports' ]:
1994 if port[ 'of_port' ] == l[ 'port1' ]:
1995 enabled = enabled and port[ 'enabled' ]
1996 for port in node2[ 'ports' ]:
1997 if port[ 'of_port' ] == l[ 'port2']:
1998 enabled = enabled and port[ 'enabled' ]
1999 if enabled:
2000 mnLinks.append( l )
2001 except KeyError:
2002 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002003 if 2 * len( mnLinks ) == len( onos ):
2004 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002005 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002006 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002007 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002008 "Mininet has " + str( len( mnLinks ) ) +
2009 " bidirectional links and ONOS has " +
2010 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002011
Jon Hall7eb38402015-01-08 17:19:54 -08002012 # iterate through MN links and check if an ONOS link exists in
2013 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002014 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002015 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002016 node1 = None
2017 port1 = None
2018 node2 = None
2019 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002020 firstDir = main.FALSE
2021 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002022 for swName, switch in switches.iteritems():
2023 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002024 node1 = switch[ 'dpid' ]
2025 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002026 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002027 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002028 if node1 is not None and node2 is not None:
2029 break
Jon Hallafa8a472015-06-12 14:02:42 -07002030 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002031 node2 = switch[ 'dpid' ]
2032 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002033 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002034 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002035 if node1 is not None and node2 is not None:
2036 break
2037
kelvin-onlabd3b64892015-01-20 13:26:24 -08002038 for onosLink in onos:
2039 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002040 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002041 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002042 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002043 onosPort1 = onosLink[ 'src' ][ 'port' ]
2044 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002045
Jon Hall72cf1dc2014-10-20 21:04:50 -04002046 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002047 if str( onosNode1 ) == str( node1 ) and str(
2048 onosNode2 ) == str( node2 ):
2049 if int( onosPort1 ) == int( port1 ) and int(
2050 onosPort2 ) == int( port2 ):
2051 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002052 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002053 main.log.warn(
2054 'The port numbers do not match for ' +
2055 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002056 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002057 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002058 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002059 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002060 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002061
2062 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002063 elif ( str( onosNode1 ) == str( node2 ) and
2064 str( onosNode2 ) == str( node1 ) ):
2065 if ( int( onosPort1 ) == int( port2 )
2066 and int( onosPort2 ) == int( port1 ) ):
2067 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002068 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002069 main.log.warn(
2070 'The port numbers do not match for ' +
2071 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002072 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002073 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002074 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002075 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002076 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002077 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002078 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002079 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002080 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002081 'ONOS does not have the link %s/%s -> %s/%s' %
2082 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002083 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002084 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002085 'ONOS does not have the link %s/%s -> %s/%s' %
2086 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002087 linkResults = linkResults and firstDir and secondDir
2088 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002089
Jon Hallafa8a472015-06-12 14:02:42 -07002090 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002091 """
Jon Hallafa8a472015-06-12 14:02:42 -07002092 Compare mn and onos Hosts.
2093 Since Mininet hosts are quiet, ONOS will only know of them when they
2094 speak. For this reason, we will only check that the hosts in ONOS
2095 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002096
Jon Hallafa8a472015-06-12 14:02:42 -07002097 Arguments:
2098 hostsJson: parsed json object from the onos hosts api
2099 Returns:
2100 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002101 import json
2102 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002103 for onosHost in hostsJson:
2104 onosMAC = onosHost[ 'mac' ].lower()
2105 match = False
2106 for mnHost in hosts:
2107 for mnIntf in mnHost[ 'interfaces' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002108 if onosMAC == mnIntf[ 'mac' ].lower() :
Jon Hallff6b4b22015-02-23 09:25:15 -08002109 match = True
2110 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002111 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002112 pass # all is well
2113 else:
2114 # misssing ip
2115 main.log.error( "ONOS host " + onosHost[ 'id' ]
Jon Hallafa8a472015-06-12 14:02:42 -07002116 + " has a different IP(" +
2117 str( onosHost[ 'ipAddresses' ] ) +
2118 ") than the Mininet host(" +
2119 str( ip ) + ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002120 output = json.dumps(
2121 onosHost,
2122 sort_keys=True,
2123 indent=4,
2124 separators=( ',', ': ' ) )
2125 main.log.info( output )
2126 hostResults = main.FALSE
2127 if not match:
2128 hostResults = main.FALSE
2129 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2130 "corresponding Mininet host." )
2131 output = json.dumps( onosHost,
2132 sort_keys=True,
2133 indent=4,
2134 separators=( ',', ': ' ) )
2135 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002136 return hostResults
2137
Jon Hallafa8a472015-06-12 14:02:42 -07002138 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002139 """
2140 Returns a list of all hosts
2141 Don't ask questions just use it"""
2142 self.handle.sendline( "" )
2143 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002144
Jon Hall7eb38402015-01-08 17:19:54 -08002145 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2146 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002147
kelvin-onlabd3b64892015-01-20 13:26:24 -08002148 handlePy = self.handle.before
2149 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2150 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002151
Jon Hall7eb38402015-01-08 17:19:54 -08002152 self.handle.sendline( "" )
2153 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002154
kelvin-onlabd3b64892015-01-20 13:26:24 -08002155 hostStr = handlePy.replace( "]", "" )
2156 hostStr = hostStr.replace( "'", "" )
2157 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002158 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002159 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002160
kelvin-onlabd3b64892015-01-20 13:26:24 -08002161 return hostList
adminbae64d82013-08-01 10:50:15 -07002162
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002163 def getHosts( self ):
2164 """
2165 Returns a list of all hosts
2166 Don't ask questions just use it"""
2167 self.handle.sendline( "" )
2168 self.handle.expect( "mininet>" )
2169
2170 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2171 self.handle.expect( "mininet>" )
2172
2173 handlePy = self.handle.before
2174 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2175 handlePy = handlePy.rstrip()
2176
2177 self.handle.sendline( "" )
2178 self.handle.expect( "mininet>" )
2179
2180 hostStr = handlePy.replace( "]", "" )
2181 hostStr = hostStr.replace( "'", "" )
2182 hostStr = hostStr.replace( "[", "" )
2183 hostStr = hostStr.replace( " ", "" )
2184 hostList = hostStr.split( "," )
2185
2186 return hostList
2187
2188 def getSwitch( self ):
2189 """
2190 Returns a list of all switches
2191 Again, don't ask question just use it...
2192 """
2193 # get host list...
2194 hostList = self.getHosts()
2195 # Make host set
2196 hostSet = set( hostList )
2197
2198 # Getting all the nodes in mininet
2199 self.handle.sendline( "" )
2200 self.handle.expect( "mininet>" )
2201
2202 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2203 self.handle.expect( "mininet>" )
2204
2205 handlePy = self.handle.before
2206 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2207 handlePy = handlePy.rstrip()
2208
2209 self.handle.sendline( "" )
2210 self.handle.expect( "mininet>" )
2211
2212 nodesStr = handlePy.replace( "]", "" )
2213 nodesStr = nodesStr.replace( "'", "" )
2214 nodesStr = nodesStr.replace( "[", "" )
2215 nodesStr = nodesStr.replace( " ", "" )
2216 nodesList = nodesStr.split( "," )
2217
2218 nodesSet = set( nodesList )
2219 # discarding default controller(s) node
2220 nodesSet.discard( 'c0' )
2221 nodesSet.discard( 'c1' )
2222 nodesSet.discard( 'c2' )
2223
2224 switchSet = nodesSet - hostSet
2225 switchList = list( switchSet )
2226
2227 return switchList
2228
Jon Hall7eb38402015-01-08 17:19:54 -08002229 def update( self ):
2230 """
2231 updates the port address and status information for
2232 each port in mn"""
2233 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002234 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002235 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002236 self.handle.sendline( "" )
2237 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002238
Jon Hall7eb38402015-01-08 17:19:54 -08002239 self.handle.sendline( "update" )
2240 self.handle.expect( "update" )
2241 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002242
Jon Hall7eb38402015-01-08 17:19:54 -08002243 self.handle.sendline( "" )
2244 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002245
Jon Hallb1290e82014-11-18 16:17:48 -05002246 return main.TRUE
2247 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002248 main.log.error( self.name + ": EOF exception found" )
2249 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002250 main.cleanup()
2251 main.exit()
2252
kaouthera3f13ca22015-05-05 15:01:41 -07002253 def assignVLAN( self, host, intf, vlan):
2254 """
2255 Add vlan tag to a host.
2256 Dependencies:
2257 This class depends on the "vlan" package
2258 $ sudo apt-get install vlan
2259 Configuration:
2260 Load the 8021q module into the kernel
2261 $sudo modprobe 8021q
2262
2263 To make this setup permanent:
2264 $ sudo su -c 'echo "8021q" >> /etc/modules'
2265 """
2266 if self.handle:
2267 try:
2268 # get the ip address of the host
2269 main.log.info("Get the ip address of the host")
2270 ipaddr = self.getIPAddress(host)
2271 print repr(ipaddr)
2272
2273 # remove IP from interface intf
2274 # Ex: h1 ifconfig h1-eth0 inet 0
2275 main.log.info("Remove IP from interface ")
2276 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2277 self.handle.sendline( cmd2 )
2278 self.handle.expect( "mininet>" )
2279 response = self.handle.before
2280 main.log.info ( "====> %s ", response)
2281
2282
2283 # create VLAN interface
2284 # Ex: h1 vconfig add h1-eth0 100
2285 main.log.info("Create Vlan")
2286 cmd3 = host + " vconfig add " + intf + " " + vlan
2287 self.handle.sendline( cmd3 )
2288 self.handle.expect( "mininet>" )
2289 response = self.handle.before
2290 main.log.info( "====> %s ", response )
2291
2292 # assign the host's IP to the VLAN interface
2293 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2294 main.log.info("Assign the host IP to the vlan interface")
2295 vintf = intf + "." + vlan
2296 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2297 self.handle.sendline( cmd4 )
2298 self.handle.expect( "mininet>" )
2299 response = self.handle.before
2300 main.log.info ( "====> %s ", response)
2301
2302
2303 return main.TRUE
2304 except pexpect.EOF:
2305 main.log.error( self.name + ": EOF exception found" )
2306 main.log.error( self.name + ": " + self.handle.before )
2307 return main.FALSE
2308
adminbae64d82013-08-01 10:50:15 -07002309if __name__ != "__main__":
2310 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002311 sys.modules[ __name__ ] = MininetCliDriver()
kaouthera3f13ca22015-05-05 15:01:41 -07002312
2313