blob: 5b7da135072be15813542bd56457850ab0841079 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jon Hall7eb38402015-01-08 17:19:54 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
Jon Hallbe6dfc42015-01-12 17:37:25 -08005author: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
Jon Hall7eb38402015-01-08 17:19:54 -08008TestON is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 2 of the License, or
11( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
Jon Hall7eb38402015-01-08 17:19:54 -080013TestON is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
adminbae64d82013-08-01 10:50:15 -070017
Jon Hall7eb38402015-01-08 17:19:54 -080018You should have received a copy of the GNU General Public License
19along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
21
Jon Hallbe6dfc42015-01-12 17:37:25 -080022MininetCliDriver is the basic driver which will handle the Mininet functions
23
Jon Hall272a4db2015-01-12 17:43:48 -080024Some functions rely on STS module. To install this,
25 git clone https://github.com/jhall11/sts.git
26
Jon Hallbe6dfc42015-01-12 17:37:25 -080027Some functions rely on a modified version of Mininet. These functions
28should all be noted in the comments. To get this MN version run these commands
29from within your Mininet folder:
Jon Hall272a4db2015-01-12 17:43:48 -080030 git remote add jhall11 https://github.com/jhall11/mininet.git
Jon Hallbe6dfc42015-01-12 17:37:25 -080031 git fetch jhall11
Jon Hall272a4db2015-01-12 17:43:48 -080032 git checkout -b dynamic_topo remotes/jhall11/dynamic_topo
Jon Hallbe6dfc42015-01-12 17:37:25 -080033 git pull
34
Jon Hall272a4db2015-01-12 17:43:48 -080035
36 Note that you may need to run 'sudo make develop' if your mnexec.c file
Jon Hallbe6dfc42015-01-12 17:37:25 -080037changed when switching branches."""
adminbae64d82013-08-01 10:50:15 -070038import pexpect
adminbae64d82013-08-01 10:50:15 -070039import re
40import sys
Jon Hall7eb38402015-01-08 17:19:54 -080041sys.path.append( "../" )
Jon Hall1ccf82c2014-10-15 14:55:16 -040042from math import pow
adminbae64d82013-08-01 10:50:15 -070043from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070044
Jon Hall7eb38402015-01-08 17:19:54 -080045
kelvin-onlab50907142015-04-01 13:37:45 -070046class MininetCliDriver( Emulator ):
Jon Hall7eb38402015-01-08 17:19:54 -080047
48 """
49 MininetCliDriver is the basic driver which will handle
50 the Mininet functions"""
51 def __init__( self ):
52 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070053 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080054 self.name = None
Jon Hall7eb38402015-01-08 17:19:54 -080055 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070056 self.flag = 0
57
Jon Hall7eb38402015-01-08 17:19:54 -080058 def connect( self, **connectargs ):
59 """
60 Here the main is the TestON instance after creating
61 all the log handles."""
kelvin-onlaba1484582015-02-02 15:46:20 -080062 try:
63 for key in connectargs:
64 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080065
kelvin-onlaba1484582015-02-02 15:46:20 -080066 self.name = self.options[ 'name' ]
67 self.handle = super(
kelvin-onlab50907142015-04-01 13:37:45 -070068 MininetCliDriver,
kelvin-onlaba1484582015-02-02 15:46:20 -080069 self ).connect(
70 user_name=self.user_name,
71 ip_address=self.ip_address,
72 port=None,
73 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080074
kelvin-onlaba1484582015-02-02 15:46:20 -080075 if self.handle:
Jon Hallefbd9792015-03-05 16:11:36 -080076 main.log.info( "Connection successful to the host " +
77 self.user_name +
78 "@" +
79 self.ip_address )
kelvin-onlaba1484582015-02-02 15:46:20 -080080 return main.TRUE
81 else:
82 main.log.error( "Connection failed to the host " +
Jon Hallefbd9792015-03-05 16:11:36 -080083 self.user_name +
84 "@" +
85 self.ip_address )
Jon Hallfebb1c72015-03-05 13:30:09 -080086 main.log.error( "Failed to connect to the Mininet CLI" )
kelvin-onlaba1484582015-02-02 15:46:20 -080087 return main.FALSE
88 except pexpect.EOF:
89 main.log.error( self.name + ": EOF exception found" )
90 main.log.error( self.name + ": " + self.handle.before )
91 main.cleanup()
92 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -080093 except Exception:
94 main.log.exception( self.name + ": Uncaught exception!" )
kelvin-onlaba1484582015-02-02 15:46:20 -080095 main.cleanup()
96 main.exit()
97
Jon Hallefbd9792015-03-05 16:11:36 -080098 def startNet( self, topoFile='', args='', timeout=120 ):
kelvin-onlab00ac67b2015-02-04 09:52:02 -080099 """
100 Starts Mininet accepts a topology(.py) file and/or an optional
Jon Hallefbd9792015-03-05 16:11:36 -0800101 argument ,to start the mininet, as a parameter.
Jon Hall21270ac2015-02-16 17:59:55 -0800102 Returns main.TRUE if the mininet starts successfully and
103 main.FALSE otherwise
kelvin-onlab00ac67b2015-02-04 09:52:02 -0800104 """
Jon Hall7eb38402015-01-08 17:19:54 -0800105 if self.handle:
106 main.log.info(
107 self.name +
108 ": Clearing any residual state or processes" )
109 self.handle.sendline( "sudo mn -c" )
110 i = self.handle.expect( [ 'password\sfor\s',
111 'Cleanup\scomplete',
112 pexpect.EOF,
113 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800114 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800115 if i == 0:
116 main.log.info( self.name + ": Sending sudo password" )
117 self.handle.sendline( self.pwd )
Jon Hallefbd9792015-03-05 16:11:36 -0800118 i = self.handle.expect( [ '%s:' % self.user,
Jon Hall7eb38402015-01-08 17:19:54 -0800119 '\$',
120 pexpect.EOF,
121 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800122 timeout )
Jon Hall7eb38402015-01-08 17:19:54 -0800123 if i == 1:
124 main.log.info( self.name + ": Clean" )
125 elif i == 2:
126 main.log.error( self.name + ": Connection terminated" )
127 elif i == 3: # timeout
128 main.log.error(
129 self.name +
130 ": Something while cleaning MN took too long... " )
Jon Hallefbd9792015-03-05 16:11:36 -0800131 if topoFile == '' and args == '':
kelvin-onlaba1484582015-02-02 15:46:20 -0800132 main.log.info( self.name + ": building fresh mininet" )
133 # for reactive/PARP enabled tests
134 cmdString = "sudo mn " + self.options[ 'arg1' ] +\
135 " " + self.options[ 'arg2' ] +\
136 " --mac --controller " +\
137 self.options[ 'controller' ] + " " +\
138 self.options[ 'arg3' ]
Jon Hallfbc828e2015-01-06 17:30:19 -0800139
kelvin-onlaba1484582015-02-02 15:46:20 -0800140 argList = self.options[ 'arg1' ].split( "," )
141 global topoArgList
142 topoArgList = argList[ 0 ].split( " " )
143 argList = map( int, argList[ 1: ] )
144 topoArgList = topoArgList[ 1: ] + argList
Jon Hallfbc828e2015-01-06 17:30:19 -0800145
kelvin-onlaba1484582015-02-02 15:46:20 -0800146 self.handle.sendline( cmdString )
147 self.handle.expect( [ "sudo mn",
148 pexpect.EOF,
149 pexpect.TIMEOUT ] )
150 while True:
151 i = self.handle.expect( [ 'mininet>',
152 '\*\*\*',
153 'Exception',
154 pexpect.EOF,
155 pexpect.TIMEOUT ],
156 timeout )
157 if i == 0:
158 main.log.info( self.name + ": mininet built" )
159 return main.TRUE
160 if i == 1:
161 self.handle.expect(
162 [ "\n", pexpect.EOF, pexpect.TIMEOUT ] )
163 main.log.info( self.handle.before )
164 elif i == 2:
165 main.log.error(
166 self.name +
167 ": Launching mininet failed..." )
168 return main.FALSE
169 elif i == 3:
170 main.log.error( self.name + ": Connection timeout" )
171 return main.FALSE
172 elif i == 4: # timeout
173 main.log.error(
174 self.name +
175 ": Something took too long... " )
176 return main.FALSE
177 return main.TRUE
178 else:
179 main.log.info( "Starting topo file " + topoFile )
Jon Hallefbd9792015-03-05 16:11:36 -0800180 if args is None:
kelvin-onlaba1484582015-02-02 15:46:20 -0800181 args = ''
182 else:
183 main.log.info( "args = " + args)
184 self.handle.sendline( 'sudo ' + topoFile + ' ' + args)
Jon Hall7eb38402015-01-08 17:19:54 -0800185 i = self.handle.expect( [ 'mininet>',
Jon Hallefbd9792015-03-05 16:11:36 -0800186 pexpect.EOF,
187 pexpect.TIMEOUT ],
kelvin-onlaba1484582015-02-02 15:46:20 -0800188 timeout)
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800189 if i == 0:
190 main.log.info(self.name + ": Network started")
191 return main.TRUE
kelvin-onlabec228b82015-02-09 15:45:55 -0800192 elif i == 1:
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800193 main.log.error( self.name + ": Connection timeout" )
194 return main.FALSE
kelvin-onlabec228b82015-02-09 15:45:55 -0800195 elif i == 2: # timeout
kelvin-onlabef0cc1c2015-02-09 15:20:26 -0800196 main.log.error(
197 self.name +
198 ": Something took too long... " )
199 return main.FALSE
kelvin-onlaba1484582015-02-02 15:46:20 -0800200 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800201 else: # if no handle
202 main.log.error(
203 self.name +
204 ": Connection failed to the host " +
kelvin-onlab08679eb2015-01-21 16:11:48 -0800205 self.user_name +
Jon Hall7eb38402015-01-08 17:19:54 -0800206 "@" +
kelvin-onlab08679eb2015-01-21 16:11:48 -0800207 self.ip_address )
Jon Hall7eb38402015-01-08 17:19:54 -0800208 main.log.error( self.name + ": Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -0700209 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800210
kelvin-onlabfccaafa2015-01-20 13:50:44 -0800211 def numSwitchesNlinks( self, topoType, depth, fanout ):
Jon Hall1ccf82c2014-10-15 14:55:16 -0400212 if topoType == 'tree':
Jon Hall7eb38402015-01-08 17:19:54 -0800213 # In tree topology, if fanout arg is not given, by default it is 2
214 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400215 fanout = 2
216 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500217 count = 0
Jon Hall7eb38402015-01-08 17:19:54 -0800218 while( k <= depth - 1 ):
219 count = count + pow( fanout, k )
220 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800221 numSwitches = count
Jon Hall7eb38402015-01-08 17:19:54 -0800222 while( k <= depth - 2 ):
223 # depth-2 gives you only core links and not considering
224 # edge links as seen by ONOS. If all the links including
225 # edge links are required, do depth-1
226 count = count + pow( fanout, k )
227 k = k + 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800228 numLinks = count * fanout
Jon Hall7eb38402015-01-08 17:19:54 -0800229 # print "num_switches for %s(%d,%d) = %d and links=%d" %(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800230 # topoType,depth,fanout,numSwitches,numLinks )
Jon Hallfbc828e2015-01-06 17:30:19 -0800231
Jon Hall7eb38402015-01-08 17:19:54 -0800232 elif topoType == 'linear':
kelvin-onlabd3b64892015-01-20 13:26:24 -0800233 # In linear topology, if fanout or numHostsPerSw is not given,
Jon Hall7eb38402015-01-08 17:19:54 -0800234 # by default it is 1
235 if fanout is None:
Jon Hall1ccf82c2014-10-15 14:55:16 -0400236 fanout = 1
kelvin-onlabd3b64892015-01-20 13:26:24 -0800237 numSwitches = depth
238 numHostsPerSw = fanout
239 totalNumHosts = numSwitches * numHostsPerSw
240 numLinks = totalNumHosts + ( numSwitches - 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800241 print "num_switches for %s(%d,%d) = %d and links=%d" %\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800242 ( topoType, depth, fanout, numSwitches, numLinks )
Jon Hallefbd9792015-03-05 16:11:36 -0800243 topoDict = { "num_switches": int( numSwitches ),
244 "num_corelinks": int( numLinks ) }
Jon Hall1ccf82c2014-10-15 14:55:16 -0400245 return topoDict
246
kelvin-onlabd3b64892015-01-20 13:26:24 -0800247 def calculateSwAndLinks( self ):
248 topoDict = self.numSwitchesN_links( *topoArgList )
Jon Hall1ccf82c2014-10-15 14:55:16 -0400249 return topoDict
250
kelvin-onlabda2c5312015-04-02 15:59:29 -0700251 def pingall( self, timeout=300, shortCircuit=False, numFailedPings=1):
Jon Hall7eb38402015-01-08 17:19:54 -0800252 """
253 Verifies the reachability of the hosts using pingall command.
254 Optional parameter timeout allows you to specify how long to
255 wait for pingall to complete
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700256 Optional:
257 shortCircuit - Break the pingall based on the number of failed hosts
258 ping
259 numFailedPings - initialized the number required for the pingall to
260 break defaults to 1
Jon Hall7eb38402015-01-08 17:19:54 -0800261 Returns:
262 main.TRUE if pingall completes with no pings dropped
263 otherwise main.FALSE"""
264 if self.handle:
265 main.log.info(
266 self.name +
267 ": Checking reachabilty to the hosts using pingall" )
Jon Hall6094a362014-04-11 14:46:56 -0700268 try:
kelvin-onlabb9408212015-04-01 13:34:04 -0700269 if not shortCircuit:
270 response = self.execute(
271 cmd="pingall",
272 prompt="mininet>",
273 timeout=int( timeout ) )
274 else:
kelvin-onlabda2c5312015-04-02 15:59:29 -0700275 response = ""
kelvin-onlabb9408212015-04-01 13:34:04 -0700276 self.handle.sendline( "pingall" )
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700277 i = self.handle.expect( [ "mininet>","X",
kelvin-onlabb9408212015-04-01 13:34:04 -0700278 pexpect.EOF,
279 pexpect.TIMEOUT ],
280 timeout )
281 if i == 0:
kelvin-onlab38143812015-04-01 15:03:01 -0700282 main.log.info( "mininet> prompt found!" )
283 response = str( self.handle.before )
kelvin-onlabb9408212015-04-01 13:34:04 -0700284 if i == 1:
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700285 main.log.info( self.name +
286 ": Cannot ping some of the hosts")
287 failedPings = 1
kelvin-onlabda2c5312015-04-02 15:59:29 -0700288 while failedPings < numFailedPings:
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700289 j = self.handle.expect( [ "mininet>","X",
290 pexpect.EOF,
291 pexpect.TIMEOUT ],
292 timeout )
293 if j == 0:
294 main.log.info( self.name + ": pingall finished")
295 break
296 if j == 1:
297 failedPings = failedPings + 1
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700298 if j == 2:
299 main.log.error( self.name +
300 ": EOF exception found" )
301 main.log.error( self.name + ": " +
302 self.handle.before )
303 main.cleanup()
304 main.exit()
305 if j == 3:
306 main.log.error( self.name +
307 ": TIMEOUT exception found" )
308 main.log.error( self.name +
309 ": " +
310 str( self.handle.before ) )
311 break
312
kelvin-onlabda2c5312015-04-02 15:59:29 -0700313 main.log.info( self.name + ": failed to ping " +
314 str( failedPings ) + " host" )
kelvin-onlab38143812015-04-01 15:03:01 -0700315 main.log.info( str( self.handle.before ) )
316 response = str( self.handle.before )
kelvin-onlabb9408212015-04-01 13:34:04 -0700317 if i == 2:
318 main.log.error( self.name + ": EOF exception found" )
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700319 main.log.error( self.name + ": "
320 + self.handle.before )
kelvin-onlabb9408212015-04-01 13:34:04 -0700321 main.cleanup()
322 main.exit()
323 if i == 3:
kelvin-onlabfbcd82f2015-04-02 12:06:00 -0700324 main.log.error( self.name +
325 ": TIMEOUT exception found" )
kelvin-onlabb9408212015-04-01 13:34:04 -0700326 main.log.error( self.name +
327 ": " +
328 str( self.handle.before ) )
329
Jon Hallb1290e82014-11-18 16:17:48 -0500330 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800331 main.log.error( self.name + ": EOF exception found" )
332 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -0500333 main.cleanup()
334 main.exit()
335 except pexpect.TIMEOUT:
Jon Hall7eb38402015-01-08 17:19:54 -0800336 # We may not want to kill the test if pexpect times out
337 main.log.error( self.name + ": TIMEOUT exception found" )
338 main.log.error( self.name +
339 ": " +
340 str( self.handle.before ) )
341 # NOTE: mininet's pingall rounds, so we will check the number of
342 # passed and number of failed
343 pattern = "Results\:\s0\%\sdropped\s\(" +\
kelvin-onlabd3b64892015-01-20 13:26:24 -0800344 "(?P<passed>[\d]+)/(?P=passed)"
Jon Hall7eb38402015-01-08 17:19:54 -0800345 if re.search( pattern, response ):
346 main.log.info( self.name + ": All hosts are reachable" )
adminbae64d82013-08-01 10:50:15 -0700347 return main.TRUE
348 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800349 main.log.error( self.name + ": Unable to reach all the hosts" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800350 main.log.info( "Pingall output: " + str( response ) )
Jon Hall7eb38402015-01-08 17:19:54 -0800351 # NOTE: Send ctrl-c to make sure pingall is done
352 self.handle.send( "\x03" )
353 self.handle.expect( "Interrupt" )
354 self.handle.expect( "mininet>" )
adminbae64d82013-08-01 10:50:15 -0700355 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800356 else:
357 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallb1290e82014-11-18 16:17:48 -0500358 main.cleanup()
359 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700360
Jon Hall7eb38402015-01-08 17:19:54 -0800361 def fpingHost( self, **pingParams ):
362 """
363 Uses the fping package for faster pinging...
364 *requires fping to be installed on machine running mininet"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800365 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800366 command = args[ "SRC" ] + \
367 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ]
368 self.handle.sendline( command )
369 self.handle.expect(
370 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] )
371 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
372 response = self.handle.before
373 if re.search( ":\s-", response ):
374 main.log.info( self.name + ": Ping fail" )
adminaeedddd2013-08-02 15:14:15 -0700375 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800376 elif re.search( ":\s\d{1,2}\.\d\d", response ):
377 main.log.info( self.name + ": Ping good!" )
adminaeedddd2013-08-02 15:14:15 -0700378 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800379 main.log.info( self.name + ": Install fping on mininet machine... " )
380 main.log.info( self.name + ": \n---\n" + response )
adminaeedddd2013-08-02 15:14:15 -0700381 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800382
Jon Hall7eb38402015-01-08 17:19:54 -0800383 def pingHost( self, **pingParams ):
384 """
385 Ping from one mininet host to another
386 Currently the only supported Params: SRC and TARGET"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800387 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
Jon Hall7eb38402015-01-08 17:19:54 -0800388 command = args[ "SRC" ] + " ping " + \
389 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700390 try:
Jon Hall61282e32015-03-19 11:34:11 -0700391 main.log.info( "Sending: " + command )
Jon Hall7eb38402015-01-08 17:19:54 -0800392 self.handle.sendline( command )
393 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700394 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800395 main.log.error(
396 self.name +
397 ": timeout when waiting for response from mininet" )
398 main.log.error( "response: " + str( self.handle.before ) )
399 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700400 if i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -0800401 main.log.error(
402 self.name +
403 ": timeout when waiting for response from mininet" )
404 main.log.error( "response: " + str( self.handle.before ) )
Jon Hall6e18c7b2014-04-23 16:26:33 -0700405 response = self.handle.before
Jon Hallfbc828e2015-01-06 17:30:19 -0800406 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800407 main.log.error( self.name + ": EOF exception found" )
408 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700409 main.cleanup()
410 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -0800411 main.log.info( self.name + ": Ping Response: " + response )
412 if re.search( ',\s0\%\spacket\sloss', response ):
413 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800414 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700415 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800416 else:
417 main.log.error(
418 self.name +
419 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800420 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700421 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800422
Jon Hall7eb38402015-01-08 17:19:54 -0800423 def checkIP( self, host ):
424 """
425 Verifies the host's ip configured or not."""
426 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700427 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800428 response = self.execute(
429 cmd=host +
430 " ifconfig",
431 prompt="mininet>",
432 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800433 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800434 main.log.error( self.name + ": EOF exception found" )
435 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700436 main.cleanup()
437 main.exit()
adminbae64d82013-08-01 10:50:15 -0700438
Jon Hall7eb38402015-01-08 17:19:54 -0800439 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800440 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\
441 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\
442 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\
443 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\
444 "[0-9]|25[0-5]|[0-9]{1,2})"
Jon Hall7eb38402015-01-08 17:19:54 -0800445 # pattern = "inet addr:10.0.0.6"
446 if re.search( pattern, response ):
447 main.log.info( self.name + ": Host Ip configured properly" )
adminbae64d82013-08-01 10:50:15 -0700448 return main.TRUE
449 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800450 main.log.error( self.name + ": Host IP not found" )
adminbae64d82013-08-01 10:50:15 -0700451 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800452 else:
453 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800454
Jon Hall7eb38402015-01-08 17:19:54 -0800455 def verifySSH( self, **connectargs ):
Jon Hallefbd9792015-03-05 16:11:36 -0800456 # FIXME: Who uses this and what is the purpose? seems very specific
Jon Hall6094a362014-04-11 14:46:56 -0700457 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800458 response = self.execute(
459 cmd="h1 /usr/sbin/sshd -D&",
460 prompt="mininet>",
461 timeout=10 )
462 response = self.execute(
463 cmd="h4 /usr/sbin/sshd -D&",
464 prompt="mininet>",
465 timeout=10 )
Jon Hall6094a362014-04-11 14:46:56 -0700466 for key in connectargs:
Jon Hall7eb38402015-01-08 17:19:54 -0800467 vars( self )[ key ] = connectargs[ key ]
468 response = self.execute(
469 cmd="xterm h1 h4 ",
470 prompt="mininet>",
471 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800472 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800473 main.log.error( self.name + ": EOF exception found" )
474 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700475 main.cleanup()
476 main.exit()
adminbae64d82013-08-01 10:50:15 -0700477 import time
Jon Hall7eb38402015-01-08 17:19:54 -0800478 time.sleep( 20 )
adminbae64d82013-08-01 10:50:15 -0700479 if self.flag == 0:
480 self.flag = 1
481 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800482 else:
adminbae64d82013-08-01 10:50:15 -0700483 return main.TRUE
shahshreyae6c7cf42014-11-26 16:39:01 -0800484
kelvin-onlaba1484582015-02-02 15:46:20 -0800485 def moveHost( self, host, oldSw, newSw, ):
486 """
487 Moves a host from one switch to another on the fly
488 Note: The intf between host and oldSw when detached
489 using detach(), will still show up in the 'net'
490 cmd, because switch.detach() doesn't affect switch.intfs[]
491 (which is correct behavior since the interfaces
492 haven't moved).
493 """
494 if self.handle:
495 try:
496 # Bring link between oldSw-host down
Jon Hallefbd9792015-03-05 16:11:36 -0800497 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'"+ host +\
498 "'," + "'down')"
kelvin-onlaba1484582015-02-02 15:46:20 -0800499 print "cmd1= ", cmd
Jon Hallefbd9792015-03-05 16:11:36 -0800500 response = self.execute( cmd=cmd,
501 prompt="mininet>",
502 timeout=10 )
kelvin-onlaba1484582015-02-02 15:46:20 -0800503
504 # Determine hostintf and Oldswitchintf
505 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800506 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800507 print "cmd2= ", cmd
508 self.handle.sendline( cmd )
509 self.handle.expect( "mininet>" )
510
shahshreya73537862015-02-11 15:15:24 -0800511 # Determine ip and mac address of the host-oldSw interface
kelvin-onlaba1484582015-02-02 15:46:20 -0800512 cmd = "px ipaddr = hintf.IP()"
513 print "cmd3= ", cmd
514 self.handle.sendline( cmd )
515 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800516
517 cmd = "px macaddr = hintf.MAC()"
518 print "cmd3= ", cmd
519 self.handle.sendline( cmd )
520 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800521
522 # Detach interface between oldSw-host
523 cmd = "px " + oldSw + ".detach( sintf )"
524 print "cmd4= ", cmd
525 self.handle.sendline( cmd )
526 self.handle.expect( "mininet>" )
527
528 # Add link between host-newSw
529 cmd = "py net.addLink(" + host + "," + newSw + ")"
530 print "cmd5= ", cmd
531 self.handle.sendline( cmd )
532 self.handle.expect( "mininet>" )
533
534 # Determine hostintf and Newswitchintf
535 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\
Jon Hallefbd9792015-03-05 16:11:36 -0800536 ")[0]"
kelvin-onlaba1484582015-02-02 15:46:20 -0800537 print "cmd6= ", cmd
538 self.handle.sendline( cmd )
539 self.handle.expect( "mininet>" )
540
541 # Attach interface between newSw-host
542 cmd = "px " + newSw + ".attach( sintf )"
543 print "cmd3= ", cmd
544 self.handle.sendline( cmd )
545 self.handle.expect( "mininet>" )
546
547 # Set ipaddress of the host-newSw interface
548 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)"
549 print "cmd7 = ", cmd
550 self.handle.sendline( cmd )
551 self.handle.expect( "mininet>" )
shahshreya73537862015-02-11 15:15:24 -0800552
553 # Set macaddress of the host-newSw interface
554 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)"
555 print "cmd8 = ", cmd
556 self.handle.sendline( cmd )
557 self.handle.expect( "mininet>" )
kelvin-onlaba1484582015-02-02 15:46:20 -0800558
559 cmd = "net"
shahshreya73537862015-02-11 15:15:24 -0800560 print "cmd9 = ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800561 self.handle.sendline( cmd )
562 self.handle.expect( "mininet>" )
563 print "output = ", self.handle.before
564
565 # Determine ipaddress of the host-newSw interface
shahshreya73537862015-02-11 15:15:24 -0800566 cmd = host + " ifconfig"
567 print "cmd10= ", cmd
kelvin-onlaba1484582015-02-02 15:46:20 -0800568 self.handle.sendline( cmd )
569 self.handle.expect( "mininet>" )
570 print "ifconfig o/p = ", self.handle.before
571
572 return main.TRUE
573 except pexpect.EOF:
574 main.log.error( self.name + ": EOF exception found" )
575 main.log.error( self.name + ": " + self.handle.before )
576 return main.FALSE
577
Jon Hall7eb38402015-01-08 17:19:54 -0800578 def changeIP( self, host, intf, newIP, newNetmask ):
579 """
580 Changes the ip address of a host on the fly
581 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800582 if self.handle:
583 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800584 cmd = host + " ifconfig " + intf + " " + \
585 newIP + " " + 'netmask' + " " + newNetmask
586 self.handle.sendline( cmd )
587 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800588 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800589 main.log.info( "response = " + response )
590 main.log.info(
591 "Ip of host " +
592 host +
593 " changed to new IP " +
594 newIP )
shahshreyae6c7cf42014-11-26 16:39:01 -0800595 return main.TRUE
596 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800597 main.log.error( self.name + ": EOF exception found" )
598 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800599 return main.FALSE
600
Jon Hall7eb38402015-01-08 17:19:54 -0800601 def changeDefaultGateway( self, host, newGW ):
602 """
603 Changes the default gateway of a host
604 Ex: h1 route add default gw 10.0.1.2"""
shahshreyae6c7cf42014-11-26 16:39:01 -0800605 if self.handle:
606 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800607 cmd = host + " route add default gw " + newGW
608 self.handle.sendline( cmd )
609 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800610 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800611 main.log.info( "response = " + response )
612 main.log.info(
613 "Default gateway of host " +
614 host +
615 " changed to " +
616 newGW )
shahshreyae6c7cf42014-11-26 16:39:01 -0800617 return main.TRUE
618 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800619 main.log.error( self.name + ": EOF exception found" )
620 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800621 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800622
Jon Hall7eb38402015-01-08 17:19:54 -0800623 def addStaticMACAddress( self, host, GW, macaddr ):
624 """
Jon Hallefbd9792015-03-05 16:11:36 -0800625 Changes the mac address of a gateway host"""
shahshreyad0c80432014-12-04 16:56:05 -0800626 if self.handle:
627 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800628 # h1 arp -s 10.0.1.254 00:00:00:00:11:11
629 cmd = host + " arp -s " + GW + " " + macaddr
630 self.handle.sendline( cmd )
631 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800632 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800633 main.log.info( "response = " + response )
634 main.log.info(
Jon Hallefbd9792015-03-05 16:11:36 -0800635 "Mac address of gateway " +
Jon Hall7eb38402015-01-08 17:19:54 -0800636 GW +
637 " changed to " +
638 macaddr )
shahshreyad0c80432014-12-04 16:56:05 -0800639 return main.TRUE
640 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800641 main.log.error( self.name + ": EOF exception found" )
642 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800643 return main.FALSE
644
Jon Hall7eb38402015-01-08 17:19:54 -0800645 def verifyStaticGWandMAC( self, host ):
646 """
647 Verify if the static gateway and mac address assignment"""
shahshreyad0c80432014-12-04 16:56:05 -0800648 if self.handle:
649 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800650 # h1 arp -an
651 cmd = host + " arp -an "
652 self.handle.sendline( cmd )
653 self.handle.expect( "mininet>" )
shahshreyad0c80432014-12-04 16:56:05 -0800654 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800655 main.log.info( host + " arp -an = " + response )
shahshreyad0c80432014-12-04 16:56:05 -0800656 return main.TRUE
657 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800658 main.log.error( self.name + ": EOF exception found" )
659 main.log.error( self.name + ": " + self.handle.before )
shahshreyad0c80432014-12-04 16:56:05 -0800660 return main.FALSE
661
Jon Hall7eb38402015-01-08 17:19:54 -0800662 def getMacAddress( self, host ):
663 """
664 Verifies the host's ip configured or not."""
665 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700666 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800667 response = self.execute(
668 cmd=host +
669 " ifconfig",
670 prompt="mininet>",
671 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800672 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800673 main.log.error( self.name + ": EOF exception found" )
674 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700675 main.cleanup()
676 main.exit()
adminbae64d82013-08-01 10:50:15 -0700677
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700678 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800679 macAddressSearch = re.search( pattern, response, re.I )
680 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800681 main.log.info(
682 self.name +
683 ": Mac-Address of Host " +
684 host +
685 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800686 macAddress )
687 return macAddress
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700688 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800689 main.log.error( self.name + ": Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700690
Jon Hall7eb38402015-01-08 17:19:54 -0800691 def getInterfaceMACAddress( self, host, interface ):
692 """
693 Return the IP address of the interface on the given host"""
694 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700695 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800696 response = self.execute( cmd=host + " ifconfig " + interface,
697 prompt="mininet>", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800698 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800699 main.log.error( self.name + ": EOF exception found" )
700 main.log.error( self.name + ": " + self.handle.before )
701 main.cleanup()
702 main.exit()
703
704 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
kelvin-onlabd3b64892015-01-20 13:26:24 -0800705 macAddressSearch = re.search( pattern, response, re.I )
706 if macAddressSearch is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800707 main.log.info( "No mac address found in %s" % response )
708 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -0800709 macAddress = macAddressSearch.group().split( " " )[ 1 ]
Jon Hall7eb38402015-01-08 17:19:54 -0800710 main.log.info(
711 "Mac-Address of " +
712 host +
713 ":" +
714 interface +
715 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800716 macAddress )
717 return macAddress
Jon Hall7eb38402015-01-08 17:19:54 -0800718 else:
719 main.log.error( "Connection failed to the host" )
720
721 def getIPAddress( self, host ):
722 """
723 Verifies the host's ip configured or not."""
724 if self.handle:
725 try:
726 response = self.execute(
727 cmd=host +
728 " ifconfig",
729 prompt="mininet>",
730 timeout=10 )
731 except pexpect.EOF:
732 main.log.error( self.name + ": EOF exception found" )
733 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700734 main.cleanup()
735 main.exit()
adminbae64d82013-08-01 10:50:15 -0700736
737 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800738 ipAddressSearch = re.search( pattern, response )
Jon Hall7eb38402015-01-08 17:19:54 -0800739 main.log.info(
740 self.name +
741 ": IP-Address of Host " +
742 host +
743 " is " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800744 ipAddressSearch.group( 1 ) )
745 return ipAddressSearch.group( 1 )
Jon Hall7eb38402015-01-08 17:19:54 -0800746 else:
747 main.log.error( self.name + ": Connection failed to the host" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800748
Jon Hall7eb38402015-01-08 17:19:54 -0800749 def getSwitchDPID( self, switch ):
750 """
751 return the datapath ID of the switch"""
752 if self.handle:
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700753 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700754 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800755 response = self.execute(
756 cmd=cmd,
757 prompt="mininet>",
758 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800759 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800760 main.log.error( self.name + ": EOF exception found" )
761 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700762 main.cleanup()
763 main.exit()
Jon Hall28bf54b2014-12-17 16:25:44 -0800764 pattern = r'^(?P<dpid>\w)+'
Jon Hall7eb38402015-01-08 17:19:54 -0800765 result = re.search( pattern, response, re.MULTILINE )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700766 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -0800767 main.log.info(
768 "Couldn't find DPID for switch %s, found: %s" %
769 ( switch, response ) )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700770 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -0800771 return str( result.group( 0 ) ).lower()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700772 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800773 main.log.error( "Connection failed to the host" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700774
Jon Hall7eb38402015-01-08 17:19:54 -0800775 def getDPID( self, switch ):
admin2580a0e2014-07-29 11:24:34 -0700776 if self.handle:
Jon Hall7eb38402015-01-08 17:19:54 -0800777 self.handle.sendline( "" )
778 self.expect( "mininet>" )
779 cmd = "py %s.dpid" % switch
admin2580a0e2014-07-29 11:24:34 -0700780 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800781 response = self.execute(
782 cmd=cmd,
783 prompt="mininet>",
784 timeout=10 )
785 self.handle.expect( "mininet>" )
admin2580a0e2014-07-29 11:24:34 -0700786 response = self.handle.before
787 return response
788 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800789 main.log.error( self.name + ": EOF exception found" )
790 main.log.error( self.name + ": " + self.handle.before )
admin2580a0e2014-07-29 11:24:34 -0700791 main.cleanup()
792 main.exit()
793
Jon Hall7eb38402015-01-08 17:19:54 -0800794 def getInterfaces( self, node ):
795 """
796 return information dict about interfaces connected to the node"""
797 if self.handle:
798 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\
kelvin-onlabedcff052015-01-16 12:53:55 -0800799 ' % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700800 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700801 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800802 response = self.execute(
803 cmd=cmd,
804 prompt="mininet>",
805 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800806 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800807 main.log.error( self.name + ": EOF exception found" )
808 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700809 main.cleanup()
810 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700811 return response
812 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800813 main.log.error( "Connection failed to the node" )
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700814
Jon Hall7eb38402015-01-08 17:19:54 -0800815 def dump( self ):
816 main.log.info( self.name + ": Dump node info" )
Jon Hall6094a362014-04-11 14:46:56 -0700817 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800818 response = self.execute(
819 cmd='dump',
820 prompt='mininet>',
821 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800822 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800823 main.log.error( self.name + ": EOF exception found" )
824 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700825 main.cleanup()
826 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700827 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800828
Jon Hall7eb38402015-01-08 17:19:54 -0800829 def intfs( self ):
830 main.log.info( self.name + ": List interfaces" )
Jon Hall6094a362014-04-11 14:46:56 -0700831 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800832 response = self.execute(
833 cmd='intfs',
834 prompt='mininet>',
835 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800836 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800837 main.log.error( self.name + ": EOF exception found" )
838 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700839 main.cleanup()
840 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700841 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800842
Jon Hall7eb38402015-01-08 17:19:54 -0800843 def net( self ):
844 main.log.info( self.name + ": List network connections" )
Jon Hall6094a362014-04-11 14:46:56 -0700845 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800846 response = self.execute( cmd='net', prompt='mininet>', timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800847 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800848 main.log.error( self.name + ": EOF exception found" )
849 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700850 main.cleanup()
851 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700852 return response
Jon Hall7eb38402015-01-08 17:19:54 -0800853
854 def iperf( self, host1, host2 ):
855 main.log.info(
856 self.name +
857 ": Simple iperf TCP test between two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700858 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800859 cmd1 = 'iperf ' + host1 + " " + host2
860 self.handle.sendline( cmd1 )
861 self.handle.expect( "mininet>" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800862 response = self.handle.before
Jon Hall7eb38402015-01-08 17:19:54 -0800863 if re.search( 'Results:', response ):
Jon Hallefbd9792015-03-05 16:11:36 -0800864 main.log.info( self.name + ": iperf test successful" )
shahshreyae6c7cf42014-11-26 16:39:01 -0800865 return main.TRUE
866 else:
Jon Hall7eb38402015-01-08 17:19:54 -0800867 main.log.error( self.name + ": iperf test failed" )
868 return main.FALSE
shahshreyae6c7cf42014-11-26 16:39:01 -0800869 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800870 main.log.error( self.name + ": EOF exception found" )
871 main.log.error( self.name + ": " + self.handle.before )
shahshreyae6c7cf42014-11-26 16:39:01 -0800872 main.cleanup()
873 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800874
Jon Hall7eb38402015-01-08 17:19:54 -0800875 def iperfudp( self ):
876 main.log.info(
877 self.name +
878 ": Simple iperf TCP test between two " +
879 "(optionally specified) hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700880 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800881 response = self.execute(
882 cmd='iperfudp',
883 prompt='mininet>',
884 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800885 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800886 main.log.error( self.name + ": EOF exception found" )
887 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700888 main.cleanup()
889 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700890 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800891
Jon Hall7eb38402015-01-08 17:19:54 -0800892 def nodes( self ):
893 main.log.info( self.name + ": List all nodes." )
Jon Hall6094a362014-04-11 14:46:56 -0700894 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800895 response = self.execute(
896 cmd='nodes',
897 prompt='mininet>',
898 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800899 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800900 main.log.error( self.name + ": EOF exception found" )
901 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700902 main.cleanup()
903 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700904 return response
Jon Hallfbc828e2015-01-06 17:30:19 -0800905
Jon Hall7eb38402015-01-08 17:19:54 -0800906 def pingpair( self ):
907 main.log.info( self.name + ": Ping between first two hosts" )
Jon Hall6094a362014-04-11 14:46:56 -0700908 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800909 response = self.execute(
910 cmd='pingpair',
911 prompt='mininet>',
912 timeout=20 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800913 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800914 main.log.error( self.name + ": EOF exception found" )
915 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700916 main.cleanup()
917 main.exit()
Jon Hallfbc828e2015-01-06 17:30:19 -0800918
Jon Hall7eb38402015-01-08 17:19:54 -0800919 if re.search( ',\s0\%\spacket\sloss', response ):
920 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800921 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700922 return main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -0800923 else:
924 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800925 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700926 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800927
Jon Hall7eb38402015-01-08 17:19:54 -0800928 def link( self, **linkargs ):
929 """
930 Bring link( s ) between two nodes up or down"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800931 args = utilities.parse_args( [ "END1", "END2", "OPTION" ], **linkargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800932 end1 = args[ "END1" ] if args[ "END1" ] is not None else ""
933 end2 = args[ "END2" ] if args[ "END2" ] is not None else ""
934 option = args[ "OPTION" ] if args[ "OPTION" ] is not None else ""
935 main.log.info(
936 "Bring link between '" +
937 end1 +
938 "' and '" +
939 end2 +
940 "' '" +
941 option +
942 "'" )
943 command = "link " + \
944 str( end1 ) + " " + str( end2 ) + " " + str( option )
Jon Hall6094a362014-04-11 14:46:56 -0700945 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800946 self.handle.sendline( command )
947 self.handle.expect( "mininet>" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800948 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800949 main.log.error( self.name + ": EOF exception found" )
950 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700951 main.cleanup()
952 main.exit()
adminbae64d82013-08-01 10:50:15 -0700953 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800954
Jon Hall7eb38402015-01-08 17:19:54 -0800955 def yank( self, **yankargs ):
956 """
957 yank a mininet switch interface to a host"""
958 main.log.info( 'Yank the switch interface attached to a host' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800959 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800960 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
961 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
962 command = "py " + str( sw ) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700963 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800964 response = self.execute(
965 cmd=command,
966 prompt="mininet>",
967 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800968 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800969 main.log.error( self.name + ": EOF exception found" )
970 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700971 main.cleanup()
972 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700973 return main.TRUE
974
Jon Hall7eb38402015-01-08 17:19:54 -0800975 def plug( self, **plugargs ):
976 """
977 plug the yanked mininet switch interface to a switch"""
978 main.log.info( 'Plug the switch interface attached to a switch' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800979 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs )
Jon Hall7eb38402015-01-08 17:19:54 -0800980 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
981 intf = args[ "INTF" ] if args[ "INTF" ] is not None else ""
982 command = "py " + str( sw ) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700983 try:
Jon Hall7eb38402015-01-08 17:19:54 -0800984 response = self.execute(
985 cmd=command,
986 prompt="mininet>",
987 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800988 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -0800989 main.log.error( self.name + ": EOF exception found" )
990 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -0700991 main.cleanup()
992 main.exit()
adminbae64d82013-08-01 10:50:15 -0700993 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800994
Jon Hall7eb38402015-01-08 17:19:54 -0800995 def dpctl( self, **dpctlargs ):
996 """
997 Run dpctl command on all switches."""
998 main.log.info( 'Run dpctl command on all switches' )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800999 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001000 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else ""
1001 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else ""
1002 command = "dpctl " + cmd + " " + str( cmdargs )
1003 try:
1004 response = self.execute(
1005 cmd=command,
1006 prompt="mininet>",
1007 timeout=10 )
1008 except pexpect.EOF:
1009 main.log.error( self.name + ": EOF exception found" )
1010 main.log.error( self.name + ": " + self.handle.before )
1011 main.cleanup()
1012 main.exit()
1013 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -08001014
kelvin-onlabd3b64892015-01-20 13:26:24 -08001015 def getVersion( self ):
Jon Hallff6b4b22015-02-23 09:25:15 -08001016 #FIXME: What uses this? This should be refactored to get
1017 # version from MN and not some other file
kelvin-onlabd3b64892015-01-20 13:26:24 -08001018 fileInput = path + '/lib/Mininet/INSTALL'
1019 version = super( Mininet, self ).getVersion()
adminbae64d82013-08-01 10:50:15 -07001020 pattern = 'Mininet\s\w\.\w\.\w\w*'
kelvin-onlabd3b64892015-01-20 13:26:24 -08001021 for line in open( fileInput, 'r' ).readlines():
Jon Hall7eb38402015-01-08 17:19:54 -08001022 result = re.match( pattern, line )
adminbae64d82013-08-01 10:50:15 -07001023 if result:
Jon Hall7eb38402015-01-08 17:19:54 -08001024 version = result.group( 0 )
Jon Hallec3c21e2014-11-10 22:22:37 -05001025 return version
adminbae64d82013-08-01 10:50:15 -07001026
kelvin-onlabd3b64892015-01-20 13:26:24 -08001027 def getSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001028 """
Jon Hallec3c21e2014-11-10 22:22:37 -05001029 Parameters:
1030 sw: The name of an OVS switch. Example "s1"
1031 Return:
Jon Hall7eb38402015-01-08 17:19:54 -08001032 The output of the command from the mininet cli
1033 or main.FALSE on timeout"""
1034 command = "sh ovs-vsctl get-controller " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001035 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001036 response = self.execute(
1037 cmd=command,
1038 prompt="mininet>",
1039 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001040 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -05001041 return response
admin2a9548d2014-06-17 14:08:07 -07001042 else:
1043 return main.FALSE
1044 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001045 main.log.error( self.name + ": EOF exception found" )
1046 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001047 main.cleanup()
1048 main.exit()
adminbae64d82013-08-01 10:50:15 -07001049
kelvin-onlabd3b64892015-01-20 13:26:24 -08001050 def assignSwController( self, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001051 """
1052 count is only needed if there is more than 1 controller"""
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001053 args = utilities.parse_args( [ "COUNT" ], **kwargs )
Jon Hall7eb38402015-01-08 17:19:54 -08001054 count = args[ "COUNT" ] if args != {} else 1
Jon Hallf89c8552014-04-02 13:14:06 -07001055
1056 argstring = "SW"
Jon Hall7eb38402015-01-08 17:19:54 -08001057 for j in range( count ):
1058 argstring = argstring + ",IP" + \
1059 str( j + 1 ) + ",PORT" + str( j + 1 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001060 args = utilities.parse_args( argstring.split( "," ), **kwargs )
Jon Hallf89c8552014-04-02 13:14:06 -07001061
Jon Hall7eb38402015-01-08 17:19:54 -08001062 sw = args[ "SW" ] if args[ "SW" ] is not None else ""
1063 ptcpA = int( args[ "PORT1" ] ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001064 int( sw ) if args[ "PORT1" ] is not None else ""
Jon Hall7eb38402015-01-08 17:19:54 -08001065 ptcpB = "ptcp:" + str( ptcpA ) if ptcpA != "" else ""
Jon Hallfbc828e2015-01-06 17:30:19 -08001066
Jon Hall7eb38402015-01-08 17:19:54 -08001067 command = "sh ovs-vsctl set-controller s" + \
1068 str( sw ) + " " + ptcpB + " "
1069 for j in range( count ):
1070 i = j + 1
kelvin-onlab7d0c9672015-01-20 15:56:22 -08001071 args = utilities.parse_args(
Jon Hall7eb38402015-01-08 17:19:54 -08001072 [ "IP" + str( i ), "PORT" + str( i ) ], **kwargs )
1073 ip = args[
1074 "IP" +
1075 str( i ) ] if args[
1076 "IP" +
1077 str( i ) ] is not None else ""
1078 port = args[
1079 "PORT" +
1080 str( i ) ] if args[
1081 "PORT" +
1082 str( i ) ] is not None else ""
1083 tcp = "tcp:" + str( ip ) + ":" + str( port ) + \
kelvin-onlabedcff052015-01-16 12:53:55 -08001084 " " if ip != "" else ""
Jon Hallf89c8552014-04-02 13:14:06 -07001085 command = command + tcp
Jon Hall6094a362014-04-11 14:46:56 -07001086 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001087 self.execute( cmd=command, prompt="mininet>", timeout=5 )
Jon Hall6094a362014-04-11 14:46:56 -07001088 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001089 main.log.error( self.name + ": EOF exception found" )
1090 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001091 main.cleanup()
1092 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001093 except Exception:
1094 main.log.exception( self.name + ": Uncaught exception!" )
Jon Hall6094a362014-04-11 14:46:56 -07001095 main.cleanup()
1096 main.exit()
adminbae64d82013-08-01 10:50:15 -07001097
kelvin-onlabd3b64892015-01-20 13:26:24 -08001098 def deleteSwController( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001099 """
1100 Removes the controller target from sw"""
1101 command = "sh ovs-vsctl del-controller " + str( sw )
Jon Hall0819fd92014-05-23 12:08:13 -07001102 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001103 response = self.execute(
1104 cmd=command,
1105 prompt="mininet>",
1106 timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -08001107 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001108 main.log.error( self.name + ": EOF exception found" )
1109 main.log.error( self.name + ": " + self.handle.before )
Jon Hall0819fd92014-05-23 12:08:13 -07001110 main.cleanup()
1111 main.exit()
1112 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001113 main.log.info( response )
Jon Hall0819fd92014-05-23 12:08:13 -07001114
kelvin-onlabd3b64892015-01-20 13:26:24 -08001115 def addSwitch( self, sw, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001116 """
Jon Hallb1290e82014-11-18 16:17:48 -05001117 adds a switch to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001118 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001119 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001120 NOTE: cannot currently specify what type of switch
1121 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001122 sw = name of the new switch as a string
1123 optional keywords:
Jon Hallb1290e82014-11-18 16:17:48 -05001124 dpid = "dpid"
Jon Hallefbd9792015-03-05 16:11:36 -08001125 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001126 """
1127 dpid = kwargs.get( 'dpid', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001128 command = "addswitch " + str( sw ) + " " + str( dpid )
Jon Hallb1290e82014-11-18 16:17:48 -05001129 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001130 response = self.execute(
1131 cmd=command,
1132 prompt="mininet>",
1133 timeout=10 )
1134 if re.search( "already exists!", response ):
1135 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001136 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001137 elif re.search( "Error", response ):
1138 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001139 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001140 elif re.search( "usage:", response ):
1141 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001142 return main.FALSE
1143 else:
1144 return main.TRUE
1145 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001146 main.log.error( self.name + ": EOF exception found" )
1147 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001148 main.cleanup()
1149 main.exit()
1150
kelvin-onlabd3b64892015-01-20 13:26:24 -08001151 def delSwitch( self, sw ):
Jon Hall7eb38402015-01-08 17:19:54 -08001152 """
Jon Hallbe6dfc42015-01-12 17:37:25 -08001153 delete a switch from the mininet topology
1154 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001155 dynamic_topo branch
Jon Hallbe6dfc42015-01-12 17:37:25 -08001156 required params:
Jon Hallefbd9792015-03-05 16:11:36 -08001157 sw = name of the switch as a string
1158 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001159 command = "delswitch " + str( sw )
Jon Hallb1290e82014-11-18 16:17:48 -05001160 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001161 response = self.execute(
1162 cmd=command,
1163 prompt="mininet>",
1164 timeout=10 )
1165 if re.search( "no switch named", response ):
1166 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001167 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001168 elif re.search( "Error", response ):
1169 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001170 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001171 elif re.search( "usage:", response ):
1172 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001173 return main.FALSE
1174 else:
1175 return main.TRUE
1176 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001177 main.log.error( self.name + ": EOF exception found" )
1178 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001179 main.cleanup()
1180 main.exit()
1181
kelvin-onlabd3b64892015-01-20 13:26:24 -08001182 def addLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001183 """
1184 add a link to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001185 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001186 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001187 NOTE: cannot currently specify what type of link
1188 required params:
1189 node1 = the string node name of the first endpoint of the link
1190 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001191 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001192 command = "addlink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001193 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001194 response = self.execute(
1195 cmd=command,
1196 prompt="mininet>",
1197 timeout=10 )
1198 if re.search( "doesnt exist!", response ):
1199 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001200 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001201 elif re.search( "Error", response ):
1202 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001203 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001204 elif re.search( "usage:", response ):
1205 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001206 return main.FALSE
1207 else:
1208 return main.TRUE
1209 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001210 main.log.error( self.name + ": EOF exception found" )
1211 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001212 main.cleanup()
1213 main.exit()
1214
kelvin-onlabd3b64892015-01-20 13:26:24 -08001215 def delLink( self, node1, node2 ):
Jon Hall7eb38402015-01-08 17:19:54 -08001216 """
1217 delete a link from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001218 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001219 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001220 required params:
1221 node1 = the string node name of the first endpoint of the link
1222 node2 = the string node name of the second endpoint of the link
Jon Hallefbd9792015-03-05 16:11:36 -08001223 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001224 command = "dellink " + str( node1 ) + " " + str( node2 )
Jon Hallb1290e82014-11-18 16:17:48 -05001225 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001226 response = self.execute(
1227 cmd=command,
1228 prompt="mininet>",
1229 timeout=10 )
1230 if re.search( "no node named", response ):
1231 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001232 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001233 elif re.search( "Error", response ):
1234 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001235 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001236 elif re.search( "usage:", response ):
1237 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001238 return main.FALSE
1239 else:
1240 return main.TRUE
1241 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001242 main.log.error( self.name + ": EOF exception found" )
1243 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001244 main.cleanup()
1245 main.exit()
1246
kelvin-onlabd3b64892015-01-20 13:26:24 -08001247 def addHost( self, hostname, **kwargs ):
Jon Hall7eb38402015-01-08 17:19:54 -08001248 """
Jon Hallb1290e82014-11-18 16:17:48 -05001249 Add a host to the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001250 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001251 dynamic_topo branch
Jon Hallb1290e82014-11-18 16:17:48 -05001252 NOTE: cannot currently specify what type of host
1253 required params:
1254 hostname = the string hostname
1255 optional key-value params
1256 switch = "switch name"
Jon Hallefbd9792015-03-05 16:11:36 -08001257 returns: main.FALSE on an error, else main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001258 """
1259 switch = kwargs.get( 'switch', '' )
Jon Hallffb386d2014-11-21 13:43:38 -08001260 command = "addhost " + str( hostname ) + " " + str( switch )
Jon Hallb1290e82014-11-18 16:17:48 -05001261 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001262 response = self.execute(
1263 cmd=command,
1264 prompt="mininet>",
1265 timeout=10 )
1266 if re.search( "already exists!", response ):
1267 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001268 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001269 elif re.search( "doesnt exists!", response ):
1270 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001271 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001272 elif re.search( "Error", response ):
1273 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001274 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001275 elif re.search( "usage:", response ):
1276 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001277 return main.FALSE
1278 else:
1279 return main.TRUE
1280 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001281 main.log.error( self.name + ": EOF exception found" )
1282 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001283 main.cleanup()
1284 main.exit()
1285
kelvin-onlabd3b64892015-01-20 13:26:24 -08001286 def delHost( self, hostname ):
Jon Hall7eb38402015-01-08 17:19:54 -08001287 """
1288 delete a host from the mininet topology
Jon Hallbe6dfc42015-01-12 17:37:25 -08001289 NOTE: This uses a custom mn function. MN repo should be on
Jon Hall272a4db2015-01-12 17:43:48 -08001290 dynamic_topo branch
Jon Hall7eb38402015-01-08 17:19:54 -08001291 NOTE: this uses a custom mn function
1292 required params:
1293 hostname = the string hostname
Jon Hallefbd9792015-03-05 16:11:36 -08001294 returns: main.FALSE on an error, else main.TRUE"""
Jon Hallffb386d2014-11-21 13:43:38 -08001295 command = "delhost " + str( hostname )
Jon Hallb1290e82014-11-18 16:17:48 -05001296 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001297 response = self.execute(
1298 cmd=command,
1299 prompt="mininet>",
1300 timeout=10 )
1301 if re.search( "no host named", response ):
1302 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001303 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001304 elif re.search( "Error", response ):
1305 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001306 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001307 elif re.search( "usage:", response ):
1308 main.log.warn( response )
Jon Hallb1290e82014-11-18 16:17:48 -05001309 return main.FALSE
1310 else:
1311 return main.TRUE
1312 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001313 main.log.error( self.name + ": EOF exception found" )
1314 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001315 main.cleanup()
1316 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -07001317
Jon Hall7eb38402015-01-08 17:19:54 -08001318 def disconnect( self ):
kelvin-onlaba1484582015-02-02 15:46:20 -08001319 """
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001320 Called at the end of the test to stop the mininet and
1321 disconnect the handle.
kelvin-onlaba1484582015-02-02 15:46:20 -08001322 """
1323 self.handle.sendline('')
Jon Halld61331b2015-02-17 16:35:47 -08001324 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
Jon Hallefbd9792015-03-05 16:11:36 -08001325 timeout=2)
kelvin-onlaba1484582015-02-02 15:46:20 -08001326 if i == 0:
1327 self.stopNet()
Jon Halld61331b2015-02-17 16:35:47 -08001328 elif i == 1:
1329 return main.TRUE
1330 response = main.TRUE
kelvin-onlaba1484582015-02-02 15:46:20 -08001331 # print "Disconnecting Mininet"
1332 if self.handle:
1333 self.handle.sendline( "exit" )
1334 self.handle.expect( "exit" )
1335 self.handle.expect( "(.*)" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001336 else:
1337 main.log.error( "Connection failed to the host" )
kelvin-onlaba1484582015-02-02 15:46:20 -08001338 return response
1339
Hari Krishnab35c6d02015-03-18 11:13:51 -07001340 def stopNet( self, fileName = "", timeout=5):
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001341 """
Jon Hall21270ac2015-02-16 17:59:55 -08001342 Stops mininet.
Jon Hallefbd9792015-03-05 16:11:36 -08001343 Returns main.TRUE if the mininet successfully stops and
Jon Hall21270ac2015-02-16 17:59:55 -08001344 main.FALSE if the pexpect handle does not exist.
1345
Jon Halld61331b2015-02-17 16:35:47 -08001346 Will cleanup and exit the test if mininet fails to stop
kelvin-onlab00ac67b2015-02-04 09:52:02 -08001347 """
Jon Hall21270ac2015-02-16 17:59:55 -08001348
Jon Halld61331b2015-02-17 16:35:47 -08001349 main.log.info( self.name + ": Stopping mininet..." )
adminbae64d82013-08-01 10:50:15 -07001350 response = ''
1351 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -07001352 try:
kelvin-onlab26bc17f2015-02-06 14:08:59 -08001353 self.handle.sendline("")
kelvin-onlab56a3f462015-02-06 14:04:43 -08001354 i = self.handle.expect( [ 'mininet>',
1355 '\$',
1356 pexpect.EOF,
1357 pexpect.TIMEOUT ],
1358 timeout )
1359 if i == 0:
1360 main.log.info( "Exiting mininet..." )
1361
Jon Hall7eb38402015-01-08 17:19:54 -08001362 response = self.execute(
1363 cmd="exit",
1364 prompt="(.*)",
1365 timeout=120 )
Jon Halld61331b2015-02-17 16:35:47 -08001366 main.log.info( self.name + ": Stopped")
Jon Hall7eb38402015-01-08 17:19:54 -08001367 self.handle.sendline( "sudo mn -c" )
shahshreya328c2a72014-11-17 10:19:50 -08001368 response = main.TRUE
Hari Krishnab35c6d02015-03-18 11:13:51 -07001369
kelvin-onlab56a3f462015-02-06 14:04:43 -08001370 if i == 1:
1371 main.log.info( " Mininet trying to exit while not " +
1372 "in the mininet prompt" )
1373 elif i == 2:
1374 main.log.error( "Something went wrong exiting mininet" )
1375 elif i == 3: # timeout
1376 main.log.error( "Something went wrong exiting mininet " +
1377 "TIMEOUT" )
1378
Hari Krishnab35c6d02015-03-18 11:13:51 -07001379 if fileName:
1380 self.handle.sendline("")
1381 self.handle.expect('\$')
1382 self.handle.sendline("sudo kill -9 \`ps -ef | grep \""+ fileName +"\" | grep -v grep | awk '{print $2}'\`")
Jon Hallfbc828e2015-01-06 17:30:19 -08001383 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001384 main.log.error( self.name + ": EOF exception found" )
1385 main.log.error( self.name + ": " + self.handle.before )
Jon Hall6094a362014-04-11 14:46:56 -07001386 main.cleanup()
1387 main.exit()
Jon Hall7eb38402015-01-08 17:19:54 -08001388 else:
1389 main.log.error( self.name + ": Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -07001390 response = main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -08001391 return response
1392
Jon Hall7eb38402015-01-08 17:19:54 -08001393 def arping( self, src, dest, destmac ):
1394 self.handle.sendline( '' )
1395 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001396
Jon Hall7eb38402015-01-08 17:19:54 -08001397 self.handle.sendline( src + ' arping ' + dest )
admin07529932013-11-22 14:58:28 -08001398 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001399 self.handle.expect( [ destmac, pexpect.EOF, pexpect.TIMEOUT ] )
1400 main.log.info( self.name + ": ARP successful" )
1401 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001402 return main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -08001403 except Exception:
Jon Hall7eb38402015-01-08 17:19:54 -08001404 main.log.warn( self.name + ": ARP FAILURE" )
1405 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] )
admin07529932013-11-22 14:58:28 -08001406 return main.FALSE
1407
Jon Hall7eb38402015-01-08 17:19:54 -08001408 def decToHex( self, num ):
1409 return hex( num ).split( 'x' )[ 1 ]
Jon Hallfbc828e2015-01-06 17:30:19 -08001410
Jon Hall7eb38402015-01-08 17:19:54 -08001411 def getSwitchFlowCount( self, switch ):
1412 """
1413 return the Flow Count of the switch"""
admin2a9548d2014-06-17 14:08:07 -07001414 if self.handle:
1415 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
1416 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001417 response = self.execute(
1418 cmd=cmd,
1419 prompt="mininet>",
1420 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001421 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001422 main.log.error( self.name + ": EOF exception found" )
1423 main.log.error( self.name + " " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001424 main.cleanup()
1425 main.exit()
1426 pattern = "flow_count=(\d+)"
Jon Hall7eb38402015-01-08 17:19:54 -08001427 result = re.search( pattern, response, re.MULTILINE )
admin2a9548d2014-06-17 14:08:07 -07001428 if result is None:
Jon Hall7eb38402015-01-08 17:19:54 -08001429 main.log.info(
1430 "Couldn't find flows on switch %s, found: %s" %
1431 ( switch, response ) )
admin2a9548d2014-06-17 14:08:07 -07001432 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001433 return result.group( 1 )
admin2a9548d2014-06-17 14:08:07 -07001434 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001435 main.log.error( "Connection failed to the Mininet host" )
Jon Hallfbc828e2015-01-06 17:30:19 -08001436
kelvin-onlabd3b64892015-01-20 13:26:24 -08001437 def checkFlows( self, sw, dumpFormat=None ):
1438 if dumpFormat:
Jon Hall7eb38402015-01-08 17:19:54 -08001439 command = "sh ovs-ofctl -F " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001440 dumpFormat + " dump-flows " + str( sw )
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -07001441 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001442 command = "sh ovs-ofctl dump-flows " + str( sw )
admin2a9548d2014-06-17 14:08:07 -07001443 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001444 response = self.execute(
1445 cmd=command,
1446 prompt="mininet>",
1447 timeout=10 )
admin2a9548d2014-06-17 14:08:07 -07001448 return response
1449 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001450 main.log.error( self.name + ": EOF exception found" )
1451 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001452 main.cleanup()
1453 main.exit()
admin2a9548d2014-06-17 14:08:07 -07001454
kelvin-onlabd3b64892015-01-20 13:26:24 -08001455 def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
Jon Hall7eb38402015-01-08 17:19:54 -08001456 """
Jon Hallefbd9792015-03-05 16:11:36 -08001457 Runs tpdump on an interface and saves the file
Jon Hall7eb38402015-01-08 17:19:54 -08001458 intf can be specified, or the default eth0 is used"""
admin2a9548d2014-06-17 14:08:07 -07001459 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001460 self.handle.sendline( "" )
1461 self.handle.expect( "mininet>" )
1462 self.handle.sendline(
1463 "sh sudo tcpdump -n -i " +
1464 intf +
1465 " " +
1466 port +
1467 " -w " +
1468 filename.strip() +
1469 " &" )
1470 self.handle.sendline( "" )
1471 i = self.handle.expect( [ 'No\ssuch\device',
1472 'listening\son',
1473 pexpect.TIMEOUT,
1474 "mininet>" ],
1475 timeout=10 )
1476 main.log.warn( self.handle.before + self.handle.after )
1477 self.handle.sendline( "" )
1478 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001479 if i == 0:
Jon Hall7eb38402015-01-08 17:19:54 -08001480 main.log.error(
1481 self.name +
1482 ": tcpdump - No such device exists. " +
1483 "tcpdump attempted on: " +
1484 intf )
admin2a9548d2014-06-17 14:08:07 -07001485 return main.FALSE
1486 elif i == 1:
Jon Hall7eb38402015-01-08 17:19:54 -08001487 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -07001488 return main.TRUE
1489 elif i == 2:
Jon Hall7eb38402015-01-08 17:19:54 -08001490 main.log.error(
1491 self.name +
1492 ": tcpdump command timed out! Check interface name," +
1493 " given interface was: " +
1494 intf )
admin2a9548d2014-06-17 14:08:07 -07001495 return main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001496 elif i == 3:
1497 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001498 return main.TRUE
1499 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001500 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -07001501 return main.FALSE
1502 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001503 main.log.error( self.name + ": EOF exception found" )
1504 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001505 main.cleanup()
1506 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001507 except Exception:
1508 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001509 main.cleanup()
1510 main.exit()
1511
kelvin-onlabd3b64892015-01-20 13:26:24 -08001512 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -08001513 """
1514 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -07001515 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001516 self.handle.sendline( "sh sudo pkill tcpdump" )
1517 self.handle.expect( "mininet>" )
1518 self.handle.sendline( "" )
1519 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001520 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001521 main.log.error( self.name + ": EOF exception found" )
1522 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -07001523 main.cleanup()
1524 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001525 except Exception:
1526 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -07001527 main.cleanup()
1528 main.exit()
1529
kelvin-onlabd3b64892015-01-20 13:26:24 -08001530 def compareSwitches( self, topo, switchesJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001531 """
1532 Compare mn and onos switches
1533 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001534 switchesJson: parsed json object from the onos devices api
Jon Hall3d87d502014-10-17 18:37:42 -04001535
Jon Hall7eb38402015-01-08 17:19:54 -08001536 This uses the sts TestONTopology object"""
kelvin-onlabd3b64892015-01-20 13:26:24 -08001537 # main.log.debug( "Switches_json string: ", switchesJson )
Jon Hall7eb38402015-01-08 17:19:54 -08001538 output = { "switches": [] }
1539 # iterate through the MN topology and pull out switches and and port
1540 # info
1541 for switch in topo.graph.switches:
Jon Hall3d87d502014-10-17 18:37:42 -04001542 ports = []
1543 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001544 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001545 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001546 'name': port.name } )
1547 output[ 'switches' ].append( {
1548 "name": switch.name,
1549 "dpid": str( switch.dpid ).zfill( 16 ),
1550 "ports": ports } )
Jon Hall3d87d502014-10-17 18:37:42 -04001551
Jon Hall7eb38402015-01-08 17:19:54 -08001552 # print "mn"
1553 # print json.dumps( output,
Jon Hallff6b4b22015-02-23 09:25:15 -08001554 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001555 # indent=4,
1556 # separators=( ',', ': ' ) )
1557 # print "onos"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001558 # print json.dumps( switchesJson,
Jon Hallff6b4b22015-02-23 09:25:15 -08001559 # sort_keys=True,
Jon Hall7eb38402015-01-08 17:19:54 -08001560 # indent=4,
1561 # separators=( ',', ': ' ) )
Jon Hall3d87d502014-10-17 18:37:42 -04001562
1563 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall7eb38402015-01-08 17:19:54 -08001564 mnDPIDs = []
1565 for switch in output[ 'switches' ]:
1566 mnDPIDs.append( switch[ 'dpid' ].lower() )
Jon Hall3d87d502014-10-17 18:37:42 -04001567 mnDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001568 # print "List of Mininet switch DPID's"
1569 # print mnDPIDs
kelvin-onlabd3b64892015-01-20 13:26:24 -08001570 if switchesJson == "": # if rest call fails
Jon Hall7eb38402015-01-08 17:19:54 -08001571 main.log.error(
1572 self.name +
1573 ".compare_switches(): Empty JSON object given from ONOS" )
Jon Hall3d87d502014-10-17 18:37:42 -04001574 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001575 onos = switchesJson
Jon Hall7eb38402015-01-08 17:19:54 -08001576 onosDPIDs = []
Jon Hall3d87d502014-10-17 18:37:42 -04001577 for switch in onos:
Jon Hall7eb38402015-01-08 17:19:54 -08001578 if switch[ 'available' ]:
1579 onosDPIDs.append(
1580 switch[ 'id' ].replace(
1581 ":",
1582 '' ).replace(
1583 "of",
1584 '' ).lower() )
1585 # else:
1586 # print "Switch is unavailable:"
1587 # print switch
Jon Hall3d87d502014-10-17 18:37:42 -04001588 onosDPIDs.sort()
Jon Hall7eb38402015-01-08 17:19:54 -08001589 # print "List of ONOS switch DPID's"
1590 # print onosDPIDs
Jon Hall3d87d502014-10-17 18:37:42 -04001591
Jon Hall7eb38402015-01-08 17:19:54 -08001592 if mnDPIDs != onosDPIDs:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001593 switchResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001594 main.log.report( "Switches in MN but not in ONOS:" )
1595 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ]
1596 main.log.report( str( list1 ) )
1597 main.log.report( "Switches in ONOS but not in MN:" )
1598 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ]
kelvin-onlabedcff052015-01-16 12:53:55 -08001599 main.log.report( str( list2 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001600 else: # list of dpid's match in onos and mn
kelvin-onlabd3b64892015-01-20 13:26:24 -08001601 switchResults = main.TRUE
1602 return switchResults
Jon Hall3d87d502014-10-17 18:37:42 -04001603
kelvin-onlabd3b64892015-01-20 13:26:24 -08001604 def comparePorts( self, topo, portsJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001605 """
Jon Hall72cf1dc2014-10-20 21:04:50 -04001606 Compare mn and onos ports
1607 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001608 portsJson: parsed json object from the onos ports api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001609
Jon Hallfbc828e2015-01-06 17:30:19 -08001610 Dependencies:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001611 1. This uses the sts TestONTopology object
1612 2. numpy - "sudo pip install numpy"
1613
Jon Hall7eb38402015-01-08 17:19:54 -08001614 """
1615 # FIXME: this does not look for extra ports in ONOS, only checks that
1616 # ONOS has what is in MN
Jon Hall72cf1dc2014-10-20 21:04:50 -04001617 from numpy import uint64
kelvin-onlabd3b64892015-01-20 13:26:24 -08001618 portsResults = main.TRUE
Jon Hall7eb38402015-01-08 17:19:54 -08001619 output = { "switches": [] }
1620 # iterate through the MN topology and pull out switches and and port
1621 # info
1622 for switch in topo.graph.switches:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001623 ports = []
1624 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001625 # print port.hw_addr.toStr( separator='' )
Jon Hallefbd9792015-03-05 16:11:36 -08001626 tmpPort = { 'of_port': port.port_no,
1627 'mac': str( port.hw_addr ).replace( '\'', '' ),
1628 'name': port.name,
1629 'enabled': port.enabled }
Jon Hall39f29df2014-11-04 19:30:21 -05001630
kelvin-onlabd3b64892015-01-20 13:26:24 -08001631 ports.append( tmpPort )
Jon Hallefbd9792015-03-05 16:11:36 -08001632 tmpSwitch = { 'name': switch.name,
1633 'dpid': str( switch.dpid ).zfill( 16 ),
1634 'ports': ports }
Jon Hall39f29df2014-11-04 19:30:21 -05001635
kelvin-onlabd3b64892015-01-20 13:26:24 -08001636 output[ 'switches' ].append( tmpSwitch )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001637
Jon Hall7eb38402015-01-08 17:19:54 -08001638 # PORTS
kelvin-onlabd3b64892015-01-20 13:26:24 -08001639 for mnSwitch in output[ 'switches' ]:
1640 mnPorts = []
1641 onosPorts = []
1642 switchResult = main.TRUE
1643 for port in mnSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001644 if port[ 'enabled' ]:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001645 mnPorts.append( port[ 'of_port' ] )
1646 for onosSwitch in portsJson:
Jon Hall7eb38402015-01-08 17:19:54 -08001647 # print "Iterating through a new switch as seen by ONOS"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001648 # print onosSwitch
1649 if onosSwitch[ 'device' ][ 'available' ]:
1650 if onosSwitch[ 'device' ][ 'id' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001651 ':',
1652 '' ).replace(
1653 "of",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001654 '' ) == mnSwitch[ 'dpid' ]:
1655 for port in onosSwitch[ 'ports' ]:
Jon Hall7eb38402015-01-08 17:19:54 -08001656 if port[ 'isEnabled' ]:
1657 if port[ 'port' ] == 'local':
kelvin-onlabd3b64892015-01-20 13:26:24 -08001658 # onosPorts.append( 'local' )
1659 onosPorts.append( long( uint64( -2 ) ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001660 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001661 onosPorts.append( int( port[ 'port' ] ) )
Jon Hallb1290e82014-11-18 16:17:48 -05001662 break
kelvin-onlabd3b64892015-01-20 13:26:24 -08001663 mnPorts.sort( key=float )
1664 onosPorts.sort( key=float )
1665 # print "\nPorts for Switch %s:" % ( mnSwitch[ 'name' ] )
1666 # print "\tmn_ports[] = ", mnPorts
1667 # print "\tonos_ports[] = ", onosPorts
1668 mnPortsLog = mnPorts
1669 onosPortsLog = onosPorts
1670 mnPorts = [ x for x in mnPorts ]
1671 onosPorts = [ x for x in onosPorts ]
Jon Hall38481722014-11-04 16:50:05 -05001672
Jon Hall7eb38402015-01-08 17:19:54 -08001673 # TODO: handle other reserved port numbers besides LOCAL
1674 # NOTE: Reserved ports
1675 # Local port: -2 in Openflow, ONOS shows 'local', we store as
1676 # long( uint64( -2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001677 for mnPort in mnPortsLog:
1678 if mnPort in onosPorts:
Jon Hall7eb38402015-01-08 17:19:54 -08001679 # don't set results to true here as this is just one of
1680 # many checks and it might override a failure
kelvin-onlabd3b64892015-01-20 13:26:24 -08001681 mnPorts.remove( mnPort )
1682 onosPorts.remove( mnPort )
Jon Hall7eb38402015-01-08 17:19:54 -08001683 # NOTE: OVS reports this as down since there is no link
Jon Hallb1290e82014-11-18 16:17:48 -05001684 # So ignoring these for now
Jon Hall7eb38402015-01-08 17:19:54 -08001685 # TODO: Come up with a better way of handling these
kelvin-onlabd3b64892015-01-20 13:26:24 -08001686 if 65534 in mnPorts:
1687 mnPorts.remove( 65534 )
1688 if long( uint64( -2 ) ) in onosPorts:
1689 onosPorts.remove( long( uint64( -2 ) ) )
1690 if len( mnPorts ): # the ports of this switch don't match
1691 switchResult = main.FALSE
1692 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) )
1693 if len( onosPorts ): # the ports of this switch don't match
1694 switchResult = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001695 main.log.warn(
1696 "Ports in ONOS but not MN: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001697 str( onosPorts ) )
1698 if switchResult == main.FALSE:
Jon Hall7eb38402015-01-08 17:19:54 -08001699 main.log.report(
1700 "The list of ports for switch %s(%s) does not match:" %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001701 ( mnSwitch[ 'name' ], mnSwitch[ 'dpid' ] ) )
1702 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) )
1703 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) )
1704 portsResults = portsResults and switchResult
1705 return portsResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001706
kelvin-onlabd3b64892015-01-20 13:26:24 -08001707 def compareLinks( self, topo, linksJson ):
Jon Hall7eb38402015-01-08 17:19:54 -08001708 """
1709 Compare mn and onos links
1710 topo: sts TestONTopology object
kelvin-onlabd3b64892015-01-20 13:26:24 -08001711 linksJson: parsed json object from the onos links api
Jon Hall72cf1dc2014-10-20 21:04:50 -04001712
Jon Hall7eb38402015-01-08 17:19:54 -08001713 This uses the sts TestONTopology object"""
1714 # FIXME: this does not look for extra links in ONOS, only checks that
Jon Hallefbd9792015-03-05 16:11:36 -08001715 # ONOS has what is in MN
Jon Hall7eb38402015-01-08 17:19:54 -08001716 output = { "switches": [] }
kelvin-onlabd3b64892015-01-20 13:26:24 -08001717 onos = linksJson
Jon Hall7eb38402015-01-08 17:19:54 -08001718 # iterate through the MN topology and pull out switches and and port
1719 # info
1720 for switch in topo.graph.switches:
Jon Hall38481722014-11-04 16:50:05 -05001721 # print "Iterating though switches as seen by Mininet"
1722 # print switch
Jon Hall72cf1dc2014-10-20 21:04:50 -04001723 ports = []
1724 for port in switch.ports.values():
kelvin-onlab652e1dd2015-01-20 17:01:39 -08001725 # print port.hw_addr.toStr( separator='' )
1726 ports.append( { 'of_port': port.port_no,
Jon Hallefbd9792015-03-05 16:11:36 -08001727 'mac': str( port.hw_addr ).replace( '\'', '' ),
Jon Hall7eb38402015-01-08 17:19:54 -08001728 'name': port.name } )
1729 output[ 'switches' ].append( {
1730 "name": switch.name,
1731 "dpid": str( switch.dpid ).zfill( 16 ),
1732 "ports": ports } )
1733 # LINKS
Jon Hall72cf1dc2014-10-20 21:04:50 -04001734
kelvin-onlabd3b64892015-01-20 13:26:24 -08001735 mnLinks = [
kelvin-onlab9592d132015-01-20 17:18:02 -08001736 link for link in topo.patch_panel.network_links if (
Jon Hall7eb38402015-01-08 17:19:54 -08001737 link.port1.enabled and link.port2.enabled ) ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08001738 if 2 * len( mnLinks ) == len( onos ):
1739 linkResults = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001740 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001741 linkResults = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001742 main.log.report(
Jon Hall328ddca2015-01-28 15:57:15 -08001743 "Mininet has " + str( len( mnLinks ) ) +
1744 " bidirectional links and ONOS has " +
1745 str( len( onos ) ) + " unidirectional links" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001746
Jon Hall7eb38402015-01-08 17:19:54 -08001747 # iterate through MN links and check if an ONOS link exists in
1748 # both directions
1749 # NOTE: Will currently only show mn links as down if they are
1750 # cut through STS. We can either do everything through STS or
kelvin-onlabd3b64892015-01-20 13:26:24 -08001751 # wait for upNetworkLinks and downNetworkLinks to be
Jon Hall7eb38402015-01-08 17:19:54 -08001752 # fully implemented.
kelvin-onlabd3b64892015-01-20 13:26:24 -08001753 for link in mnLinks:
Jon Hall7eb38402015-01-08 17:19:54 -08001754 # print "Link: %s" % link
1755 # TODO: Find a more efficient search method
Jon Hall72cf1dc2014-10-20 21:04:50 -04001756 node1 = None
1757 port1 = None
1758 node2 = None
1759 port2 = None
kelvin-onlabd3b64892015-01-20 13:26:24 -08001760 firstDir = main.FALSE
1761 secondDir = main.FALSE
Jon Hall7eb38402015-01-08 17:19:54 -08001762 for switch in output[ 'switches' ]:
1763 # print "Switch: %s" % switch[ 'name' ]
1764 if switch[ 'name' ] == link.node1.name:
1765 node1 = switch[ 'dpid' ]
1766 for port in switch[ 'ports' ]:
1767 if str( port[ 'name' ] ) == str( link.port1 ):
1768 port1 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001769 if node1 is not None and node2 is not None:
1770 break
Jon Hall7eb38402015-01-08 17:19:54 -08001771 if switch[ 'name' ] == link.node2.name:
1772 node2 = switch[ 'dpid' ]
1773 for port in switch[ 'ports' ]:
1774 if str( port[ 'name' ] ) == str( link.port2 ):
1775 port2 = port[ 'of_port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001776 if node1 is not None and node2 is not None:
1777 break
1778
kelvin-onlabd3b64892015-01-20 13:26:24 -08001779 for onosLink in onos:
1780 onosNode1 = onosLink[ 'src' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001781 ":",
1782 '' ).replace(
1783 "of",
1784 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001785 onosNode2 = onosLink[ 'dst' ][ 'device' ].replace(
Jon Hall7eb38402015-01-08 17:19:54 -08001786 ":",
1787 '' ).replace(
1788 "of",
1789 '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001790 onosPort1 = onosLink[ 'src' ][ 'port' ]
1791 onosPort2 = onosLink[ 'dst' ][ 'port' ]
Jon Hall72cf1dc2014-10-20 21:04:50 -04001792
Jon Hall72cf1dc2014-10-20 21:04:50 -04001793 # check onos link from node1 to node2
kelvin-onlabd3b64892015-01-20 13:26:24 -08001794 if str( onosNode1 ) == str( node1 ) and str(
1795 onosNode2 ) == str( node2 ):
1796 if int( onosPort1 ) == int( port1 ) and int(
1797 onosPort2 ) == int( port2 ):
1798 firstDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001799 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001800 main.log.warn(
1801 'The port numbers do not match for ' +
1802 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001803 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001804 'link %s/%s -> %s/%s' %
1805 ( node1,
1806 port1,
1807 node2,
1808 port2 ) +
1809 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001810 ( onosNode1,
1811 onosPort1,
1812 onosNode2,
1813 onosPort2 ) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001814
1815 # check onos link from node2 to node1
kelvin-onlabd3b64892015-01-20 13:26:24 -08001816 elif ( str( onosNode1 ) == str( node2 ) and
1817 str( onosNode2 ) == str( node1 ) ):
1818 if ( int( onosPort1 ) == int( port2 )
1819 and int( onosPort2 ) == int( port1 ) ):
1820 secondDir = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001821 else:
Jon Hall7eb38402015-01-08 17:19:54 -08001822 main.log.warn(
1823 'The port numbers do not match for ' +
1824 str( link ) +
Jon Hallefbd9792015-03-05 16:11:36 -08001825 ' between ONOS and MN. When checking ONOS for ' +
Jon Hall7eb38402015-01-08 17:19:54 -08001826 'link %s/%s -> %s/%s' %
1827 ( node2,
1828 port2,
1829 node1,
1830 port1 ) +
1831 ' ONOS has the values %s/%s -> %s/%s' %
kelvin-onlabd3b64892015-01-20 13:26:24 -08001832 ( onosNode2,
1833 onosPort2,
1834 onosNode1,
1835 onosPort1 ) )
Jon Hall7eb38402015-01-08 17:19:54 -08001836 else: # this is not the link you're looking for
Jon Hall72cf1dc2014-10-20 21:04:50 -04001837 pass
kelvin-onlabd3b64892015-01-20 13:26:24 -08001838 if not firstDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001839 main.log.report(
1840 'ONOS does not have the link %s/%s -> %s/%s' %
1841 ( node1, port1, node2, port2 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001842 if not secondDir:
Jon Hall7eb38402015-01-08 17:19:54 -08001843 main.log.report(
1844 'ONOS does not have the link %s/%s -> %s/%s' %
1845 ( node2, port2, node1, port1 ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001846 linkResults = linkResults and firstDir and secondDir
1847 return linkResults
Jon Hall72cf1dc2014-10-20 21:04:50 -04001848
Jon Hallff6b4b22015-02-23 09:25:15 -08001849 def compareHosts( self, topo, hostsJson ):
1850 """
1851 Compare mn and onos Hosts.
1852 Since Mininet hosts are quiet, ONOS will only know of them when they
1853 speak. For this reason, we will only check that the hosts in ONOS
1854 stores are in Mininet, and not vice versa.
1855 topo: sts TestONTopology object
1856 hostsJson: parsed json object from the onos hosts api
1857
1858 This uses the sts TestONTopology object"""
1859 import json
1860 hostResults = main.TRUE
1861 hosts = []
1862 # iterate through the MN topology and pull out hosts
1863 for mnHost in topo.graph.hosts:
1864 interfaces = []
1865 for intf in mnHost.interfaces:
1866 interfaces.append( {
1867 "name": intf.name, # str
1868 "ips": [ str( ip ) for ip in intf.ips ], # list of IPAddrs
1869 # hw_addr is of type EthAddr, Not JSON serializable
1870 "hw_addr": str( intf.hw_addr ) } )
1871 hosts.append( {
1872 "name": mnHost.name, # str
1873 "interfaces": interfaces } ) # list
1874 for onosHost in hostsJson:
1875 onosMAC = onosHost[ 'mac' ].lower()
1876 match = False
1877 for mnHost in hosts:
1878 for mnIntf in mnHost[ 'interfaces' ]:
1879 if onosMAC == mnIntf[ 'hw_addr' ].lower() :
1880 match = True
1881 for ip in mnIntf[ 'ips' ]:
1882 if ip in onosHost[ 'ips' ]:
1883 pass # all is well
1884 else:
1885 # misssing ip
1886 main.log.error( "ONOS host " + onosHost[ 'id' ]
1887 + " has a different IP than " +
1888 "the Mininet host." )
1889 output = json.dumps(
1890 onosHost,
1891 sort_keys=True,
1892 indent=4,
1893 separators=( ',', ': ' ) )
1894 main.log.info( output )
1895 hostResults = main.FALSE
1896 if not match:
1897 hostResults = main.FALSE
1898 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
1899 "corresponding Mininet host." )
1900 output = json.dumps( onosHost,
1901 sort_keys=True,
1902 indent=4,
1903 separators=( ',', ': ' ) )
1904 main.log.info( output )
Jon Hallff6b4b22015-02-23 09:25:15 -08001905 return hostResults
1906
kelvin-onlabd3b64892015-01-20 13:26:24 -08001907 def getHosts( self ):
Jon Hall7eb38402015-01-08 17:19:54 -08001908 """
1909 Returns a list of all hosts
1910 Don't ask questions just use it"""
1911 self.handle.sendline( "" )
1912 self.handle.expect( "mininet>" )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001913
Jon Hall7eb38402015-01-08 17:19:54 -08001914 self.handle.sendline( "py [ host.name for host in net.hosts ]" )
1915 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001916
kelvin-onlabd3b64892015-01-20 13:26:24 -08001917 handlePy = self.handle.before
1918 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ]
1919 handlePy = handlePy.rstrip()
admin2a9548d2014-06-17 14:08:07 -07001920
Jon Hall7eb38402015-01-08 17:19:54 -08001921 self.handle.sendline( "" )
1922 self.handle.expect( "mininet>" )
admin2a9548d2014-06-17 14:08:07 -07001923
kelvin-onlabd3b64892015-01-20 13:26:24 -08001924 hostStr = handlePy.replace( "]", "" )
1925 hostStr = hostStr.replace( "'", "" )
1926 hostStr = hostStr.replace( "[", "" )
1927 hostList = hostStr.split( "," )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001928
kelvin-onlabd3b64892015-01-20 13:26:24 -08001929 return hostList
adminbae64d82013-08-01 10:50:15 -07001930
Jon Hall7eb38402015-01-08 17:19:54 -08001931 def update( self ):
1932 """
1933 updates the port address and status information for
1934 each port in mn"""
1935 # TODO: Add error checking. currently the mininet command has no output
Jon Hallefbd9792015-03-05 16:11:36 -08001936 main.log.info( "Updating MN port information" )
Jon Hallb1290e82014-11-18 16:17:48 -05001937 try:
Jon Hall7eb38402015-01-08 17:19:54 -08001938 self.handle.sendline( "" )
1939 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001940
Jon Hall7eb38402015-01-08 17:19:54 -08001941 self.handle.sendline( "update" )
1942 self.handle.expect( "update" )
1943 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001944
Jon Hall7eb38402015-01-08 17:19:54 -08001945 self.handle.sendline( "" )
1946 self.handle.expect( "mininet>" )
Jon Hall38481722014-11-04 16:50:05 -05001947
Jon Hallb1290e82014-11-18 16:17:48 -05001948 return main.TRUE
1949 except pexpect.EOF:
Jon Hall7eb38402015-01-08 17:19:54 -08001950 main.log.error( self.name + ": EOF exception found" )
1951 main.log.error( self.name + ": " + self.handle.before )
Jon Hallb1290e82014-11-18 16:17:48 -05001952 main.cleanup()
1953 main.exit()
1954
adminbae64d82013-08-01 10:50:15 -07001955if __name__ != "__main__":
1956 import sys
kelvin-onlab50907142015-04-01 13:37:45 -07001957 sys.modules[ __name__ ] = MininetCliDriver()