blob: cea3eab696a501c191d55eabee72ea33e48c0fee [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
kelvin-onlabedcff052015-01-16 12:53:55 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
kelvin-onlabedcff052015-01-16 12:53:55 -08005author:: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
kelvin-onlabedcff052015-01-16 12:53:55 -080011 ( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
Jon Hallfbc828e2015-01-06 17:30:19 -080019 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
21
22MininetCliDriver is the basic driver which will handle the Mininet functions
kelvin-onlabedcff052015-01-16 12:53:55 -080023"""
adminbae64d82013-08-01 10:50:15 -070024import pexpect
adminbae64d82013-08-01 10:50:15 -070025import re
26import sys
kelvin-onlaba4074292015-07-09 15:19:49 -070027import os
kelvin-onlabedcff052015-01-16 12:53:55 -080028sys.path.append( "../" )
adminbae64d82013-08-01 10:50:15 -070029from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070030
kelvin-onlabedcff052015-01-16 12:53:55 -080031
32class RemoteMininetDriver( Emulator ):
33
34 """
kelvin-onlabd3b64892015-01-20 13:26:24 -080035 RemoteMininetCliDriver is the basic driver which will handle the Mininet
36 functions. The main different between this and the MininetCliDriver is that
37 this one does not build the mininet. It assumes that there is already a
38 mininet running on the target.
kelvin-onlabedcff052015-01-16 12:53:55 -080039 """
40 def __init__( self ):
41 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070042 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080043 self.name = None
kelvin-onlabedcff052015-01-16 12:53:55 -080044 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070045 self.flag = 0
46
kelvin-onlabedcff052015-01-16 12:53:55 -080047 def connect( self, **connectargs ):
kelvin-onlab08679eb2015-01-21 16:11:48 -080048 """,user_name, ip_address, pwd,options ):
kelvin-onlabd3b64892015-01-20 13:26:24 -080049 Here the main is the TestON instance after creating all the log
50 handles."""
adminbae64d82013-08-01 10:50:15 -070051 for key in connectargs:
kelvin-onlabedcff052015-01-16 12:53:55 -080052 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080053
kelvin-onlabedcff052015-01-16 12:53:55 -080054 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070055
56 try:
57 if os.getenv( str( self.ip_address ) ) != None:
58 self.ip_address = os.getenv( str( self.ip_address ) )
59 else:
60 main.log.info( self.name +
61 ": Trying to connect to " +
62 self.ip_address )
63
64 except KeyError:
65 main.log.info( "Invalid host name," +
66 " connecting to local host instead" )
67 self.ip_address = 'localhost'
68 except Exception as inst:
69 main.log.error( "Uncaught exception: " + str( inst ) )
70
kelvin-onlabedcff052015-01-16 12:53:55 -080071 self.handle = super(
72 RemoteMininetDriver,
73 self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080074 user_name=self.user_name,
75 ip_address=self.ip_address,
kelvin-onlabedcff052015-01-16 12:53:55 -080076 port=None,
77 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080078
Jon Hallfbc828e2015-01-06 17:30:19 -080079 # Copying the readme file to process the
kelvin-onlabedcff052015-01-16 12:53:55 -080080 if self.handle:
adminbae64d82013-08-01 10:50:15 -070081 return main.TRUE
82
kelvin-onlabedcff052015-01-16 12:53:55 -080083 else:
84 main.log.error(
85 "Connection failed to the host " +
kelvin-onlab08679eb2015-01-21 16:11:48 -080086 self.user_name +
kelvin-onlabedcff052015-01-16 12:53:55 -080087 "@" +
kelvin-onlab08679eb2015-01-21 16:11:48 -080088 self.ip_address )
kelvin-onlabedcff052015-01-16 12:53:55 -080089 main.log.error( "Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -070090 return main.FALSE
admin98ad0092014-07-23 16:51:07 -070091
kelvin-onlabedcff052015-01-16 12:53:55 -080092 def checkForLoss( self, pingList ):
93 """
Jon Hall6c794f32014-08-14 13:33:13 -070094 Returns main.FALSE for 0% packet loss and
95 Returns main.ERROR if "found multiple mininet" is found and
96 Returns main.TRUE else
kelvin-onlabedcff052015-01-16 12:53:55 -080097 """
kelvin-onlabedcff052015-01-16 12:53:55 -080098 self.handle.sendline( "" )
99 self.handle.expect( "\$" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800100 self.handle.sendline( "" )
101 self.handle.expect( "\$" )
102 self.handle.sendline( "cat " + pingList )
103 self.handle.expect( pingList )
104 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700105 outputs = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800106 if re.search( " 0% packet loss", outputs ):
admin98ad0092014-07-23 16:51:07 -0700107 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800108 elif re.search( "found multiple mininet", outputs ):
admin2580a0e2014-07-29 11:24:34 -0700109 return main.ERROR
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700110 else:
Jon Hall80daded2015-05-27 16:07:00 -0700111 # TODO: Parse for failed pings, give some truncated output
kelvin-onlabedcff052015-01-16 12:53:55 -0800112 main.log.error( "Error, unexpected output in the ping file" )
Jon Hall2ef1e9e2014-11-18 14:27:05 -0500113 main.log.warn( outputs )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700114 return main.TRUE
115
shahshreya3140b1a2015-04-28 14:22:15 -0700116 def arping( self, host="", ip="10.128.20.211" ):
117 """
118 Description:
119 Sends arp message from mininet host for hosts discovery
120 Required:
121 host - hosts name
122 Optional:
123 ip - ip address that does not exist in the network so there would
124 be no reply.
125 """
126 cmd = " py " + host + ".cmd(\"arping -c 1 " + ip + "\")"
127 try:
128 main.log.warn( "Sending: " + cmd )
129 self.handle.sendline( cmd )
130 response = self.handle.before
131 self.handle.sendline( "" )
132 self.handle.expect( "mininet>" )
133 return main.TRUE
134
135 except pexpect.EOF:
136 main.log.error( self.name + ": EOF exception found" )
137 main.log.error( self.name + ": " + self.handle.before )
138 main.cleanup()
139 main.exit()
140
kelvin-onlabedcff052015-01-16 12:53:55 -0800141 def pingLong( self, **pingParams ):
142 """
Jon Hallefbd9792015-03-05 16:11:36 -0800143 Starts a continuous ping on the mininet host outputting
kelvin-onlabd3b64892015-01-20 13:26:24 -0800144 to a file in the /tmp dir.
kelvin-onlabedcff052015-01-16 12:53:55 -0800145 """
146 self.handle.sendline( "" )
147 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800148 args = utilities.parse_args(
kelvin-onlabedcff052015-01-16 12:53:55 -0800149 [ "SRC", "TARGET", "PINGTIME" ], **pingParams )
150 precmd = "sudo rm /tmp/ping." + args[ "SRC" ]
151 self.execute( cmd=precmd, prompt="(.*)", timeout=10 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800152 command = "sudo mininet/util/m " + args[ "SRC" ] + " ping " +\
Jon Hallefbd9792015-03-05 16:11:36 -0800153 args[ "TARGET" ] + " -i .2 -w " +\
154 str( args[ 'PINGTIME' ] ) + " -D > /tmp/ping." +\
155 args[ "SRC" ] + " &"
Jon Hallfbc828e2015-01-06 17:30:19 -0800156 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800157 self.execute( cmd=command, prompt="(.*)", timeout=10 )
158 self.handle.sendline( "" )
159 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700160 return main.TRUE
161
kelvin-onlabedcff052015-01-16 12:53:55 -0800162 def pingstatus( self, **pingParams ):
163 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800164 Tails the respective ping output file and check that
165 there is a moving "64 bytes"
kelvin-onlabedcff052015-01-16 12:53:55 -0800166 """
167 self.handle.sendline( "" )
168 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800169 args = utilities.parse_args( [ "SRC" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800170 self.handle.sendline( "tail /tmp/ping." + args[ "SRC" ] )
171 self.handle.expect( "tail" )
172 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700173 result = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800174 self.handle.sendline( "" )
175 self.handle.expect( "\$" )
176 if re.search( 'Unreachable', result ):
177 main.log.info( "Unreachable found in ping logs..." )
adminbae64d82013-08-01 10:50:15 -0700178 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800179 elif re.search( '64\sbytes', result ):
180 main.log.info( "Pings look good" )
adminbae64d82013-08-01 10:50:15 -0700181 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800182 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800183 main.log.info( "No, or faulty ping data..." )
adminbae64d82013-08-01 10:50:15 -0700184 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800185
kelvin-onlabedcff052015-01-16 12:53:55 -0800186 def pingKill( self, testONUser, testONIP ):
187 """
adminaeedddd2013-08-02 15:14:15 -0700188 Kills all continuous ping processes.
189 Then copies all the ping files to the TestStation.
kelvin-onlabedcff052015-01-16 12:53:55 -0800190 """
191 self.handle.sendline( "" )
192 self.handle.expect( "\$" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800193 command = "sudo kill -SIGINT `pgrep ping`"
194 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800195 self.execute( cmd=command, prompt="(.*)", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800196
adminbae64d82013-08-01 10:50:15 -0700197 main.log.info( "Transferring ping files to TestStation" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800198 command = "scp /tmp/ping.* " + \
199 str( testONUser ) + "@" + str( testONIP ) + ":/tmp/"
200 self.execute( cmd=command, prompt="100%", timeout=20 )
201 # Make sure the output is cleared
202 self.handle.sendline( "" )
203 self.handle.expect( "\$" )
204 self.handle.sendline( "" )
205 self.handle.expect( "\$" )
206 self.handle.sendline( "" )
207 i = self.handle.expect( [ "password", "\$" ] )
Jon Hall368769f2014-11-19 15:43:35 -0800208 if i == 0:
kelvin-onlabedcff052015-01-16 12:53:55 -0800209 main.log.error( "Error, sudo asking for password" )
210 main.log.error( self.handle.before )
Jon Hall368769f2014-11-19 15:43:35 -0800211 return main.FALSE
212 else:
213 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800214
kelvin-onlabedcff052015-01-16 12:53:55 -0800215 def pingLongKill( self ):
216 self.handle.sendline( "" )
217 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700218 command = "sudo kill -SIGING `pgrep ping`"
kelvin-onlabedcff052015-01-16 12:53:55 -0800219 main.log.info( command )
220 self.execute( cmd=command, prompt="(.*)", timeout=10 )
221 self.handle.sendline( "" )
222 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700223 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800224
kelvin-onlabedcff052015-01-16 12:53:55 -0800225 def pingHostOptical( self, **pingParams ):
226 """
Jon Hallefbd9792015-03-05 16:11:36 -0800227 This function is only for Packet Optical related ping
kelvin-onlabedcff052015-01-16 12:53:55 -0800228 Use the next pingHost() function for all normal scenarios )
shahshreya28bb18e2014-11-17 10:26:23 -0800229 Ping from one mininet host to another
230 Currently the only supported Params: SRC and TARGET
kelvin-onlabedcff052015-01-16 12:53:55 -0800231 """
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800232 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800233 command = args[ "SRC" ] + " ping " + \
234 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
shahshreya28bb18e2014-11-17 10:26:23 -0800235 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800236 main.log.warn( "Sending: " + command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800237 self.handle.sendline( command )
238 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800239 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800240 main.log.error(
241 self.name +
242 ": timeout when waiting for response from mininet" )
243 main.log.error( "response: " + str( self.handle.before ) )
244 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800245 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800246 main.log.error(
247 self.name +
248 ": timeout when waiting for response from mininet" )
249 main.log.error( "response: " + str( self.handle.before ) )
shahshreya28bb18e2014-11-17 10:26:23 -0800250 response = self.handle.before
251 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800252 main.log.error( self.name + ": EOF exception found" )
253 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800254 main.cleanup()
255 main.exit()
kelvin-onlabedcff052015-01-16 12:53:55 -0800256 main.log.info( self.name + ": Ping Response: " + response )
kelvin-onlabedcff052015-01-16 12:53:55 -0800257 if re.search( ',\s0\%\spacket\sloss', response ):
258 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800259 main.lastResult = main.TRUE
shahshreya28bb18e2014-11-17 10:26:23 -0800260 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800261 else:
262 main.log.error(
263 self.name +
264 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800265 main.lastResult = main.FALSE
shahshreya28bb18e2014-11-17 10:26:23 -0800266 return main.FALSE
267
kelvin-onlabedcff052015-01-16 12:53:55 -0800268 def pingHost( self, **pingParams ):
269 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800270 Pings between two hosts on remote mininet
kelvin-onlabedcff052015-01-16 12:53:55 -0800271 """
272 self.handle.sendline( "" )
273 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800274 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800275 command = "mininet/util/m " + \
276 args[ "SRC" ] + " ping " + args[ "TARGET" ] + " -c 4 -W 1 -i .2"
277 main.log.info( command )
278 response = self.execute( cmd=command, prompt="rtt", timeout=10 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800279 if utilities.assert_matches(
kelvin-onlabedcff052015-01-16 12:53:55 -0800280 expect=',\s0\%\spacket\sloss',
281 actual=response,
282 onpass="No Packet loss",
283 onfail="Host is not reachable" ):
284 main.log.info( "NO PACKET LOSS, HOST IS REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800285 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700286 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800287 else:
288 main.log.error( "PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800289 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700290 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800291
kelvin-onlabedcff052015-01-16 12:53:55 -0800292 def checknum( self, num ):
293 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800294 Verifies the correct number of switches are running
kelvin-onlabedcff052015-01-16 12:53:55 -0800295 """
296 if self.handle:
297 self.handle.sendline( "" )
298 self.handle.expect( "\$" )
299 self.handle.sendline( 'ifconfig -a | grep "sw.. " | wc -l' )
300 self.handle.expect( "wc" )
301 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700302 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800303 self.handle.sendline(
304 'ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l' )
305 self.handle.expect( "color" )
306 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700307 response2 = self.handle.before
308
kelvin-onlabedcff052015-01-16 12:53:55 -0800309 if re.search( num, response ):
310 if re.search( num, response2 ):
adminbae64d82013-08-01 10:50:15 -0700311 return main.TRUE
312 else:
313 return main.FALSE
314 else:
315 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800316 else:
317 main.log.error( "Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -0700318
kelvin-onlabd3b64892015-01-20 13:26:24 -0800319 def startTcpdump(
kelvin-onlabedcff052015-01-16 12:53:55 -0800320 self,
321 filename,
322 intf="eth0",
323 port="port 6633",
324 user="admin" ):
325 """
Jon Hallefbd9792015-03-05 16:11:36 -0800326 Runs tcpdump on an interface and saves the file
admin2a9548d2014-06-17 14:08:07 -0700327 intf can be specified, or the default eth0 is used
kelvin-onlabedcff052015-01-16 12:53:55 -0800328 """
admin2a9548d2014-06-17 14:08:07 -0700329 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800330 self.handle.sendline( "" )
331 self.handle.sendline(
332 "sudo tcpdump -n -i " +
333 intf +
334 " " +
335 port +
336 " -w " +
337 filename.strip() +
338 " -Z " +
339 user +
340 " &" )
341 self.handle.sendline( "" )
342 self.handle.sendline( "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800343 i = self.handle.expect( [ 'No\ssuch\device', 'listening\son',
344 pexpect.TIMEOUT, "\$" ], timeout=10 )
Jon Hall61282e32015-03-19 11:34:11 -0700345 main.log.info( self.handle.before + self.handle.after )
admin2a9548d2014-06-17 14:08:07 -0700346 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800347 main.log.error( self.name + ": tcpdump - No such device exists.\
348 tcpdump attempted on: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700349 return main.FALSE
350 elif i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800351 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -0700352 return main.TRUE
353 elif i == 2:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800354 main.log.error( self.name + ": tcpdump command timed out!\
355 Check interface name, given interface was: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700356 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800357 elif i == 3:
358 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700359 return main.TRUE
360 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800361 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -0700362 return main.FALSE
363 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800364 main.log.error( self.name + ": EOF exception found" )
365 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700366 main.cleanup()
367 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800368 except Exception:
369 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700370 main.cleanup()
371 main.exit()
372
kelvin-onlabd3b64892015-01-20 13:26:24 -0800373 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -0800374 """
375 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -0700376 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800377 self.handle.sendline( "sudo pkill tcpdump" )
378 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800379 self.handle.expect( "\$" )
admin2a9548d2014-06-17 14:08:07 -0700380 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800381 main.log.error( self.name + ": EOF exception found" )
382 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700383 main.cleanup()
384 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800385 except Exception:
386 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700387 main.cleanup()
388 main.exit()
389
shahshreya1f119da2015-04-21 17:16:46 -0700390 def runOpticalMnScript( self,name = 'onos', ctrllerIP = None ):
shahshreya2c57c902015-04-06 20:40:20 -0700391 import time
shahshreya1f119da2015-04-21 17:16:46 -0700392 import types
kelvin-onlabedcff052015-01-16 12:53:55 -0800393 """
shahshreya1f119da2015-04-21 17:16:46 -0700394 Description:
395 This function is only meant for Packet Optical.
396 It runs python script "opticalTest.py" to create the
397 packet layer( mn ) and optical topology
398 Optional:
399 name - Name of onos directory. (ONOS | onos)
400 Required:
401 ctrllerIP = Controller(s) IP address
402 TODO: If no ctrllerIP is provided, a default
shahshreya2c57c902015-04-06 20:40:20 -0700403 $OC1 can be accepted
kelvin-onlabedcff052015-01-16 12:53:55 -0800404 """
shahshreya28bb18e2014-11-17 10:26:23 -0800405 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800406 self.handle.sendline( "" )
407 self.handle.expect( "\$" )
shahshreya1f119da2015-04-21 17:16:46 -0700408 self.handle.sendline( "cd ~/" + name + "/tools/test/topos" )
shahshreya2c57c902015-04-06 20:40:20 -0700409 self.handle.expect( "topos\$" )
410 if ctrllerIP == None:
411 main.log.info( "You need to specify the IP" )
412 return main.FALSE
413 else:
shahshreya1f119da2015-04-21 17:16:46 -0700414 controller = ''
415 if isinstance( ctrllerIP, types.ListType ):
416 for i in xrange( len( ctrllerIP ) ):
417 controller += ctrllerIP[i] + ' '
418 main.log.info( "Mininet topology is being loaded with " +
419 "controllers: " + controller )
420 elif isinstance( ctrllerIP, types.StringType ):
421 controller = ctrllerIP
422 main.log.info( "Mininet topology is being loaded with " +
423 "controller: " + controller )
424 else:
425 main.log.info( "You need to specify a valid IP" )
426 return main.FALSE
427 cmd = "sudo -E python opticalTest.py " + controller
428 main.log.info( self.name + ": cmd = " + cmd )
shahshreya2c57c902015-04-06 20:40:20 -0700429 self.handle.sendline( cmd )
shahshreyad524a942015-04-21 09:55:16 -0700430 time.sleep(30)
shahshreya2c57c902015-04-06 20:40:20 -0700431 self.handle.sendline( "" )
shahshreya3140b1a2015-04-28 14:22:15 -0700432 self.handle.sendline( "" )
shahshreya2c57c902015-04-06 20:40:20 -0700433 self.handle.expect("mininet>")
434 return main.TRUE
435 except pexpect.EOF:
436 main.log.error( self.name + ": EOF exception found" )
437 main.log.error( self.name + ": " + self.handle.before )
438 return main.FALSE
439
440 def attachLincOESession( self ):
441 """
442 Since executing opticalTest.py will give you mininet
443 prompt, you would at some point require to get onto
444 console of LincOE ((linc@onosTestBench)1>) to execute
445 commands like bring a optical port up or down on a ROADM
446 You can attach to console of Linc-OE session by a cmd:
447 sudo ~/linc-oe/rel/linc/bin/linc attach
448 """
449 try:
450 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800451 self.handle.expect( "\$" )
shahshreya2c57c902015-04-06 20:40:20 -0700452 self.handle.sendline( "sudo ~/linc-oe/rel/linc/bin/linc attach" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800453 self.handle.expect( ">" )
shahshreya28bb18e2014-11-17 10:26:23 -0800454 return main.TRUE
455 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800456 main.log.error( self.name + ": EOF exception found" )
457 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800458 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700459
kelvin-onlabedcff052015-01-16 12:53:55 -0800460 def disconnect( self ):
461 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800462 Called at the end of the test to disconnect the handle.
kelvin-onlabedcff052015-01-16 12:53:55 -0800463 """
adminbae64d82013-08-01 10:50:15 -0700464 if self.handle:
shahshreya95dd6f82015-02-05 15:59:16 -0800465 # Close the ssh connection
466 self.handle.sendline( "" )
Jon Hallefbd9792015-03-05 16:11:36 -0800467 # self.handle.expect( "\$" )
Jon Hall390696c2015-05-05 17:13:41 -0700468 i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT,
469 pexpect.EOF ], timeout=2 )
shahshreyadccfbc62015-02-20 11:40:09 -0800470 if i == 0:
471 self.handle.sendline( "exit" )
472 self.handle.expect( "closed" )
473 elif i == 1:
474 self.handle.sendline( "exit" )
475 self.handle.expect( "exit" )
476 self.handle.expect('\$')
477 self.handle.sendline( "exit" )
478 self.handle.expect( "exit" )
479 self.handle.expect( "closed" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800480 else:
481 main.log.error( "Connection failed to the host" )
Jon Halld61331b2015-02-17 16:35:47 -0800482 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700483
kelvin-onlabd3b64892015-01-20 13:26:24 -0800484 def getFlowTable( self, protoVersion, sw ):
485 """
486 TODO document usage
Jon Hallefbd9792015-03-05 16:11:36 -0800487 TODO add option to look at cookies. ignoring them for now
kelvin-onlabd3b64892015-01-20 13:26:24 -0800488
489 print "get_flowTable(" + str( protoVersion ) +" " + str( sw ) +")"
490 NOTE: Use format to force consistent flow table output across
491 versions"""
kelvin-onlabedcff052015-01-16 12:53:55 -0800492 self.handle.sendline( "cd" )
493 self.handle.expect( [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
kelvin-onlabedcff052015-01-16 12:53:55 -0800494 if protoVersion == 1.0:
495 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800496 " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 \
497 $7 $8}' | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800498 self.handle.sendline( command )
499 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
500 self.handle.expect(
501 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700502 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800503 # print "response=", response
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700504 return response
kelvin-onlabedcff052015-01-16 12:53:55 -0800505 elif protoVersion == 1.3:
506 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800507 " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}'\
508 | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800509 self.handle.sendline( command )
510 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
511 self.handle.expect(
512 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700513 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800514 # print "response=", response
Jon Hall94fd0472014-12-08 11:52:42 -0800515 return response
516 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800517 main.log.error(
518 "Unknown protoVersion in get_flowTable(). given: (" +
519 str(
520 type( protoVersion ) ) +
521 ") '" +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800522 str( protoVersion ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800523 "'" )
Jon Hall94fd0472014-12-08 11:52:42 -0800524
kelvin-onlabd3b64892015-01-20 13:26:24 -0800525 def flowComp( self, flow1, flow2 ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800526 if flow1 == flow2:
santhosh19fd8032014-07-29 11:56:17 -0700527 return main.TRUE
528 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800529 main.log.info( "Flow tables do not match, printing tables:" )
530 main.log.info( "Flow Table 1:" )
531 main.log.info( flow1 )
532 main.log.info( "Flow Table 2:" )
533 main.log.info( flow2 )
santhosh19fd8032014-07-29 11:56:17 -0700534 return main.FALSE
535
kelvin-onlabd3b64892015-01-20 13:26:24 -0800536 def setIpTablesOUTPUT( self, dstIp, dstPort, action='add',
537 packetType='tcp', rule='DROP' ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800538 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700539 Description:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800540 add or remove iptables rule to DROP ( default )
541 packets from specific IP and PORT
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700542 Usage:
kelvin-onlabedcff052015-01-16 12:53:55 -0800543 * specify action ( 'add' or 'remove' )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700544 when removing, pass in the same argument as you would add. It will
Jon Hallfbc828e2015-01-06 17:30:19 -0800545 delete that specific rule.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800546 * specify the destination ip to block with dstIp
547 * specify destination port to block to dstPort
kelvin-onlabedcff052015-01-16 12:53:55 -0800548 * optional packet type to block ( default tcp )
549 * optional iptables rule ( default DROP )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700550 WARNING:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800551 * This function uses root privilege iptables command which may result
552 in unwanted network errors. USE WITH CAUTION
kelvin-onlabedcff052015-01-16 12:53:55 -0800553 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700554 import re
555 import time
556
kelvin-onlabedcff052015-01-16 12:53:55 -0800557 # NOTE*********
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700558 # The strict checking methods of this driver function is intentional
559 # to discourage any misuse or error of iptables, which can cause
560 # severe network errors
kelvin-onlabd3b64892015-01-20 13:26:24 -0800561 # *************
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700562
kelvin-onlabd3b64892015-01-20 13:26:24 -0800563 # NOTE: Sleep needed to give some time
564 # for rule to be added and registered
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700565 # to the instance
kelvin-onlabedcff052015-01-16 12:53:55 -0800566 time.sleep( 5 )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700567
kelvin-onlabd3b64892015-01-20 13:26:24 -0800568 actionType = action.lower()
569 if actionType != 'add' and actionType != 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800570 main.log.error(
571 "Invalid action type. 'add' or 'remove' table rule" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700572 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
kelvin-onlabedcff052015-01-16 12:53:55 -0800573 # NOTE: Currently only supports rules DROP, ACCEPT, and LOG
574 main.log.error(
575 "Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700576 return
577 return
578 else:
579
kelvin-onlabedcff052015-01-16 12:53:55 -0800580 # If there is no existing rule in the iptables, we will see an
kelvin-onlabd3b64892015-01-20 13:26:24 -0800581 # 'iptables:'... message. We expect to see this message.
kelvin-onlabedcff052015-01-16 12:53:55 -0800582 # Otherwise, if there IS an existing rule, we will get the prompt
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700583 # back, hence why we expect $ for remove type. We want to remove
584 # an already existing rule
585
kelvin-onlabd3b64892015-01-20 13:26:24 -0800586 if actionType == 'add':
587 # NOTE: "iptables:" expect is a result of
588 # return from the command
589 # iptables -C ...
590 # Any changes by the iptables command return string
591 # will result in failure of the function. ( deemed unlikely
592 # at the time of writing this function )
kelvin-onlabedcff052015-01-16 12:53:55 -0800593 # Check for existing rules on current input
594 self.handle.sendline( "" )
595 self.handle.expect( "\$" )
596 self.handle.sendline(
597 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800598 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800599 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800600 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800601 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800602 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800603 " -j " +
604 str( rule ) )
605 i = self.handle.expect( [ "iptables:", "\$" ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700606 print i
607 print self.handle.before
608 print "after: "
609 print self.handle.after
610
kelvin-onlabd3b64892015-01-20 13:26:24 -0800611 elif actionType == 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800612 # Check for existing rules on current input
613 self.handle.sendline( "" )
614 self.handle.expect( "\$" )
615 self.handle.sendline(
616 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800617 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800618 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800619 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800620 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800621 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800622 " -j " +
623 str( rule ) )
624 self.handle.expect( "\$" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700625 print "before: "
626 print self.handle.before
kelvin-onlabd3b64892015-01-20 13:26:24 -0800627 actualString = self.handle.after
628 expectString = "iptables:"
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700629 print "Actual String:"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800630 print actualString
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700631
kelvin-onlabd3b64892015-01-20 13:26:24 -0800632 if re.search( expectString, actualString ):
633 matchResult = main.TRUE
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700634 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800635 matchResult = main.FALSE
636 # If matchResult is main.TRUE, it means there is no matching rule.
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700637
kelvin-onlabd3b64892015-01-20 13:26:24 -0800638 # If tables does not exist and expected prompt is returned,
639 # go ahead and add iptables rule
640 if matchResult == main.TRUE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800641 # Ensure action type is add
kelvin-onlabd3b64892015-01-20 13:26:24 -0800642 if actionType == 'add':
643 # -A is the 'append' action of iptables
644 actionAdd = '-A'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700645 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800646 self.handle.sendline( "" )
647 self.handle.sendline(
648 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800649 actionAdd +
kelvin-onlabedcff052015-01-16 12:53:55 -0800650 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800651 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800652 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800653 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800654 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800655 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800656 " -j " +
657 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700658
kelvin-onlabd3b64892015-01-20 13:26:24 -0800659 infoString = "Rules added to " + str( self.name )
Jon Hallefbd9792015-03-05 16:11:36 -0800660 infoString += "iptables rule added to block IP: " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800661 str( dstIp )
662 infoString += "Port: " + \
663 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700664
kelvin-onlabd3b64892015-01-20 13:26:24 -0800665 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700666
kelvin-onlabedcff052015-01-16 12:53:55 -0800667 self.handle.expect(
668 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700669 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800670 main.log.error(
671 self.name +
672 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800673 except Exception:
674 main.log.exception( self.name +
675 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700676 main.cleanup()
677 main.exit()
678 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800679 main.log.error(
680 "Given rule already exists, but attempted to add it" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800681 # If matchResult is 0, it means there IS a matching rule provided
682 elif matchResult == main.FALSE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800683 # Ensure action type is remove
kelvin-onlabd3b64892015-01-20 13:26:24 -0800684 if actionType == 'remove':
685 # -D is the 'delete' rule of iptables
686 actionRemove = '-D'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700687 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800688 self.handle.sendline( "" )
689 # Delete a specific rule specified into the function
690 self.handle.sendline(
691 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800692 actionRemove +
kelvin-onlabedcff052015-01-16 12:53:55 -0800693 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800694 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800695 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800696 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800697 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800698 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800699 " -j " +
700 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700701
kelvin-onlabd3b64892015-01-20 13:26:24 -0800702 infoString = "Rules removed from " + str( self.name )
703 infoString += " iptables rule removed \
704 from blocking IP: " + \
705 str( dstIp )
706 infoString += " Port: " + \
707 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700708
kelvin-onlabd3b64892015-01-20 13:26:24 -0800709 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700710
kelvin-onlabedcff052015-01-16 12:53:55 -0800711 self.handle.expect(
712 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700713 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800714 main.log.error(
715 self.name +
716 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800717 except Exception:
718 main.log.exception( self.name +
719 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700720 main.cleanup()
721 main.exit()
722 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800723 main.log.error(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800724 "Given rule does not exist,\
725 but attempted to remove it" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700726 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800727 # NOTE: If a bad usage of this function occurs, exit the entire
728 # test
729 main.log.error( "Bad rule given for iptables. Exiting..." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700730 main.cleanup()
731 main.exit()
732
733
adminbae64d82013-08-01 10:50:15 -0700734if __name__ != "__main__":
735 import sys
kelvin-onlabedcff052015-01-16 12:53:55 -0800736 sys.modules[ __name__ ] = RemoteMininetDriver()