blob: 158fcd894b17179e588ef0b69520277312c0a4b5 [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 Hallbe6dfc42015-01-12 17:37:25 -080022MininetCliDriver is the basic driver which will handle the Mininet functions
23
24Some functions rely on a modified version of Mininet. These functions
25should all be noted in the comments. To get this MN version run these commands
26from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080027 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080028 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080029 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080030 git pull
31
Jon Hall272a4db2015-01-12 17:43:48 -080032
33 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080034changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070035import pexpect
adminbae64d82013-08-01 10:50:15 -070036import re
37import sys
kelvin-onlabfa6ada82015-06-11 13:06:24 -070038import types
Jon Hall7eb38402015-01-08 17:19:54 -080039sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040040from math import pow
adminbae64d82013-08-01 10:50:15 -070041from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070042
Jon Hall7eb38402015-01-08 17:19:54 -080043
kelvin-onlab50907142015-04-01 13:37:45 -070044class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080045
46 """
47 MininetCliDriver is the basic driver which will handle
48 the Mininet functions"""
49 def __init__( self ):
50 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070051 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080052 self.name = None
Jon Hall7eb38402015-01-08 17:19:54 -080053 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070054 self.flag = 0
55
Jon Hall7eb38402015-01-08 17:19:54 -080056 def connect( self, **connectargs ):
57 """
58 Here the main is the TestON instance after creating
59 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080060 try:
61 for key in connectargs:
62 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080063
kelvin-onlaba1484582015-02-02 15:46:20 -080064 self.name = self.options[ 'name' ]
65 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070066 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080067 self ).connect(
68 user_name=self.user_name,
69 ip_address=self.ip_address,
70 port=None,
71 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080072
kelvin-onlaba1484582015-02-02 15:46:20 -080073 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080074 main.log.info( "Connection successful to the host " +
75 self.user_name +
76 "@" +
77 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080078 return main.TRUE
79 else:
80 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080081 self.user_name +
82 "@" +
83 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -080084 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -080085 return main.FALSE
86 except pexpect.EOF:
87 main.log.error( self.name + ": EOF exception found" )
88 main.log.error( self.name + ": " + self.handle.before )
89 main.cleanup()
90 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -080091 except Exception:
92 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -080093 main.cleanup()
94 main.exit()
95
kelvin-onlab10e8d392015-06-03 13:53:45 -070096 def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -080097 """
kelvin-onlabf512e942015-06-08 19:42:59 -070098 Description:
99 Starts Mininet accepts a topology(.py) file and/or an optional
100 argument, to start the mininet, as a parameter.
101 Can also send regular mininet command to load up desired topology.
102 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd
103 Options:
104 topoFile = file path for topology file (.py)
105 args = extra option added when starting the topology from the file
106 mnCmd = Mininet command use to start topology
107 Returns:
108 main.TRUE if the mininet starts successfully, main.FALSE
109 otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800110 """
Jon Hall7eb38402015-01-08 17:19:54 -0800111 if self.handle:
Jon Hall689d8e42015-04-03 13:59:24 -0700112 # make sure old networks are cleaned up
113 main.log.info( self.name +
114 ": Clearing any residual state or processes" )
Jon Hall7eb38402015-01-08 17:19:54 -0800115 self.handle.sendline( "sudo mn -c" )
116 i = self.handle.expect( [ 'password\sfor\s',
117 'Cleanup\scomplete',
118 pexpect.EOF,
119 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800120 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800121 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700122 # Sudo asking for password
Jon Hall7eb38402015-01-08 17:19:54 -0800123 main.log.info( self.name + ": Sending sudo password" )
124 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800125 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800126 '\$',
127 pexpect.EOF,
128 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800129 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800130 if i == 1:
131 main.log.info( self.name + ": Clean" )
132 elif i == 2:
133 main.log.error( self.name + ": Connection terminated" )
134 elif i == 3: # timeout
Jon Hall689d8e42015-04-03 13:59:24 -0700135 main.log.error( self.name + ": Something while cleaning " +
136 "Mininet took too long... " )
137 # Craft the string to start mininet
138 cmdString = "sudo "
kelvin-onlab10e8d392015-06-03 13:53:45 -0700139 if not mnCmd:
140 if topoFile is None or topoFile == '': # If no file is given
141 main.log.info( self.name + ": building fresh Mininet" )
142 cmdString += "mn "
143 if args is None or args == '':
144 # If no args given, use args from .topo file
145 args = self.options[ 'arg1' ] +\
146 " " + self.options[ 'arg2' ] +\
147 " --mac --controller " +\
148 self.options[ 'controller' ] + " " +\
149 self.options[ 'arg3' ]
150 else: # else only use given args
151 pass
152 # TODO: allow use of topo args and method args?
153 else: # Use given topology file
154 main.log.info( "Starting Mininet from topo file " + topoFile )
155 cmdString += topoFile + " "
156 if args is None:
157 args = ''
158 # TODO: allow use of args from .topo file?
159 cmdString += args
160 else:
161 main.log.info( "Starting Mininet topology using '" + mnCmd +
162 "' command" )
163 cmdString += mnCmd
Jon Hall689d8e42015-04-03 13:59:24 -0700164 # Send the command and check if network started
165 self.handle.sendline( "" )
166 self.handle.expect( '\$' )
167 main.log.info( "Sending '" + cmdString + "' to " + self.name )
168 self.handle.sendline( cmdString )
169 while True:
Jon Hall7eb38402015-01-08 17:19:54 -0800170 i = self.handle.expect( [ 'mininet>',
Jon Hall689d8e42015-04-03 13:59:24 -0700171 'Exception',
172 '\*\*\*',
Jon Hallefbd9792015-03-05 16:11:36 -0800173 pexpect.EOF,
174 pexpect.TIMEOUT ],
Jon Hall689d8e42015-04-03 13:59:24 -0700175 timeout )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800176 if i == 0:
Jon Hall689d8e42015-04-03 13:59:24 -0700177 main.log.info( self.name + ": Mininet built" )
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800178 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800179 elif i == 1:
Jon Hall689d8e42015-04-03 13:59:24 -0700180 response = str( self.handle.before +
181 self.handle.after )
182 self.handle.expect( '\$' )
183 response += str( self.handle.before +
184 self.handle.after )
185 main.log.error(
186 self.name +
187 ": Launching Mininet failed: " + response )
188 return main.FALSE
189 elif i == 2:
190 self.handle.expect( [ "\n",
191 pexpect.EOF,
192 pexpect.TIMEOUT ],
193 timeout )
194 main.log.info( self.handle.before )
195 elif i == 3:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800196 main.log.error( self.name + ": Connection timeout" )
197 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700198 elif i == 4: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800199 main.log.error(
200 self.name +
201 ": Something took too long... " )
202 return main.FALSE
Jon Hall689d8e42015-04-03 13:59:24 -0700203 # Why did we hit this part?
204 main.log.error( "startNet did not return correctly" )
205 return main.FASLE
Jon Hall7eb38402015-01-08 17:19:54 -0800206 else: # if no handle
Jon Hall689d8e42015-04-03 13:59:24 -0700207 main.log.error( self.name + ": Connection failed to the host " +
208 self.user_name + "@" + self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800209 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700210 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800211
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800212 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400213 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800214 # In tree topology, if fanout arg is not given, by default it is 2
215 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400216 fanout = 2
217 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500218 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800219 while( k <= depth - 1 ):
220 count = count + pow( fanout, k )
221 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800222 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800223 while( k <= depth - 2 ):
224 # depth-2 gives you only core links and not considering
225 # edge links as seen by ONOS. If all the links including
226 # edge links are required, do depth-1
227 count = count + pow( fanout, k )
228 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800229 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800230 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800231 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800232
Jon Hall7eb38402015-01-08 17:19:54 -0800233 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800234 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800235 # by default it is 1
236 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400237 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800238 numSwitches = depth
239 numHostsPerSw = fanout
240 totalNumHosts = numSwitches * numHostsPerSw
241 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800242 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800243 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800244 topoDict = { "num_switches": int( numSwitches ),
245 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400246 return topoDict
247
kelvin-onlabd3b64892015-01-20 13:26:24 -0800248 def calculateSwAndLinks( self ):
Jon Hall689d8e42015-04-03 13:59:24 -0700249 """
250 Calculate the number of switches and links in a topo."""
251 # TODO: combine this function and numSwitchesNlinks
252 argList = self.options[ 'arg1' ].split( "," )
253 topoArgList = argList[ 0 ].split( " " )
254 argList = map( int, argList[ 1: ] )
255 topoArgList = topoArgList[ 1: ] + argList
256
257 topoDict = self.numSwitchesNlinks( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400258 return topoDict
259
kelvin-onlabc44f0192015-04-02 22:08:41 -0700260 def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0):
Jon Hall7eb38402015-01-08 17:19:54 -0800261 """
262 Verifies the reachability of the hosts using pingall command.
263 Optional parameter timeout allows you to specify how long to
264 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700265 Optional:
Jon Hall390696c2015-05-05 17:13:41 -0700266 timeout(seconds) - How long to wait before breaking the pingall
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700267 shortCircuit - Break the pingall based on the number of failed hosts
kelvin-onlabc44f0192015-04-02 22:08:41 -0700268 ping
269 acceptableFailed - Set the number of acceptable failed pings for the
270 function to still return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800271 Returns:
272 main.TRUE if pingall completes with no pings dropped
Jon Hall390696c2015-05-05 17:13:41 -0700273 otherwise main.FALSE
274 """
275 import time
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700276 try:
Jon Hallfb760a02015-04-13 15:35:03 -0700277 timeout = int( timeout )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700278 if self.handle:
279 main.log.info(
280 self.name +
281 ": Checking reachabilty to the hosts using pingall" )
282 response = ""
283 failedPings = 0
284 returnValue = main.TRUE
285 self.handle.sendline( "pingall" )
Jon Hall390696c2015-05-05 17:13:41 -0700286 startTime = time.time()
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700287 while True:
288 i = self.handle.expect( [ "mininet>","X",
289 pexpect.EOF,
290 pexpect.TIMEOUT ],
291 timeout )
292 if i == 0:
293 main.log.info( self.name + ": pingall finished")
294 response += self.handle.before
295 break
296 elif i == 1:
297 response += self.handle.before + self.handle.after
298 failedPings = failedPings + 1
kelvin-onlabd26a3742015-04-06 15:31:16 -0700299 if failedPings > acceptableFailed:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700300 returnValue = main.FALSE
301 if shortCircuit:
302 main.log.error( self.name +
303 ": Aborting pingall - "
304 + str( failedPings ) +
305 " pings failed" )
306 break
Jon Hall390696c2015-05-05 17:13:41 -0700307 if ( time.time() - startTime ) > timeout:
308 returnValue = main.FALSE
309 main.log.error( self.name +
310 ": Aborting pingall - " +
311 "Function took too long " )
312 break
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700313 elif i == 2:
314 main.log.error( self.name +
315 ": EOF exception found" )
316 main.log.error( self.name + ": " +
317 self.handle.before )
318 main.cleanup()
319 main.exit()
320 elif i == 3:
321 response += self.handle.before
322 main.log.error( self.name +
323 ": TIMEOUT exception found" )
324 main.log.error( self.name +
325 ": " +
326 str( response ) )
327 # NOTE: Send ctrl-c to make sure pingall is done
328 self.handle.sendline( "\x03" )
329 self.handle.expect( "Interrupt" )
330 self.handle.expect( "mininet>" )
331 break
332 pattern = "Results\:"
333 main.log.info( "Pingall output: " + str( response ) )
334 if re.search( pattern, response ):
335 main.log.info( self.name + ": Pingall finished with "
336 + str( failedPings ) + " failed pings" )
337 return returnValue
338 else:
kelvin-onlabc44f0192015-04-02 22:08:41 -0700339 # NOTE: Send ctrl-c to make sure pingall is done
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700340 self.handle.sendline( "\x03" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700341 self.handle.expect( "Interrupt" )
kelvin-onlabc44f0192015-04-02 22:08:41 -0700342 self.handle.expect( "mininet>" )
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700343 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700344 else:
kelvin-onlabd9a8ed32015-04-03 13:55:28 -0700345 main.log.error( self.name + ": Connection failed to the host" )
346 main.cleanup()
347 main.exit()
348 except pexpect.TIMEOUT:
349 if response:
350 main.log.info( "Pingall output: " + str( response ) )
351 main.log.error( self.name + ": pexpect.TIMEOUT found" )
352 return main.FALSE
353 except pexpect.EOF:
354 main.log.error( self.name + ": EOF exception found" )
355 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500356 main.cleanup()
357 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700358
Jon Hall7eb38402015-01-08 17:19:54 -0800359 def fpingHost( self, **pingParams ):
360 """
361 Uses the fping package for faster pinging...
362 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800363 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800364 command = args[ "SRC" ] + \
365 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
366 self.handle.sendline( command )
367 self.handle.expect(
368 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
369 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
370 response = self.handle.before
371 if re.search( ":\s-", response ):
372 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700373 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800374 elif re.search( ":\s\d{1,2}\.\d\d", response ):
375 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700376 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800377 main.log.info( self.name + ": Install fping on mininet machine... " )
378 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700379 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800380
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400381 def pingallHosts( self, hostList, pingType='ipv4' ):
382 """
kelvin-onlab2ff57022015-05-29 10:48:51 -0700383 Ping all specified hosts with a specific ping type
384
385 Acceptable pingTypes:
386 - 'ipv4'
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400387 - 'ipv6'
kelvin-onlab2ff57022015-05-29 10:48:51 -0700388
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400389 Acceptable hostList:
390 - ['h1','h2','h3','h4']
kelvin-onlab2ff57022015-05-29 10:48:51 -0700391
392 Returns main.TRUE if all hosts specified can reach
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400393 each other
kelvin-onlab2ff57022015-05-29 10:48:51 -0700394
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400395 Returns main.FALSE if one or more of hosts specified
396 cannot reach each other"""
kelvin-onlab2ff57022015-05-29 10:48:51 -0700397
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400398 if pingType == "ipv4":
kelvin-onlab2ff57022015-05-29 10:48:51 -0700399 cmd = " ping -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400400 elif pingType == "ipv6":
401 cmd = " ping6 -c 1 -i 1 -W 8 "
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400402 else:
403 main.log.warn( "Invalid pingType specified" )
404 return
405
406 try:
407 main.log.info( "Testing reachability between specified hosts" )
kelvin-onlab2ff57022015-05-29 10:48:51 -0700408
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400409 isReachable = main.TRUE
410
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400411 for host in hostList:
412 listIndex = hostList.index(host)
413 # List of hosts to ping other than itself
414 pingList = hostList[:listIndex] + hostList[(listIndex+1):]
kelvin-onlab2ff57022015-05-29 10:48:51 -0700415
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400416 for temp in pingList:
417 # Current host pings all other hosts specified
kelvin-onlab2ff57022015-05-29 10:48:51 -0700418 pingCmd = str(host) + cmd + str(temp)
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400419 self.handle.sendline( pingCmd )
420 i = self.handle.expect( [ pingCmd, pexpect.TIMEOUT ] )
421 j = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
422 response = self.handle.before
423 if re.search( ',\s0\%\spacket\sloss', response ):
424 main.log.info( str(host) + " -> " + str(temp) )
425 else:
426 main.log.info( str(host) + " -> X ("+str(temp)+") "
kelvin-onlab2ff57022015-05-29 10:48:51 -0700427 " Destination Unreachable" )
andrew@onlab.usdefe38c2015-05-14 19:18:18 -0400428 # One of the host to host pair is unreachable
429 isReachable = main.FALSE
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400430
kelvin-onlab2ff57022015-05-29 10:48:51 -0700431 return isReachable
andrew@onlab.us9fdee812015-05-14 17:23:26 -0400432
433 except pexpect.EOF:
434 main.log.error( self.name + ": EOF exception found" )
435 main.log.error( self.name + ": " + self.handle.before )
436 main.cleanup()
437 main.exit()
438
Jon Hall7eb38402015-01-08 17:19:54 -0800439 def pingHost( self, **pingParams ):
440 """
441 Ping from one mininet host to another
442 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800443 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800444 command = args[ "SRC" ] + " ping " + \
445 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700446 try:
Jon Hall61282e32015-03-19 11:34:11 -0700447 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800448 self.handle.sendline( command )
449 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700450 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800451 main.log.error(
452 self.name +
453 ": timeout when waiting for response from mininet" )
454 main.log.error( "response: " + str( self.handle.before ) )
455 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700456 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800457 main.log.error(
458 self.name +
459 ": timeout when waiting for response from mininet" )
460 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700461 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800462 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800463 main.log.error( self.name + ": EOF exception found" )
464 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700465 main.cleanup()
466 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800467 main.log.info( self.name + ": Ping Response: " + response )
468 if re.search( ',\s0\%\spacket\sloss', response ):
469 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800470 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700471 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800472 else:
473 main.log.error(
474 self.name +
475 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800476 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700477 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800478
Jon Hall7eb38402015-01-08 17:19:54 -0800479 def checkIP( self, host ):
480 """
481 Verifies the host's ip configured or not."""
482 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700483 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800484 response = self.execute(
485 cmd=host +
486 " ifconfig",
487 prompt="mininet>",
488 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800489 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800490 main.log.error( self.name + ": EOF exception found" )
491 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700492 main.cleanup()
493 main.exit()
adminbae64d82013-08-01 10:50:15 -0700494
Jon Hall7eb38402015-01-08 17:19:54 -0800495 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800496 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
497 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
498 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
499 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
500 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800501 # pattern = "inet addr:10.0.0.6"
502 if re.search( pattern, response ):
503 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700504 return main.TRUE
505 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800506 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700507 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800508 else:
509 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800510
Jon Hall7eb38402015-01-08 17:19:54 -0800511 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800512 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700513 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800514 response = self.execute(
515 cmd="h1 /usr/sbin/sshd -D&",
516 prompt="mininet>",
517 timeout=10 )
518 response = self.execute(
519 cmd="h4 /usr/sbin/sshd -D&",
520 prompt="mininet>",
521 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700522 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800523 vars( self )[ key ] = connectargs[ key ]
524 response = self.execute(
525 cmd="xterm h1 h4 ",
526 prompt="mininet>",
527 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800528 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800529 main.log.error( self.name + ": EOF exception found" )
530 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700531 main.cleanup()
532 main.exit()
adminbae64d82013-08-01 10:50:15 -0700533 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800534 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700535 if self.flag == 0:
536 self.flag = 1
537 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800538 else:
adminbae64d82013-08-01 10:50:15 -0700539 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800540
kelvin-onlaba1484582015-02-02 15:46:20 -0800541 def moveHost( self, host, oldSw, newSw, ):
542 """
543 Moves a host from one switch to another on the fly
544 Note: The intf between host and oldSw when detached
545 using detach(), will still show up in the 'net'
546 cmd, because switch.detach() doesn't affect switch.intfs[]
Jon Hallafa8a472015-06-12 14:02:42 -0700547 (which is correct behavior since the interfaces
kelvin-onlaba1484582015-02-02 15:46:20 -0800548 haven't moved).
549 """
550 if self.handle:
551 try:
552 # Bring link between oldSw-host down
Jon Hallefbd9792015-03-05 16:11:36 -0800553 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'"+ host +\
554 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800555 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800556 response = self.execute( cmd=cmd,
557 prompt="mininet>",
558 timeout=10 )
Jon Hallafa8a472015-06-12 14:02:42 -0700559
kelvin-onlaba1484582015-02-02 15:46:20 -0800560 # Determine hostintf and Oldswitchintf
561 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800562 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800563 print "cmd2= ", cmd
564 self.handle.sendline( cmd )
565 self.handle.expect( "mininet>" )
566
shahshreya73537862015-02-11 15:15:24 -0800567 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800568 cmd = "px ipaddr = hintf.IP()"
569 print "cmd3= ", cmd
570 self.handle.sendline( cmd )
571 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800572
573 cmd = "px macaddr = hintf.MAC()"
574 print "cmd3= ", cmd
575 self.handle.sendline( cmd )
576 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700577
kelvin-onlaba1484582015-02-02 15:46:20 -0800578 # Detach interface between oldSw-host
579 cmd = "px " + oldSw + ".detach( sintf )"
580 print "cmd4= ", cmd
581 self.handle.sendline( cmd )
582 self.handle.expect( "mininet>" )
583
584 # Add link between host-newSw
585 cmd = "py net.addLink(" + host + "," + newSw + ")"
586 print "cmd5= ", cmd
587 self.handle.sendline( cmd )
588 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700589
kelvin-onlaba1484582015-02-02 15:46:20 -0800590 # Determine hostintf and Newswitchintf
591 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800592 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800593 print "cmd6= ", cmd
594 self.handle.sendline( cmd )
Jon Hallafa8a472015-06-12 14:02:42 -0700595 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800596
597 # Attach interface between newSw-host
598 cmd = "px " + newSw + ".attach( sintf )"
599 print "cmd3= ", cmd
600 self.handle.sendline( cmd )
601 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700602
kelvin-onlaba1484582015-02-02 15:46:20 -0800603 # Set ipaddress of the host-newSw interface
604 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
605 print "cmd7 = ", cmd
606 self.handle.sendline( cmd )
607 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800608
609 # Set macaddress of the host-newSw interface
610 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
611 print "cmd8 = ", cmd
612 self.handle.sendline( cmd )
613 self.handle.expect( "mininet>" )
Jon Hallafa8a472015-06-12 14:02:42 -0700614
kelvin-onlaba1484582015-02-02 15:46:20 -0800615 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800616 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800617 self.handle.sendline( cmd )
618 self.handle.expect( "mininet>" )
619 print "output = ", self.handle.before
620
621 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800622 cmd = host + " ifconfig"
623 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800624 self.handle.sendline( cmd )
625 self.handle.expect( "mininet>" )
626 print "ifconfig o/p = ", self.handle.before
Jon Hallafa8a472015-06-12 14:02:42 -0700627
kelvin-onlaba1484582015-02-02 15:46:20 -0800628 return main.TRUE
629 except pexpect.EOF:
630 main.log.error( self.name + ": EOF exception found" )
631 main.log.error( self.name + ": " + self.handle.before )
632 return main.FALSE
633
Jon Hall7eb38402015-01-08 17:19:54 -0800634 def changeIP( self, host, intf, newIP, newNetmask ):
635 """
636 Changes the ip address of a host on the fly
637 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800638 if self.handle:
639 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800640 cmd = host + " ifconfig " + intf + " " + \
641 newIP + " " + 'netmask' + " " + newNetmask
642 self.handle.sendline( cmd )
643 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800644 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800645 main.log.info( "response = " + response )
646 main.log.info(
647 "Ip of host " +
648 host +
649 " changed to new IP " +
650 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800651 return main.TRUE
652 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800653 main.log.error( self.name + ": EOF exception found" )
654 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800655 return main.FALSE
656
Jon Hall7eb38402015-01-08 17:19:54 -0800657 def changeDefaultGateway( self, host, newGW ):
658 """
659 Changes the default gateway of a host
660 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800661 if self.handle:
662 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800663 cmd = host + " route add default gw " + newGW
664 self.handle.sendline( cmd )
665 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800666 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800667 main.log.info( "response = " + response )
668 main.log.info(
669 "Default gateway of host " +
670 host +
671 " changed to " +
672 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800673 return main.TRUE
674 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800675 main.log.error( self.name + ": EOF exception found" )
676 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800677 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800678
Jon Hall7eb38402015-01-08 17:19:54 -0800679 def addStaticMACAddress( self, host, GW, macaddr ):
680 """
Jon Hallefbd9792015-03-05 16:11:36 -0800681 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800682 if self.handle:
683 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800684 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
685 cmd = host + " arp -s " + GW + " " + macaddr
686 self.handle.sendline( cmd )
687 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800688 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800689 main.log.info( "response = " + response )
690 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800691 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800692 GW +
693 " changed to " +
694 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800695 return main.TRUE
696 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800697 main.log.error( self.name + ": EOF exception found" )
698 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800699 return main.FALSE
700
Jon Hall7eb38402015-01-08 17:19:54 -0800701 def verifyStaticGWandMAC( self, host ):
702 """
703 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800704 if self.handle:
705 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800706 # h1 arp -an
707 cmd = host + " arp -an "
708 self.handle.sendline( cmd )
709 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800710 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800711 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800712 return main.TRUE
713 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800714 main.log.error( self.name + ": EOF exception found" )
715 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800716 return main.FALSE
717
Jon Hall7eb38402015-01-08 17:19:54 -0800718 def getMacAddress( self, host ):
719 """
720 Verifies the host's ip configured or not."""
721 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700722 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800723 response = self.execute(
724 cmd=host +
725 " ifconfig",
726 prompt="mininet>",
727 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800728 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800729 main.log.error( self.name + ": EOF exception found" )
730 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700731 main.cleanup()
732 main.exit()
adminbae64d82013-08-01 10:50:15 -0700733
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700734 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800735 macAddressSearch = re.search( pattern, response, re.I )
736 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800737 main.log.info(
738 self.name +
739 ": Mac-Address of Host " +
740 host +
741 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800742 macAddress )
743 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700744 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800745 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700746
Jon Hall7eb38402015-01-08 17:19:54 -0800747 def getInterfaceMACAddress( self, host, interface ):
748 """
749 Return the IP address of the interface on the given host"""
750 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700751 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800752 response = self.execute( cmd=host + " ifconfig " + interface,
753 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800754 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800755 main.log.error( self.name + ": EOF exception found" )
756 main.log.error( self.name + ": " + self.handle.before )
757 main.cleanup()
758 main.exit()
759
760 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800761 macAddressSearch = re.search( pattern, response, re.I )
762 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800763 main.log.info( "No mac address found in %s" % response )
764 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800765 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800766 main.log.info(
767 "Mac-Address of " +
768 host +
769 ":" +
770 interface +
771 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800772 macAddress )
773 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800774 else:
775 main.log.error( "Connection failed to the host" )
776
777 def getIPAddress( self, host ):
778 """
779 Verifies the host's ip configured or not."""
780 if self.handle:
781 try:
782 response = self.execute(
783 cmd=host +
784 " ifconfig",
785 prompt="mininet>",
786 timeout=10 )
787 except pexpect.EOF:
788 main.log.error( self.name + ": EOF exception found" )
789 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700790 main.cleanup()
791 main.exit()
adminbae64d82013-08-01 10:50:15 -0700792
793 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800794 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800795 main.log.info(
796 self.name +
797 ": IP-Address of Host " +
798 host +
799 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800800 ipAddressSearch.group( 1 ) )
801 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800802 else:
803 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800804
Jon Hall7eb38402015-01-08 17:19:54 -0800805 def getSwitchDPID( self, switch ):
806 """
807 return the datapath ID of the switch"""
808 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700809 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700810 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800811 response = self.execute(
812 cmd=cmd,
813 prompt="mininet>",
814 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800815 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800816 main.log.error( self.name + ": EOF exception found" )
817 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700818 main.cleanup()
819 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800820 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800821 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700822 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800823 main.log.info(
824 "Couldn't find DPID for switch %s, found: %s" %
825 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700826 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800827 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700828 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800829 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700830
Jon Hall7eb38402015-01-08 17:19:54 -0800831 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700832 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800833 self.handle.sendline( "" )
834 self.expect( "mininet>" )
835 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700836 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800837 response = self.execute(
838 cmd=cmd,
839 prompt="mininet>",
840 timeout=10 )
841 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700842 response = self.handle.before
843 return response
844 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800845 main.log.error( self.name + ": EOF exception found" )
846 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700847 main.cleanup()
848 main.exit()
849
Jon Hall7eb38402015-01-08 17:19:54 -0800850 def getInterfaces( self, node ):
851 """
852 return information dict about interfaces connected to the node"""
853 if self.handle:
854 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800855 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700856 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700857 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800858 response = self.execute(
859 cmd=cmd,
860 prompt="mininet>",
861 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800862 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800863 main.log.error( self.name + ": EOF exception found" )
864 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700865 main.cleanup()
866 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700867 return response
868 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800869 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700870
Jon Hall7eb38402015-01-08 17:19:54 -0800871 def dump( self ):
872 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700873 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800874 response = self.execute(
875 cmd='dump',
876 prompt='mininet>',
877 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800878 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800879 main.log.error( self.name + ": EOF exception found" )
880 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700881 main.cleanup()
882 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700883 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800884
Jon Hall7eb38402015-01-08 17:19:54 -0800885 def intfs( self ):
886 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700887 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800888 response = self.execute(
889 cmd='intfs',
890 prompt='mininet>',
891 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800892 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800893 main.log.error( self.name + ": EOF exception found" )
894 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700895 main.cleanup()
896 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700897 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800898
Jon Hall7eb38402015-01-08 17:19:54 -0800899 def net( self ):
900 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700901 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800902 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800903 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800904 main.log.error( self.name + ": EOF exception found" )
905 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700906 main.cleanup()
907 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700908 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800909
Jon Hallafa8a472015-06-12 14:02:42 -0700910 def links( self ):
911 main.log.info( self.name + ": List network links" )
912 try:
913 response = self.execute( cmd='links', prompt='mininet>',
914 timeout=10 )
915 except pexpect.EOF:
916 main.log.error( self.name + ": EOF exception found" )
917 main.log.error( self.name + ": " + self.handle.before )
918 main.cleanup()
919 main.exit()
920 return response
921
Jon Hall7eb38402015-01-08 17:19:54 -0800922 def iperf( self, host1, host2 ):
923 main.log.info(
924 self.name +
925 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700926 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800927 cmd1 = 'iperf ' + host1 + " " + host2
928 self.handle.sendline( cmd1 )
929 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800930 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800931 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800932 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800933 return main.TRUE
934 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800935 main.log.error( self.name + ": iperf test failed" )
936 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800937 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800938 main.log.error( self.name + ": EOF exception found" )
939 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800940 main.cleanup()
941 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800942
Jon Hall7eb38402015-01-08 17:19:54 -0800943 def iperfudp( self ):
944 main.log.info(
945 self.name +
946 ": Simple iperf TCP test between two " +
947 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700948 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800949 response = self.execute(
950 cmd='iperfudp',
951 prompt='mininet>',
952 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800953 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800954 main.log.error( self.name + ": EOF exception found" )
955 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700956 main.cleanup()
957 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700958 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800959
Jon Hall7eb38402015-01-08 17:19:54 -0800960 def nodes( self ):
961 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700962 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800963 response = self.execute(
964 cmd='nodes',
965 prompt='mininet>',
966 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800967 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800968 main.log.error( self.name + ": EOF exception found" )
969 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700970 main.cleanup()
971 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700972 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800973
Jon Hall7eb38402015-01-08 17:19:54 -0800974 def pingpair( self ):
975 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700976 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800977 response = self.execute(
978 cmd='pingpair',
979 prompt='mininet>',
980 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800981 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800982 main.log.error( self.name + ": EOF exception found" )
983 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700984 main.cleanup()
985 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800986
Jon Hall7eb38402015-01-08 17:19:54 -0800987 if re.search( ',\s0\%\spacket\sloss', response ):
988 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800989 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700990 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800991 else:
992 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800993 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700994 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800995
Jon Hall7eb38402015-01-08 17:19:54 -0800996 def link( self, **linkargs ):
997 """
998 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800999 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001000 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
1001 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
1002 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
1003 main.log.info(
1004 "Bring link between '" +
1005 end1 +
1006 "' and '" +
1007 end2 +
1008 "' '" +
1009 option +
1010 "'" )
1011 command = "link " + \
1012 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -07001013 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001014 self.handle.sendline( command )
1015 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001016 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001017 main.log.error( self.name + ": EOF exception found" )
1018 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001019 main.cleanup()
1020 main.exit()
adminbae64d82013-08-01 10:50:15 -07001021 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001022
Jon Hall7eb38402015-01-08 17:19:54 -08001023 def yank( self, **yankargs ):
1024 """
1025 yank a mininet switch interface to a host"""
1026 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001027 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001028 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1029 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1030 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001031 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001032 response = self.execute(
1033 cmd=command,
1034 prompt="mininet>",
1035 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001036 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001037 main.log.error( self.name + ": EOF exception found" )
1038 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001039 main.cleanup()
1040 main.exit()
adminaeedddd2013-08-02 15:14:15 -07001041 return main.TRUE
1042
Jon Hall7eb38402015-01-08 17:19:54 -08001043 def plug( self, **plugargs ):
1044 """
1045 plug the yanked mininet switch interface to a switch"""
1046 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001047 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001048 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1049 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
1050 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -07001051 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001052 response = self.execute(
1053 cmd=command,
1054 prompt="mininet>",
1055 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001056 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001057 main.log.error( self.name + ": EOF exception found" )
1058 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001059 main.cleanup()
1060 main.exit()
adminbae64d82013-08-01 10:50:15 -07001061 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001062
Jon Hall7eb38402015-01-08 17:19:54 -08001063 def dpctl( self, **dpctlargs ):
1064 """
1065 Run dpctl command on all switches."""
1066 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001067 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001068 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1069 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1070 command = "dpctl " + cmd + " " + str( cmdargs )
1071 try:
1072 response = self.execute(
1073 cmd=command,
1074 prompt="mininet>",
1075 timeout=10 )
1076 except pexpect.EOF:
1077 main.log.error( self.name + ": EOF exception found" )
1078 main.log.error( self.name + ": " + self.handle.before )
1079 main.cleanup()
1080 main.exit()
1081 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001082
kelvin-onlabd3b64892015-01-20 13:26:24 -08001083 def getVersion( self ):
Jon Hallff6b4b22015-02-23 09:25:15 -08001084 #FIXME: What uses this? This should be refactored to get
1085 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001086 fileInput = path + '/lib/Mininet/INSTALL'
1087 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001088 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001089 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001090 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001091 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001092 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001093 return version
adminbae64d82013-08-01 10:50:15 -07001094
kelvin-onlabd3b64892015-01-20 13:26:24 -08001095 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001096 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001097 Parameters:
1098 sw: The name of an OVS switch. Example "s1"
1099 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001100 The output of the command from the mininet cli
1101 or main.FALSE on timeout"""
1102 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001103 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001104 response = self.execute(
1105 cmd=command,
1106 prompt="mininet>",
1107 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001108 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001109 return response
admin2a9548d2014-06-17 14:08:07 -07001110 else:
1111 return main.FALSE
1112 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001113 main.log.error( self.name + ": EOF exception found" )
1114 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001115 main.cleanup()
1116 main.exit()
adminbae64d82013-08-01 10:50:15 -07001117
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001118 def assignSwController( self, sw, ip, port="6633", ptcp="" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001119 """
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001120 Description:
1121 Assign switches to the controllers ( for ovs use only )
1122 Required:
1123 sw - Name of the switch. This can be a list or a string.
1124 ip - Ip addresses of controllers. This can be a list or a string.
1125 Optional:
1126 port - ONOS use port 6633, if no list of ports is passed, then
1127 the all the controller will use 6633 as their port number
1128 ptcp - ptcp number, This can be a string or a list that has
1129 the same length as switch. This is optional and not required
1130 when using ovs switches.
1131 NOTE: If switches and ptcp are given in a list type they should have the
1132 same length and should be in the same order, Eg. sw=[ 's1' ... n ]
1133 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on.
Jon Hallf89c8552014-04-02 13:14:06 -07001134
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001135 Return:
1136 Returns main.TRUE if mininet correctly assigned switches to
1137 controllers, otherwise it will return main.FALSE or an appropriate
1138 exception(s)
1139 """
1140 assignResult = main.TRUE
1141 # Initial ovs command
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001142 commandList = []
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001143 command = "sh ovs-vsctl set-controller "
1144 onosIp = ""
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001145 try:
1146 if isinstance( ip, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001147 onosIp = "tcp:" + str( ip ) + ":"
kelvin-onlab5c2df432015-06-11 17:29:56 -07001148 if isinstance( port, types.StringType ) or \
1149 isinstance( port, types.IntType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001150 onosIp += str( port )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001151 elif isinstance( port, types.ListType ):
1152 main.log.error( self.name + ": Only one controller " +
1153 "assigned and a list of ports has" +
1154 " been passed" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001155 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001156 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001157 main.log.error( self.name + ": Invalid controller port " +
1158 "number. Please specify correct " +
1159 "controller port" )
1160 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001161
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001162 elif isinstance( ip, types.ListType ):
kelvin-onlab5c2df432015-06-11 17:29:56 -07001163 if isinstance( port, types.StringType ) or \
1164 isinstance( port, types.IntType ):
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001165 for ipAddress in ip:
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001166 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1167 str( port ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001168 elif isinstance( port, types.ListType ):
1169 if ( len( ip ) != len( port ) ):
1170 main.log.error( self.name + ": Port list = " +
1171 str( len( port ) ) +
1172 "should be the same as controller" +
1173 " ip list = " + str( len( ip ) ) )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001174 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001175 else:
1176 onosIp = ""
1177 for ipAddress, portNum in zip( ip, port ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001178 onosIp += "tcp:" + str( ipAddress ) + ":" + \
1179 str( portNum ) + " "
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001180 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001181 main.log.error( self.name + ": Invalid controller port " +
1182 "number. Please specify correct " +
1183 "controller port" )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001184 return main.FALSE
kelvin-onlabe5edb9e2015-06-12 09:38:47 -07001185 else:
1186 main.log.error( self.name + ": Invalid ip address" )
1187 return main.FALSE
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001188
1189 if isinstance( sw, types.StringType ):
1190 command += sw + " "
1191 if ptcp:
1192 if isinstance( ptcp, types.StringType ):
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001193 command += "ptcp:" + str( ptcp ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001194 elif isinstance( ptcp, types.ListType ):
1195 main.log.error( self.name + ": Only one switch is " +
1196 "being set and multiple PTCP is " +
1197 "being passed " )
1198 else:
1199 main.log.error( self.name + ": Invalid PTCP" )
1200 ptcp = ""
1201 command += onosIp
1202 commandList.append( command )
1203
1204 elif isinstance( sw, types.ListType ):
1205 if ptcp:
1206 if isinstance( ptcp, types.ListType ):
1207 if len( ptcp ) != len( sw ):
1208 main.log.error( self.name + ": PTCP length = " +
1209 str( len( ptcp ) ) +
1210 " is not the same as switch" +
1211 " length = " +
1212 str( len( sw ) ) )
1213 return main.FALSE
1214 else:
1215 for switch, ptcpNum in zip( sw, ptcp ):
1216 tempCmd = "sh ovs-vsctl set-controller "
kelvin-onlabf713d7c2015-06-11 14:29:05 -07001217 tempCmd += switch + " ptcp:" + \
1218 str( ptcpNum ) + " "
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001219 tempCmd += onosIp
1220 commandList.append( tempCmd )
1221 else:
1222 main.log.error( self.name + ": Invalid PTCP" )
1223 return main.FALSE
1224 else:
1225 for switch in sw:
1226 tempCmd = "sh ovs-vsctl set-controller "
1227 tempCmd += switch + " " + onosIp
1228 commandList.append( tempCmd )
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001229 else:
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001230 main.log.error( self.name + ": Invalid switch type " )
1231 return main.FALSE
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001232
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001233 for cmd in commandList:
1234 try:
kelvin-onlabfa6ada82015-06-11 13:06:24 -07001235 self.execute( cmd=cmd, prompt="mininet>", timeout=5 )
kelvin-onlab4f9f7e02015-06-11 14:07:20 -07001236 except pexpect.TIMEOUT:
1237 main.log.error( self.name + ": pexpect.TIMEOUT found" )
1238 return main.FALSE
1239 except pexpect.EOF:
1240 main.log.error( self.name + ": EOF exception found" )
1241 main.log.error( self.name + ": " + self.handle.before )
1242 main.cleanup()
1243 main.exit()
1244 return main.TRUE
1245 except Exception:
1246 main.log.exception( self.name + ": Uncaught exception!" )
1247 main.cleanup()
1248 main.exit()
adminbae64d82013-08-01 10:50:15 -07001249
kelvin-onlabd3b64892015-01-20 13:26:24 -08001250 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001251 """
1252 Removes the controller target from sw"""
1253 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001254 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001255 response = self.execute(
1256 cmd=command,
1257 prompt="mininet>",
1258 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001259 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001260 main.log.error( self.name + ": EOF exception found" )
1261 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001262 main.cleanup()
1263 main.exit()
1264 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001265 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001266
kelvin-onlabd3b64892015-01-20 13:26:24 -08001267 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001268 """
Jon Hallb1290e82014-11-18 16:17:48 -05001269 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001270 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001271 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001272 NOTE: cannot currently specify what type of switch
1273 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001274 sw = name of the new switch as a string
1275 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001276 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001277 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001278 """
1279 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001280 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001281 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001282 response = self.execute(
1283 cmd=command,
1284 prompt="mininet>",
1285 timeout=10 )
1286 if re.search( "already exists!", response ):
1287 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001288 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001289 elif re.search( "Error", response ):
1290 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001291 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001292 elif re.search( "usage:", response ):
1293 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001294 return main.FALSE
1295 else:
1296 return main.TRUE
1297 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001298 main.log.error( self.name + ": EOF exception found" )
kaouthera3f13ca22015-05-05 15:01:41 -07001299 main.log.error(self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001300 main.cleanup()
1301 main.exit()
1302
kelvin-onlabd3b64892015-01-20 13:26:24 -08001303 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001304 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001305 delete a switch from the mininet topology
1306 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001307 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001308 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001309 sw = name of the switch as a string
1310 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001311 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001312 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001313 response = self.execute(
1314 cmd=command,
1315 prompt="mininet>",
1316 timeout=10 )
1317 if re.search( "no switch named", response ):
1318 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001319 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001320 elif re.search( "Error", response ):
1321 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001322 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001323 elif re.search( "usage:", response ):
1324 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001325 return main.FALSE
1326 else:
1327 return main.TRUE
1328 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001329 main.log.error( self.name + ": EOF exception found" )
1330 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001331 main.cleanup()
1332 main.exit()
1333
kelvin-onlabd3b64892015-01-20 13:26:24 -08001334 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001335 """
1336 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001337 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001338 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001339 NOTE: cannot currently specify what type of link
1340 required params:
1341 node1 = the string node name of the first endpoint of the link
1342 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001343 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001344 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001345 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001346 response = self.execute(
1347 cmd=command,
1348 prompt="mininet>",
1349 timeout=10 )
1350 if re.search( "doesnt exist!", response ):
1351 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001352 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001353 elif re.search( "Error", response ):
1354 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001355 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001356 elif re.search( "usage:", response ):
1357 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001358 return main.FALSE
1359 else:
1360 return main.TRUE
1361 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001362 main.log.error( self.name + ": EOF exception found" )
1363 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001364 main.cleanup()
1365 main.exit()
1366
kelvin-onlabd3b64892015-01-20 13:26:24 -08001367 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001368 """
1369 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001370 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001371 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001372 required params:
1373 node1 = the string node name of the first endpoint of the link
1374 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001375 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001376 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001377 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001378 response = self.execute(
1379 cmd=command,
1380 prompt="mininet>",
1381 timeout=10 )
1382 if re.search( "no node named", response ):
1383 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001384 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001385 elif re.search( "Error", response ):
1386 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001387 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001388 elif re.search( "usage:", response ):
1389 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001390 return main.FALSE
1391 else:
1392 return main.TRUE
1393 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001394 main.log.error( self.name + ": EOF exception found" )
1395 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001396 main.cleanup()
1397 main.exit()
1398
kelvin-onlabd3b64892015-01-20 13:26:24 -08001399 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001400 """
Jon Hallb1290e82014-11-18 16:17:48 -05001401 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001402 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001403 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001404 NOTE: cannot currently specify what type of host
1405 required params:
1406 hostname = the string hostname
1407 optional key-value params
1408 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001409 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001410 """
1411 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001412 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001413 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001414 response = self.execute(
1415 cmd=command,
1416 prompt="mininet>",
1417 timeout=10 )
1418 if re.search( "already exists!", response ):
1419 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001420 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001421 elif re.search( "doesnt exists!", response ):
1422 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001423 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001424 elif re.search( "Error", response ):
1425 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001426 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001427 elif re.search( "usage:", response ):
1428 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001429 return main.FALSE
1430 else:
1431 return main.TRUE
1432 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001433 main.log.error( self.name + ": EOF exception found" )
1434 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001435 main.cleanup()
1436 main.exit()
1437
kelvin-onlabd3b64892015-01-20 13:26:24 -08001438 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001439 """
1440 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001441 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001442 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001443 NOTE: this uses a custom mn function
1444 required params:
1445 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001446 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001447 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001448 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001449 response = self.execute(
1450 cmd=command,
1451 prompt="mininet>",
1452 timeout=10 )
1453 if re.search( "no host named", response ):
1454 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001455 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001456 elif re.search( "Error", response ):
1457 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001458 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001459 elif re.search( "usage:", response ):
1460 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001461 return main.FALSE
1462 else:
1463 return main.TRUE
1464 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001465 main.log.error( self.name + ": EOF exception found" )
1466 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001467 main.cleanup()
1468 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001469
Jon Hall7eb38402015-01-08 17:19:54 -08001470 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001471 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001472 Called at the end of the test to stop the mininet and
1473 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001474 """
1475 self.handle.sendline('')
Jon Halld61331b2015-02-17 16:35:47 -08001476 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Hallefbd9792015-03-05 16:11:36 -08001477 timeout=2)
Jon Hall390696c2015-05-05 17:13:41 -07001478 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001479 if i == 0:
Jon Hall390696c2015-05-05 17:13:41 -07001480 response = self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001481 elif i == 1:
1482 return main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001483 # print "Disconnecting Mininet"
1484 if self.handle:
1485 self.handle.sendline( "exit" )
1486 self.handle.expect( "exit" )
1487 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001488 else:
1489 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001490 return response
1491
Hari Krishnab35c6d02015-03-18 11:13:51 -07001492 def stopNet( self, fileName = "", timeout=5):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001493 """
Jon Hall21270ac2015-02-16 17:59:55 -08001494 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001495 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001496 main.FALSE if the pexpect handle does not exist.
1497
Jon Halld61331b2015-02-17 16:35:47 -08001498 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001499 """
Jon Hall21270ac2015-02-16 17:59:55 -08001500
Jon Halld61331b2015-02-17 16:35:47 -08001501 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001502 response = ''
1503 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001504 try:
kelvin-onlab26bc17f2015-02-06 14:08:59 -08001505 self.handle.sendline("")
kelvin-onlab56a3f462015-02-06 14:04:43 -08001506 i = self.handle.expect( [ 'mininet>',
1507 '\$',
1508 pexpect.EOF,
1509 pexpect.TIMEOUT ],
1510 timeout )
1511 if i == 0:
1512 main.log.info( "Exiting mininet..." )
Jon Hall7eb38402015-01-08 17:19:54 -08001513 response = self.execute(
1514 cmd="exit",
1515 prompt="(.*)",
1516 timeout=120 )
Jon Halld61331b2015-02-17 16:35:47 -08001517 main.log.info( self.name + ": Stopped")
Jon Hall7eb38402015-01-08 17:19:54 -08001518 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001519 response = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001520
kelvin-onlab56a3f462015-02-06 14:04:43 -08001521 if i == 1:
1522 main.log.info( " Mininet trying to exit while not " +
1523 "in the mininet prompt" )
1524 elif i == 2:
1525 main.log.error( "Something went wrong exiting mininet" )
1526 elif i == 3: # timeout
1527 main.log.error( "Something went wrong exiting mininet " +
1528 "TIMEOUT" )
Jon Hallafa8a472015-06-12 14:02:42 -07001529
Hari Krishnab35c6d02015-03-18 11:13:51 -07001530 if fileName:
1531 self.handle.sendline("")
1532 self.handle.expect('\$')
1533 self.handle.sendline("sudo kill -9 \`ps -ef | grep \""+ fileName +"\" | grep -v grep | awk '{print $2}'\`")
Jon Hallfbc828e2015-01-06 17:30:19 -08001534 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001535 main.log.error( self.name + ": EOF exception found" )
1536 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001537 main.cleanup()
1538 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001539 else:
1540 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001541 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001542 return response
1543
kelvin-onlabf0594d72015-05-19 17:25:12 -07001544 def arping( self, host="", ip="10.128.20.211", ethDevice="" ):
kelvin-onlab65782a82015-05-07 14:12:13 -07001545 """
1546 Description:
1547 Sends arp message from mininet host for hosts discovery
1548 Required:
1549 host - hosts name
1550 Optional:
1551 ip - ip address that does not exist in the network so there would
1552 be no reply.
1553 """
kelvin-onlabf0594d72015-05-19 17:25:12 -07001554 if ethDevice:
1555 ethDevice = '-I ' + ethDevice + ' '
1556 cmd = " py " + host + ".cmd(\"arping -c 1 " + ethDevice + ip + "\")"
admin07529932013-11-22 14:58:28 -08001557 try:
kelvin-onlab65782a82015-05-07 14:12:13 -07001558 main.log.warn( "Sending: " + cmd )
1559 self.handle.sendline( cmd )
1560 response = self.handle.before
1561 self.handle.sendline( "" )
1562 self.handle.expect( "mininet>" )
admin07529932013-11-22 14:58:28 -08001563 return main.TRUE
kelvin-onlab65782a82015-05-07 14:12:13 -07001564
1565 except pexpect.EOF:
1566 main.log.error( self.name + ": EOF exception found" )
1567 main.log.error( self.name + ": " + self.handle.before )
1568 main.cleanup()
1569 main.exit()
admin07529932013-11-22 14:58:28 -08001570
Jon Hall7eb38402015-01-08 17:19:54 -08001571 def decToHex( self, num ):
1572 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001573
Jon Hall7eb38402015-01-08 17:19:54 -08001574 def getSwitchFlowCount( self, switch ):
1575 """
1576 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001577 if self.handle:
1578 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1579 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001580 response = self.execute(
1581 cmd=cmd,
1582 prompt="mininet>",
1583 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001584 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001585 main.log.error( self.name + ": EOF exception found" )
1586 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001587 main.cleanup()
1588 main.exit()
1589 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001590 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001591 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001592 main.log.info(
1593 "Couldn't find flows on switch %s, found: %s" %
1594 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001595 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001596 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001597 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001598 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001599
kelvin-onlabd3b64892015-01-20 13:26:24 -08001600 def checkFlows( self, sw, dumpFormat=None ):
1601 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001602 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001603 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001604 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001605 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001606 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001607 response = self.execute(
1608 cmd=command,
1609 prompt="mininet>",
1610 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001611 return response
1612 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001613 main.log.error( self.name + ": EOF exception found" )
1614 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001615 main.cleanup()
1616 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001617
kelvin-onlabd3b64892015-01-20 13:26:24 -08001618 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001619 """
Jon Hallefbd9792015-03-05 16:11:36 -08001620 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001621 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001622 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001623 self.handle.sendline( "" )
1624 self.handle.expect( "mininet>" )
1625 self.handle.sendline(
1626 "sh sudo tcpdump -n -i " +
1627 intf +
1628 " " +
1629 port +
1630 " -w " +
1631 filename.strip() +
1632 " &" )
1633 self.handle.sendline( "" )
1634 i = self.handle.expect( [ 'No\ssuch\device',
1635 'listening\son',
1636 pexpect.TIMEOUT,
1637 "mininet>" ],
1638 timeout=10 )
1639 main.log.warn( self.handle.before + self.handle.after )
1640 self.handle.sendline( "" )
1641 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001642 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001643 main.log.error(
1644 self.name +
1645 ": tcpdump - No such device exists. " +
1646 "tcpdump attempted on: " +
1647 intf )
admin2a9548d2014-06-17 14:08:07 -07001648 return main.FALSE
1649 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001650 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001651 return main.TRUE
1652 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001653 main.log.error(
1654 self.name +
1655 ": tcpdump command timed out! Check interface name," +
1656 " given interface was: " +
1657 intf )
admin2a9548d2014-06-17 14:08:07 -07001658 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001659 elif i == 3:
1660 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001661 return main.TRUE
1662 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001663 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001664 return main.FALSE
1665 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001666 main.log.error( self.name + ": EOF exception found" )
1667 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001668 main.cleanup()
1669 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001670 except Exception:
1671 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001672 main.cleanup()
1673 main.exit()
1674
kelvin-onlabd3b64892015-01-20 13:26:24 -08001675 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001676 """
1677 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001678 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001679 self.handle.sendline( "sh sudo pkill tcpdump" )
1680 self.handle.expect( "mininet>" )
1681 self.handle.sendline( "" )
1682 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001683 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001684 main.log.error( self.name + ": EOF exception found" )
1685 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001686 main.cleanup()
1687 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001688 except Exception:
1689 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001690 main.cleanup()
1691 main.exit()
1692
Jon Hallafa8a472015-06-12 14:02:42 -07001693 def getPorts(self, nodeName, verbose=False ):
1694 """
1695 Read ports from a Mininet switch.
1696
1697 Returns a json structure containing information about the
1698 ports of the given switch.
1699 """
1700 response = self.getInterfaces( nodeName )
1701 # TODO: Sanity check on response. log if no such switch exists
1702 ports = []
1703 for line in response.split( "\n" ):
1704 if not line.startswith( "name=" ):
1705 continue
1706 portVars = {}
1707 for var in line.split( "," ):
1708 key, value = var.split( "=" )
1709 portVars[ key ] = value
1710 isUp = portVars.pop( 'enabled', "True" )
1711 isUp = "True" in isUp
1712 if verbose:
1713 main.log.info( "Reading switch port %s(%s)" %
1714 ( portVars[ 'name' ], portVars[ 'mac' ] ) )
1715 mac = portVars[ 'mac' ]
1716 if mac== 'None':
1717 mac = None
1718 ips = []
1719 ip = portVars[ 'ip' ]
1720 if ip == 'None':
1721 ip = None
1722 ips.append( ip )
1723 name = portVars[ 'name' ]
1724 if name == 'None':
1725 name = None
1726 portRe = r'[^\-]\d\-eth(?P<port>\d+)'
1727 if name == 'lo':
1728 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo?
1729 else:
1730 portNo = re.search( portRe, name ).group( 'port' )
1731 ports.append( { 'of_port': portNo,
1732 'mac': str( mac ).replace( '\'', '' ),
1733 'name': name,
1734 'ips': ips,
1735 'enabled': isUp } )
1736 return ports
1737
1738 def getSwitches(self, verbose=False ):
1739 """
1740 Read switches from Mininet.
1741
1742 Returns a dictionary whose keys are the switch names and the value is
1743 a dictionary containing information about the switch.
1744 """
1745 # FIXME: This currently only works with OVS Switches
1746
1747 # Regex patterns to parse dump output
1748 # Example Switch:
1749 # <OVSSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=5238>
1750 # <OVSSwitch{'protocols': 'OpenFlow10'} s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974>
1751 swRE = r"<OVSSwitch(\{.*\})?\s(?P<name>[^:]+)\:\s" +\
1752 "(?P<ports>([^,]+,)*[^,\s]+)"
1753 # Update mn port info
1754 self.update()
1755 output = { }
1756 dump = self.dump().split( "\n" )
1757 for line in dump:
1758 if line.startswith( "<OVSSwitch" ):
1759 result = re.search( swRE, line, re.I )
1760 name = result.group( 'name' )
1761 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 )
1762 if verbose:
1763 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) )
1764 ports = self.getPorts( name )
1765 output[ name ] = { "dpid": dpid, "ports": ports }
1766 return output
1767
1768 def getHosts(self, verbose=False):
1769 """
1770 Read hosts from Mininet.
1771
1772 Returns a dictionary whose keys are the host names and the value is
1773 a dictionary containing information about the host.
1774 """
1775 # Regex patterns to parse dump output
1776 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227>
1777 # or <Host h1: pid=12725>
1778 # NOTE: Does not correctly match hosts with multi-links
1779 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386>
1780 # FIXME: Fix that
1781 hostRE = r"<Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\
1782 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))"
1783 # update mn port info
1784 self.update()
1785 # Get mininet dump
1786 dump = self.dump().split( "\n" )
Jon Hall5b0120a2015-06-12 17:35:53 -07001787 hosts = {}
Jon Hallafa8a472015-06-12 14:02:42 -07001788 for line in dump:
1789 if line.startswith( "<Host" ):
1790 result = re.search( hostRE, line )
1791 name = result.group( 'name' )
1792 interfaces = []
1793 response = self.getInterfaces( name )
1794 # Populate interface info
1795 for line in response.split( "\n" ):
1796 if line.startswith( "name=" ):
1797 portVars = {}
1798 for var in line.split( "," ):
1799 key, value = var.split( "=" )
1800 portVars[ key ] = value
1801 isUp = portVars.pop( 'enabled', "True" )
1802 isUp = "True" in isUp
1803 if verbose:
1804 main.log.info( "Reading host port %s(%s)" %
1805 ( portVars[ 'name' ],
1806 portVars[ 'mac' ] ) )
1807 mac = portVars[ 'mac' ]
1808 if mac== 'None':
1809 mac = None
1810 ips = []
1811 ip = portVars[ 'ip' ]
1812 if ip == 'None':
1813 ip = None
1814 ips.append( ip )
1815 intfName = portVars[ 'name' ]
1816 if name == 'None':
1817 name = None
1818 interfaces.append( {
1819 "name": intfName,
1820 "ips": ips,
1821 "mac": str( mac ),
1822 "isUp": isUp } )
Jon Hall5b0120a2015-06-12 17:35:53 -07001823 hosts[ name ] = { "interfaces": interfaces }
Jon Hallafa8a472015-06-12 14:02:42 -07001824 return hosts
1825
1826 def getLinks( self ):
1827 """
1828 Gathers information about current Mininet links. These links may not
1829 be up if one of the ports is down.
1830
1831 Returns a list of dictionaries with link endpoints.
1832
1833 The dictionary structure is:
1834 { 'node1': str(node1 name)
1835 'node2': str(node2 name)
1836 'port1': str(port1 of_port)
1837 'port2': str(port2 of_port) }
1838 Note: The port number returned is the eth#, not necessarily the of_port
1839 number. In Mininet, for OVS switch, these should be the same. For
1840 hosts, this is just the eth#.
1841 """
1842 self.update()
1843 response = self.links().split( '\n' )
1844
1845 # Examples:
1846 # s1-eth3<->s2-eth1 (OK OK)
1847 # s13-eth3<->h27-eth0 (OK OK)
1848 linkRE = "(?P<node1>[\w]+)\-eth(?P<port1>[\d]+)\<\-\>" +\
1849 "(?P<node2>[\w]+)\-eth(?P<port2>[\d]+)"
1850 links = []
1851 for line in response:
1852 match = re.search( linkRE, line )
1853 if match:
1854 node1 = match.group( 'node1' )
1855 node2 = match.group( 'node2' )
1856 port1 = match.group( 'port1' )
1857 port2 = match.group( 'port2' )
1858 links.append( { 'node1': node1,
1859 'node2': node2,
1860 'port1': port1,
1861 'port2': port2 } )
1862 return links
1863
1864 def compareSwitches( self, switches, switchesJson, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001865 """
1866 Compare mn and onos switches
Jon Hallafa8a472015-06-12 14:02:42 -07001867 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001868
Jon Hallafa8a472015-06-12 14:02:42 -07001869 Dependencies:
1870 1. numpy - "sudo pip install numpy"
1871 """
1872 from numpy import uint64
Jon Hall3d87d502014-10-17 18:37:42 -04001873 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001874 mnDPIDs = []
Jon Hallafa8a472015-06-12 14:02:42 -07001875 for swName, switch in switches.iteritems():
Jon Hall7eb38402015-01-08 17:19:54 -08001876 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001877 mnDPIDs.sort()
kelvin-onlabd3b64892015-01-20 13:26:24 -08001878 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001879 main.log.error(
1880 self.name +
Jon Hallfeff3082015-05-19 10:23:26 -07001881 ".compareSwitches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001882 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001883 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001884 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001885 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001886 if switch[ 'available' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07001887 onosDPIDs.append( switch[ 'id' ].replace( ":", ''
1888 ).replace( "of", '' ).lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001889 onosDPIDs.sort()
Jon Hall3d87d502014-10-17 18:37:42 -04001890
Jon Hall7eb38402015-01-08 17:19:54 -08001891 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001892 switchResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07001893 main.log.error( "Switches in MN but not in ONOS:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001894 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001895 main.log.error( str( list1 ) )
1896 main.log.error( "Switches in ONOS but not in MN:" )
Jon Hall7eb38402015-01-08 17:19:54 -08001897 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
Jon Hallafa8a472015-06-12 14:02:42 -07001898 main.log.error( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001899 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001900 switchResults = main.TRUE
Jon Hallafa8a472015-06-12 14:02:42 -07001901 finalResults = switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001902
Jon Hall7eb38402015-01-08 17:19:54 -08001903 # FIXME: this does not look for extra ports in ONOS, only checks that
1904 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08001905 portsResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001906
Jon Hall7eb38402015-01-08 17:19:54 -08001907 # PORTS
Jon Hallafa8a472015-06-12 14:02:42 -07001908 for name, mnSwitch in switches.iteritems():
kelvin-onlabd3b64892015-01-20 13:26:24 -08001909 mnPorts = []
1910 onosPorts = []
1911 switchResult = main.TRUE
1912 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001913 if port[ 'enabled' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07001914 mnPorts.append( int( port[ 'of_port' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001915 for onosSwitch in portsJson:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001916 if onosSwitch[ 'device' ][ 'available' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07001917 if onosSwitch[ 'device' ][ 'id' ].replace( ':',''
1918 ).replace( "of", '' ) == mnSwitch[ 'dpid' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001919 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001920 if port[ 'isEnabled' ]:
1921 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001922 # onosPorts.append( 'local' )
1923 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001924 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001925 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001926 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001927 mnPorts.sort( key=float )
1928 onosPorts.sort( key=float )
Jon Hallafa8a472015-06-12 14:02:42 -07001929
kelvin-onlabd3b64892015-01-20 13:26:24 -08001930 mnPortsLog = mnPorts
1931 onosPortsLog = onosPorts
1932 mnPorts = [ x for x in mnPorts ]
1933 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001934
Jon Hall7eb38402015-01-08 17:19:54 -08001935 # TODO: handle other reserved port numbers besides LOCAL
1936 # NOTE: Reserved ports
1937 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1938 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001939 for mnPort in mnPortsLog:
1940 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001941 # don't set results to true here as this is just one of
1942 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001943 mnPorts.remove( mnPort )
1944 onosPorts.remove( mnPort )
Jon Hallafa8a472015-06-12 14:02:42 -07001945
Jon Hall7eb38402015-01-08 17:19:54 -08001946 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001947 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001948 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001949 if 65534 in mnPorts:
1950 mnPorts.remove( 65534 )
1951 if long( uint64( -2 ) ) in onosPorts:
1952 onosPorts.remove( long( uint64( -2 ) ) )
1953 if len( mnPorts ): # the ports of this switch don't match
1954 switchResult = main.FALSE
1955 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1956 if len( onosPorts ): # the ports of this switch don't match
1957 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001958 main.log.warn(
1959 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001960 str( onosPorts ) )
1961 if switchResult == main.FALSE:
Jon Hallafa8a472015-06-12 14:02:42 -07001962 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08001963 "The list of ports for switch %s(%s) does not match:" %
Jon Hallafa8a472015-06-12 14:02:42 -07001964 ( name, mnSwitch[ 'dpid' ] ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001965 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1966 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1967 portsResults = portsResults and switchResult
Jon Hallafa8a472015-06-12 14:02:42 -07001968 finalResults = finalResults and portsResults
1969 return finalResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001970
Jon Hallafa8a472015-06-12 14:02:42 -07001971 def compareLinks( self, switches, links, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001972 """
1973 Compare mn and onos links
kelvin-onlabd3b64892015-01-20 13:26:24 -08001974 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001975
Jon Hallafa8a472015-06-12 14:02:42 -07001976 """
Jon Hall7eb38402015-01-08 17:19:54 -08001977 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08001978 # ONOS has what is in MN
kelvin-onlabd3b64892015-01-20 13:26:24 -08001979 onos = linksJson
Jon Hall72cf1dc2014-10-20 21:04:50 -04001980
Jon Hallafa8a472015-06-12 14:02:42 -07001981 mnLinks = [ ]
1982 for l in links:
1983 try:
1984 node1 = switches[ l[ 'node1' ] ]
1985 node2 = switches[ l[ 'node2' ] ]
1986 enabled = True
1987 for port in node1[ 'ports' ]:
1988 if port[ 'of_port' ] == l[ 'port1' ]:
1989 enabled = enabled and port[ 'enabled' ]
1990 for port in node2[ 'ports' ]:
1991 if port[ 'of_port' ] == l[ 'port2']:
1992 enabled = enabled and port[ 'enabled' ]
1993 if enabled:
1994 mnLinks.append( l )
1995 except KeyError:
1996 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08001997 if 2 * len( mnLinks ) == len( onos ):
1998 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001999 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002000 linkResults = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002001 main.log.error(
Jon Hall328ddca2015-01-28 15:57:15 -08002002 "Mininet has " + str( len( mnLinks ) ) +
2003 " bidirectional links and ONOS has " +
2004 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002005
Jon Hall7eb38402015-01-08 17:19:54 -08002006 # iterate through MN links and check if an ONOS link exists in
2007 # both directions
kelvin-onlabd3b64892015-01-20 13:26:24 -08002008 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08002009 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04002010 node1 = None
2011 port1 = None
2012 node2 = None
2013 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08002014 firstDir = main.FALSE
2015 secondDir = main.FALSE
Jon Hallafa8a472015-06-12 14:02:42 -07002016 for swName, switch in switches.iteritems():
2017 if swName == link[ 'node1' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002018 node1 = switch[ 'dpid' ]
2019 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002020 if str( port[ 'of_port' ] ) == str( link[ 'port1' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002021 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002022 if node1 is not None and node2 is not None:
2023 break
Jon Hallafa8a472015-06-12 14:02:42 -07002024 if swName == link[ 'node2' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08002025 node2 = switch[ 'dpid' ]
2026 for port in switch[ 'ports' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002027 if str( port[ 'of_port' ] ) == str( link[ 'port2' ] ):
Jon Hall7eb38402015-01-08 17:19:54 -08002028 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002029 if node1 is not None and node2 is not None:
2030 break
2031
kelvin-onlabd3b64892015-01-20 13:26:24 -08002032 for onosLink in onos:
2033 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002034 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002035 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hallafa8a472015-06-12 14:02:42 -07002036 ":", '' ).replace( "of", '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002037 onosPort1 = onosLink[ 'src' ][ 'port' ]
2038 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04002039
Jon Hall72cf1dc2014-10-20 21:04:50 -04002040 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08002041 if str( onosNode1 ) == str( node1 ) and str(
2042 onosNode2 ) == str( node2 ):
2043 if int( onosPort1 ) == int( port1 ) and int(
2044 onosPort2 ) == int( port2 ):
2045 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002046 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002047 main.log.warn(
2048 'The port numbers do not match for ' +
2049 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002050 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002051 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002052 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002053 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002054 ( onosNode1, onosPort1, onosNode2, onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002055
2056 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08002057 elif ( str( onosNode1 ) == str( node2 ) and
2058 str( onosNode2 ) == str( node1 ) ):
2059 if ( int( onosPort1 ) == int( port2 )
2060 and int( onosPort2 ) == int( port1 ) ):
2061 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04002062 else:
Jon Hall7eb38402015-01-08 17:19:54 -08002063 main.log.warn(
2064 'The port numbers do not match for ' +
2065 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08002066 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08002067 'link %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002068 ( node1, port1, node2, port2 ) +
Jon Hall7eb38402015-01-08 17:19:54 -08002069 ' ONOS has the values %s/%s -> %s/%s' %
Jon Hallafa8a472015-06-12 14:02:42 -07002070 ( onosNode2, onosPort2, onosNode1, onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08002071 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04002072 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08002073 if not firstDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002074 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002075 'ONOS does not have the link %s/%s -> %s/%s' %
2076 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002077 if not secondDir:
Jon Hallafa8a472015-06-12 14:02:42 -07002078 main.log.error(
Jon Hall7eb38402015-01-08 17:19:54 -08002079 'ONOS does not have the link %s/%s -> %s/%s' %
2080 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002081 linkResults = linkResults and firstDir and secondDir
2082 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04002083
Jon Hallafa8a472015-06-12 14:02:42 -07002084 def compareHosts( self, hosts, hostsJson ):
Jon Hallff6b4b22015-02-23 09:25:15 -08002085 """
Jon Hallafa8a472015-06-12 14:02:42 -07002086 Compare mn and onos Hosts.
2087 Since Mininet hosts are quiet, ONOS will only know of them when they
2088 speak. For this reason, we will only check that the hosts in ONOS
2089 stores are in Mininet, and not vice versa.
Jon Hallff6b4b22015-02-23 09:25:15 -08002090
Jon Hallafa8a472015-06-12 14:02:42 -07002091 Arguments:
2092 hostsJson: parsed json object from the onos hosts api
2093 Returns:
2094 """
Jon Hallff6b4b22015-02-23 09:25:15 -08002095 import json
2096 hostResults = main.TRUE
Jon Hallff6b4b22015-02-23 09:25:15 -08002097 for onosHost in hostsJson:
2098 onosMAC = onosHost[ 'mac' ].lower()
2099 match = False
2100 for mnHost in hosts:
2101 for mnIntf in mnHost[ 'interfaces' ]:
Jon Hallafa8a472015-06-12 14:02:42 -07002102 if onosMAC == mnIntf[ 'mac' ].lower() :
Jon Hallff6b4b22015-02-23 09:25:15 -08002103 match = True
2104 for ip in mnIntf[ 'ips' ]:
Jon Hallfeff3082015-05-19 10:23:26 -07002105 if ip in onosHost[ 'ipAddresses' ]:
Jon Hallff6b4b22015-02-23 09:25:15 -08002106 pass # all is well
2107 else:
2108 # misssing ip
2109 main.log.error( "ONOS host " + onosHost[ 'id' ]
Jon Hallafa8a472015-06-12 14:02:42 -07002110 + " has a different IP(" +
2111 str( onosHost[ 'ipAddresses' ] ) +
2112 ") than the Mininet host(" +
2113 str( ip ) + ")." )
Jon Hallff6b4b22015-02-23 09:25:15 -08002114 output = json.dumps(
2115 onosHost,
2116 sort_keys=True,
2117 indent=4,
2118 separators=( ',', ': ' ) )
2119 main.log.info( output )
2120 hostResults = main.FALSE
2121 if not match:
2122 hostResults = main.FALSE
2123 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
2124 "corresponding Mininet host." )
2125 output = json.dumps( onosHost,
2126 sort_keys=True,
2127 indent=4,
2128 separators=( ',', ': ' ) )
2129 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08002130 return hostResults
2131
Jon Hallafa8a472015-06-12 14:02:42 -07002132 def getHostsOld( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08002133 """
2134 Returns a list of all hosts
2135 Don't ask questions just use it"""
2136 self.handle.sendline( "" )
2137 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04002138
Jon Hall7eb38402015-01-08 17:19:54 -08002139 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2140 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002141
kelvin-onlabd3b64892015-01-20 13:26:24 -08002142 handlePy = self.handle.before
2143 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2144 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07002145
Jon Hall7eb38402015-01-08 17:19:54 -08002146 self.handle.sendline( "" )
2147 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07002148
kelvin-onlabd3b64892015-01-20 13:26:24 -08002149 hostStr = handlePy.replace( "]", "" )
2150 hostStr = hostStr.replace( "'", "" )
2151 hostStr = hostStr.replace( "[", "" )
kelvin-onlab2ccad6e2015-05-18 10:36:54 -07002152 hostStr = hostStr.replace( " ", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002153 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04002154
kelvin-onlabd3b64892015-01-20 13:26:24 -08002155 return hostList
adminbae64d82013-08-01 10:50:15 -07002156
kelvin-onlabfa6ada82015-06-11 13:06:24 -07002157 def getHosts( self ):
2158 """
2159 Returns a list of all hosts
2160 Don't ask questions just use it"""
2161 self.handle.sendline( "" )
2162 self.handle.expect( "mininet>" )
2163
2164 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
2165 self.handle.expect( "mininet>" )
2166
2167 handlePy = self.handle.before
2168 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2169 handlePy = handlePy.rstrip()
2170
2171 self.handle.sendline( "" )
2172 self.handle.expect( "mininet>" )
2173
2174 hostStr = handlePy.replace( "]", "" )
2175 hostStr = hostStr.replace( "'", "" )
2176 hostStr = hostStr.replace( "[", "" )
2177 hostStr = hostStr.replace( " ", "" )
2178 hostList = hostStr.split( "," )
2179
2180 return hostList
2181
2182 def getSwitch( self ):
2183 """
2184 Returns a list of all switches
2185 Again, don't ask question just use it...
2186 """
2187 # get host list...
2188 hostList = self.getHosts()
2189 # Make host set
2190 hostSet = set( hostList )
2191
2192 # Getting all the nodes in mininet
2193 self.handle.sendline( "" )
2194 self.handle.expect( "mininet>" )
2195
2196 self.handle.sendline( "py [ node.name for node in net.values() ]" )
2197 self.handle.expect( "mininet>" )
2198
2199 handlePy = self.handle.before
2200 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
2201 handlePy = handlePy.rstrip()
2202
2203 self.handle.sendline( "" )
2204 self.handle.expect( "mininet>" )
2205
2206 nodesStr = handlePy.replace( "]", "" )
2207 nodesStr = nodesStr.replace( "'", "" )
2208 nodesStr = nodesStr.replace( "[", "" )
2209 nodesStr = nodesStr.replace( " ", "" )
2210 nodesList = nodesStr.split( "," )
2211
2212 nodesSet = set( nodesList )
2213 # discarding default controller(s) node
2214 nodesSet.discard( 'c0' )
2215 nodesSet.discard( 'c1' )
2216 nodesSet.discard( 'c2' )
2217
2218 switchSet = nodesSet - hostSet
2219 switchList = list( switchSet )
2220
2221 return switchList
2222
Jon Hall7eb38402015-01-08 17:19:54 -08002223 def update( self ):
2224 """
2225 updates the port address and status information for
2226 each port in mn"""
2227 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08002228 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05002229 try:
Jon Hall7eb38402015-01-08 17:19:54 -08002230 self.handle.sendline( "" )
2231 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002232
Jon Hall7eb38402015-01-08 17:19:54 -08002233 self.handle.sendline( "update" )
2234 self.handle.expect( "update" )
2235 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002236
Jon Hall7eb38402015-01-08 17:19:54 -08002237 self.handle.sendline( "" )
2238 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05002239
Jon Hallb1290e82014-11-18 16:17:48 -05002240 return main.TRUE
2241 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08002242 main.log.error( self.name + ": EOF exception found" )
2243 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05002244 main.cleanup()
2245 main.exit()
2246
kaouthera3f13ca22015-05-05 15:01:41 -07002247 def assignVLAN( self, host, intf, vlan):
2248 """
2249 Add vlan tag to a host.
2250 Dependencies:
2251 This class depends on the "vlan" package
2252 $ sudo apt-get install vlan
2253 Configuration:
2254 Load the 8021q module into the kernel
2255 $sudo modprobe 8021q
2256
2257 To make this setup permanent:
2258 $ sudo su -c 'echo "8021q" >> /etc/modules'
2259 """
2260 if self.handle:
2261 try:
2262 # get the ip address of the host
2263 main.log.info("Get the ip address of the host")
2264 ipaddr = self.getIPAddress(host)
2265 print repr(ipaddr)
2266
2267 # remove IP from interface intf
2268 # Ex: h1 ifconfig h1-eth0 inet 0
2269 main.log.info("Remove IP from interface ")
2270 cmd2 = host + " ifconfig " + intf + " " + " inet 0 "
2271 self.handle.sendline( cmd2 )
2272 self.handle.expect( "mininet>" )
2273 response = self.handle.before
2274 main.log.info ( "====> %s ", response)
2275
2276
2277 # create VLAN interface
2278 # Ex: h1 vconfig add h1-eth0 100
2279 main.log.info("Create Vlan")
2280 cmd3 = host + " vconfig add " + intf + " " + vlan
2281 self.handle.sendline( cmd3 )
2282 self.handle.expect( "mininet>" )
2283 response = self.handle.before
2284 main.log.info( "====> %s ", response )
2285
2286 # assign the host's IP to the VLAN interface
2287 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1
2288 main.log.info("Assign the host IP to the vlan interface")
2289 vintf = intf + "." + vlan
2290 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr
2291 self.handle.sendline( cmd4 )
2292 self.handle.expect( "mininet>" )
2293 response = self.handle.before
2294 main.log.info ( "====> %s ", response)
2295
2296
2297 return main.TRUE
2298 except pexpect.EOF:
2299 main.log.error( self.name + ": EOF exception found" )
2300 main.log.error( self.name + ": " + self.handle.before )
2301 return main.FALSE
2302
adminbae64d82013-08-01 10:50:15 -07002303if __name__ != "__main__":
2304 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07002305 sys.modules[ __name__ ] = MininetCliDriver()
kaouthera3f13ca22015-05-05 15:01:41 -07002306
2307