blob: 9c9585aa74cbcc8a885ef02760d5b8c8b7363523 [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"""
admin2a9548d2014-06-17 14:08:07 -070024import traceback
adminbae64d82013-08-01 10:50:15 -070025import pexpect
adminbae64d82013-08-01 10:50:15 -070026import re
27import sys
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
kelvin-onlabedcff052015-01-16 12:53:55 -080043 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070044 self.flag = 0
45
kelvin-onlabedcff052015-01-16 12:53:55 -080046 def connect( self, **connectargs ):
kelvin-onlab08679eb2015-01-21 16:11:48 -080047 """,user_name, ip_address, pwd,options ):
kelvin-onlabd3b64892015-01-20 13:26:24 -080048 Here the main is the TestON instance after creating all the log
49 handles."""
adminbae64d82013-08-01 10:50:15 -070050 for key in connectargs:
kelvin-onlabedcff052015-01-16 12:53:55 -080051 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080052
kelvin-onlabedcff052015-01-16 12:53:55 -080053 self.name = self.options[ 'name' ]
54 self.handle = super(
55 RemoteMininetDriver,
56 self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080057 user_name=self.user_name,
58 ip_address=self.ip_address,
kelvin-onlabedcff052015-01-16 12:53:55 -080059 port=None,
60 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080061
kelvin-onlabd3b64892015-01-20 13:26:24 -080062 self.sshHandle = self.handle
Jon Hallfbc828e2015-01-06 17:30:19 -080063
64 # Copying the readme file to process the
kelvin-onlabedcff052015-01-16 12:53:55 -080065 if self.handle:
adminbae64d82013-08-01 10:50:15 -070066 return main.TRUE
67
kelvin-onlabedcff052015-01-16 12:53:55 -080068 else:
69 main.log.error(
70 "Connection failed to the host " +
kelvin-onlab08679eb2015-01-21 16:11:48 -080071 self.user_name +
kelvin-onlabedcff052015-01-16 12:53:55 -080072 "@" +
kelvin-onlab08679eb2015-01-21 16:11:48 -080073 self.ip_address )
kelvin-onlabedcff052015-01-16 12:53:55 -080074 main.log.error( "Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -070075 return main.FALSE
admin98ad0092014-07-23 16:51:07 -070076
kelvin-onlabedcff052015-01-16 12:53:55 -080077 def checkForLoss( self, pingList ):
78 """
Jon Hall6c794f32014-08-14 13:33:13 -070079 Returns main.FALSE for 0% packet loss and
80 Returns main.ERROR if "found multiple mininet" is found and
81 Returns main.TRUE else
kelvin-onlabedcff052015-01-16 12:53:55 -080082 """
kelvin-onlabedcff052015-01-16 12:53:55 -080083 self.handle.sendline( "" )
84 self.handle.expect( "\$" )
kelvin-onlabedcff052015-01-16 12:53:55 -080085 self.handle.sendline( "" )
86 self.handle.expect( "\$" )
87 self.handle.sendline( "cat " + pingList )
88 self.handle.expect( pingList )
89 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -070090 outputs = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -080091 if re.search( " 0% packet loss", outputs ):
admin98ad0092014-07-23 16:51:07 -070092 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -080093 elif re.search( "found multiple mininet", outputs ):
admin2580a0e2014-07-29 11:24:34 -070094 return main.ERROR
shahshreyaf4d4d0c2014-10-10 12:11:10 -070095 else:
kelvin-onlabedcff052015-01-16 12:53:55 -080096 main.log.error( "Error, unexpected output in the ping file" )
Jon Hall2ef1e9e2014-11-18 14:27:05 -050097 main.log.warn( outputs )
shahshreyaf4d4d0c2014-10-10 12:11:10 -070098 return main.TRUE
99
kelvin-onlabedcff052015-01-16 12:53:55 -0800100 def pingLong( self, **pingParams ):
101 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800102 Starts a continuous ping on the mininet host outputing
103 to a file in the /tmp dir.
kelvin-onlabedcff052015-01-16 12:53:55 -0800104 """
105 self.handle.sendline( "" )
106 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800107 args = utilities.parse_args(
kelvin-onlabedcff052015-01-16 12:53:55 -0800108 [ "SRC", "TARGET", "PINGTIME" ], **pingParams )
109 precmd = "sudo rm /tmp/ping." + args[ "SRC" ]
110 self.execute( cmd=precmd, prompt="(.*)", timeout=10 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800111 command = "sudo mininet/util/m " + args[ "SRC" ] + " ping " +\
112 args[ "TARGET" ] + " -i .2 -w " + str( args[ 'PINGTIME' ] ) +\
113 " -D > /tmp/ping." + args[ "SRC" ] + " &"
Jon Hallfbc828e2015-01-06 17:30:19 -0800114 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800115 self.execute( cmd=command, prompt="(.*)", timeout=10 )
116 self.handle.sendline( "" )
117 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700118 return main.TRUE
119
kelvin-onlabedcff052015-01-16 12:53:55 -0800120 def pingstatus( self, **pingParams ):
121 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800122 Tails the respective ping output file and check that
123 there is a moving "64 bytes"
kelvin-onlabedcff052015-01-16 12:53:55 -0800124 """
125 self.handle.sendline( "" )
126 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800127 args = utilities.parse_args( [ "SRC" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800128 self.handle.sendline( "tail /tmp/ping." + args[ "SRC" ] )
129 self.handle.expect( "tail" )
130 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700131 result = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800132 self.handle.sendline( "" )
133 self.handle.expect( "\$" )
134 if re.search( 'Unreachable', result ):
135 main.log.info( "Unreachable found in ping logs..." )
adminbae64d82013-08-01 10:50:15 -0700136 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800137 elif re.search( '64\sbytes', result ):
138 main.log.info( "Pings look good" )
adminbae64d82013-08-01 10:50:15 -0700139 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800140 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800141 main.log.info( "No, or faulty ping data..." )
adminbae64d82013-08-01 10:50:15 -0700142 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800143
kelvin-onlabedcff052015-01-16 12:53:55 -0800144 def pingKill( self, testONUser, testONIP ):
145 """
adminaeedddd2013-08-02 15:14:15 -0700146 Kills all continuous ping processes.
147 Then copies all the ping files to the TestStation.
kelvin-onlabedcff052015-01-16 12:53:55 -0800148 """
149 self.handle.sendline( "" )
150 self.handle.expect( "\$" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800151 command = "sudo kill -SIGINT `pgrep ping`"
152 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800153 self.execute( cmd=command, prompt="(.*)", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800154
adminbae64d82013-08-01 10:50:15 -0700155 main.log.info( "Transferring ping files to TestStation" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800156 command = "scp /tmp/ping.* " + \
157 str( testONUser ) + "@" + str( testONIP ) + ":/tmp/"
158 self.execute( cmd=command, prompt="100%", timeout=20 )
159 # Make sure the output is cleared
160 self.handle.sendline( "" )
161 self.handle.expect( "\$" )
162 self.handle.sendline( "" )
163 self.handle.expect( "\$" )
164 self.handle.sendline( "" )
165 i = self.handle.expect( [ "password", "\$" ] )
Jon Hall368769f2014-11-19 15:43:35 -0800166 if i == 0:
kelvin-onlabedcff052015-01-16 12:53:55 -0800167 main.log.error( "Error, sudo asking for password" )
168 main.log.error( self.handle.before )
Jon Hall368769f2014-11-19 15:43:35 -0800169 return main.FALSE
170 else:
171 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800172
kelvin-onlabedcff052015-01-16 12:53:55 -0800173 def pingLongKill( self ):
174 self.handle.sendline( "" )
175 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700176 command = "sudo kill -SIGING `pgrep ping`"
kelvin-onlabedcff052015-01-16 12:53:55 -0800177 main.log.info( command )
178 self.execute( cmd=command, prompt="(.*)", timeout=10 )
179 self.handle.sendline( "" )
180 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700181 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800182
kelvin-onlabedcff052015-01-16 12:53:55 -0800183 def pingHostOptical( self, **pingParams ):
184 """
shahshreya28bb18e2014-11-17 10:26:23 -0800185 This function is only for Packey Optical related ping
kelvin-onlabedcff052015-01-16 12:53:55 -0800186 Use the next pingHost() function for all normal scenarios )
shahshreya28bb18e2014-11-17 10:26:23 -0800187 Ping from one mininet host to another
188 Currently the only supported Params: SRC and TARGET
kelvin-onlabedcff052015-01-16 12:53:55 -0800189 """
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800190 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800191 command = args[ "SRC" ] + " ping " + \
192 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
shahshreya28bb18e2014-11-17 10:26:23 -0800193 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800194 main.log.warn( "Sending: " + command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800195 self.handle.sendline( command )
196 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800197 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800198 main.log.error(
199 self.name +
200 ": timeout when waiting for response from mininet" )
201 main.log.error( "response: " + str( self.handle.before ) )
202 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800203 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800204 main.log.error(
205 self.name +
206 ": timeout when waiting for response from mininet" )
207 main.log.error( "response: " + str( self.handle.before ) )
shahshreya28bb18e2014-11-17 10:26:23 -0800208 response = self.handle.before
209 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800210 main.log.error( self.name + ": EOF exception found" )
211 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800212 main.cleanup()
213 main.exit()
kelvin-onlabedcff052015-01-16 12:53:55 -0800214 main.log.info( self.name + ": Ping Response: " + response )
kelvin-onlabedcff052015-01-16 12:53:55 -0800215 if re.search( ',\s0\%\spacket\sloss', response ):
216 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800217 main.lastResult = main.TRUE
shahshreya28bb18e2014-11-17 10:26:23 -0800218 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800219 else:
220 main.log.error(
221 self.name +
222 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800223 main.lastResult = main.FALSE
shahshreya28bb18e2014-11-17 10:26:23 -0800224 return main.FALSE
225
kelvin-onlabedcff052015-01-16 12:53:55 -0800226 def pingHost( self, **pingParams ):
227 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800228 Pings between two hosts on remote mininet
kelvin-onlabedcff052015-01-16 12:53:55 -0800229 """
230 self.handle.sendline( "" )
231 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800232 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800233 command = "mininet/util/m " + \
234 args[ "SRC" ] + " ping " + args[ "TARGET" ] + " -c 4 -W 1 -i .2"
235 main.log.info( command )
236 response = self.execute( cmd=command, prompt="rtt", timeout=10 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800237 if utilities.assert_matches(
kelvin-onlabedcff052015-01-16 12:53:55 -0800238 expect=',\s0\%\spacket\sloss',
239 actual=response,
240 onpass="No Packet loss",
241 onfail="Host is not reachable" ):
242 main.log.info( "NO PACKET LOSS, HOST IS REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800243 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700244 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800245 else:
246 main.log.error( "PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800247 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700248 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800249
kelvin-onlabedcff052015-01-16 12:53:55 -0800250 def checknum( self, num ):
251 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800252 Verifies the correct number of switches are running
kelvin-onlabedcff052015-01-16 12:53:55 -0800253 """
254 if self.handle:
255 self.handle.sendline( "" )
256 self.handle.expect( "\$" )
257 self.handle.sendline( 'ifconfig -a | grep "sw.. " | wc -l' )
258 self.handle.expect( "wc" )
259 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700260 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800261 self.handle.sendline(
262 'ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l' )
263 self.handle.expect( "color" )
264 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700265 response2 = self.handle.before
266
kelvin-onlabedcff052015-01-16 12:53:55 -0800267 if re.search( num, response ):
268 if re.search( num, response2 ):
adminbae64d82013-08-01 10:50:15 -0700269 return main.TRUE
270 else:
271 return main.FALSE
272 else:
273 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800274 else:
275 main.log.error( "Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -0700276
kelvin-onlabd3b64892015-01-20 13:26:24 -0800277 def startTcpdump(
kelvin-onlabedcff052015-01-16 12:53:55 -0800278 self,
279 filename,
280 intf="eth0",
281 port="port 6633",
282 user="admin" ):
283 """
admin2a9548d2014-06-17 14:08:07 -0700284 Runs tpdump on an intferface and saves the file
285 intf can be specified, or the default eth0 is used
kelvin-onlabedcff052015-01-16 12:53:55 -0800286 """
admin2a9548d2014-06-17 14:08:07 -0700287 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800288 self.handle.sendline( "" )
289 self.handle.sendline(
290 "sudo tcpdump -n -i " +
291 intf +
292 " " +
293 port +
294 " -w " +
295 filename.strip() +
296 " -Z " +
297 user +
298 " &" )
299 self.handle.sendline( "" )
300 self.handle.sendline( "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800301 i = self.handle.expect( [ 'No\ssuch\device', 'listening\son',
302 pexpect.TIMEOUT, "\$" ], timeout=10 )
kelvin-onlabedcff052015-01-16 12:53:55 -0800303 main.log.warn( self.handle.before + self.handle.after )
admin2a9548d2014-06-17 14:08:07 -0700304 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800305 main.log.error( self.name + ": tcpdump - No such device exists.\
306 tcpdump attempted on: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700307 return main.FALSE
308 elif i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800309 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -0700310 return main.TRUE
311 elif i == 2:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800312 main.log.error( self.name + ": tcpdump command timed out!\
313 Check interface name, given interface was: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700314 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800315 elif i == 3:
316 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700317 return main.TRUE
318 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800319 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -0700320 return main.FALSE
321 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800322 main.log.error( self.name + ": EOF exception found" )
323 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700324 main.cleanup()
325 main.exit()
326 except:
kelvin-onlabedcff052015-01-16 12:53:55 -0800327 main.log.info(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800328 self.name + ":" * 60 )
kelvin-onlab64b33712015-01-21 15:26:15 -0800329 main.log.error( traceback.print_exc() )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800330 main.log.info( ":" * 80 )
admin2a9548d2014-06-17 14:08:07 -0700331 main.cleanup()
332 main.exit()
333
kelvin-onlabd3b64892015-01-20 13:26:24 -0800334 def stopTcpdump( self ):
admin2a9548d2014-06-17 14:08:07 -0700335 "pkills tcpdump"
336 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800337 self.handle.sendline( "sudo pkill tcpdump" )
338 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800339 self.handle.expect( "\$" )
admin2a9548d2014-06-17 14:08:07 -0700340 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800341 main.log.error( self.name + ": EOF exception found" )
342 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700343 main.cleanup()
344 main.exit()
345 except:
kelvin-onlabedcff052015-01-16 12:53:55 -0800346 main.log.info(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800347 self.name + ":" * 60 )
kelvin-onlab64b33712015-01-21 15:26:15 -0800348 main.log.error( traceback.print_exc() )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800349 main.log.info( ":" * 80 )
admin2a9548d2014-06-17 14:08:07 -0700350 main.cleanup()
351 main.exit()
352
kelvin-onlabd3b64892015-01-20 13:26:24 -0800353 def runOpticalMnScript( self ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800354 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800355 This function is only meant for Packet Optical.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800356 It runs the python script "optical.py" to create the
357 packet layer( mn ) topology
kelvin-onlabedcff052015-01-16 12:53:55 -0800358 """
shahshreya28bb18e2014-11-17 10:26:23 -0800359 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800360 self.handle.sendline( "" )
361 self.handle.expect( "\$" )
362 self.handle.sendline( "cd ~" )
363 self.handle.expect( "\$" )
364 self.handle.sendline( "sudo python optical.py" )
365 self.handle.expect( ">" )
shahshreya28bb18e2014-11-17 10:26:23 -0800366 return main.TRUE
367 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800368 main.log.error( self.name + ": EOF exception found" )
369 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800370 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700371
kelvin-onlabedcff052015-01-16 12:53:55 -0800372 def disconnect( self ):
373 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800374 Called at the end of the test to disconnect the handle.
kelvin-onlabedcff052015-01-16 12:53:55 -0800375 """
adminbae64d82013-08-01 10:50:15 -0700376 if self.handle:
shahshreya95dd6f82015-02-05 15:59:16 -0800377 # Close the ssh connection
378 self.handle.sendline( "" )
shahshreyadccfbc62015-02-20 11:40:09 -0800379 #self.handle.expect( "\$" )
380 i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT ],
381 timeout = 2)
382 if i == 0:
383 self.handle.sendline( "exit" )
384 self.handle.expect( "closed" )
385 elif i == 1:
386 self.handle.sendline( "exit" )
387 self.handle.expect( "exit" )
388 self.handle.expect('\$')
389 self.handle.sendline( "exit" )
390 self.handle.expect( "exit" )
391 self.handle.expect( "closed" )
392
kelvin-onlabedcff052015-01-16 12:53:55 -0800393 else:
394 main.log.error( "Connection failed to the host" )
Jon Halld61331b2015-02-17 16:35:47 -0800395 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700396
kelvin-onlabd3b64892015-01-20 13:26:24 -0800397 def getFlowTable( self, protoVersion, sw ):
398 """
399 TODO document usage
400 TODO add option to look at cookies. ignoreing them for now
401
402 print "get_flowTable(" + str( protoVersion ) +" " + str( sw ) +")"
403 NOTE: Use format to force consistent flow table output across
404 versions"""
kelvin-onlabedcff052015-01-16 12:53:55 -0800405 self.handle.sendline( "cd" )
406 self.handle.expect( [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
kelvin-onlabedcff052015-01-16 12:53:55 -0800407 if protoVersion == 1.0:
408 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800409 " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 \
410 $7 $8}' | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800411 self.handle.sendline( command )
412 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
413 self.handle.expect(
414 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700415 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800416 # print "response=", response
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700417 return response
kelvin-onlabedcff052015-01-16 12:53:55 -0800418 elif protoVersion == 1.3:
419 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800420 " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}'\
421 | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800422 self.handle.sendline( command )
423 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
424 self.handle.expect(
425 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700426 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800427 # print "response=", response
Jon Hall94fd0472014-12-08 11:52:42 -0800428 return response
429 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800430 main.log.error(
431 "Unknown protoVersion in get_flowTable(). given: (" +
432 str(
433 type( protoVersion ) ) +
434 ") '" +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800435 str( protoVersion ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800436 "'" )
Jon Hall94fd0472014-12-08 11:52:42 -0800437
kelvin-onlabd3b64892015-01-20 13:26:24 -0800438 def flowComp( self, flow1, flow2 ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800439 if flow1 == flow2:
santhosh19fd8032014-07-29 11:56:17 -0700440 return main.TRUE
441 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800442 main.log.info( "Flow tables do not match, printing tables:" )
443 main.log.info( "Flow Table 1:" )
444 main.log.info( flow1 )
445 main.log.info( "Flow Table 2:" )
446 main.log.info( flow2 )
santhosh19fd8032014-07-29 11:56:17 -0700447 return main.FALSE
448
kelvin-onlabd3b64892015-01-20 13:26:24 -0800449 def setIpTablesOUTPUT( self, dstIp, dstPort, action='add',
450 packetType='tcp', rule='DROP' ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800451 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700452 Description:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800453 add or remove iptables rule to DROP ( default )
454 packets from specific IP and PORT
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700455 Usage:
kelvin-onlabedcff052015-01-16 12:53:55 -0800456 * specify action ( 'add' or 'remove' )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700457 when removing, pass in the same argument as you would add. It will
Jon Hallfbc828e2015-01-06 17:30:19 -0800458 delete that specific rule.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800459 * specify the destination ip to block with dstIp
460 * specify destination port to block to dstPort
kelvin-onlabedcff052015-01-16 12:53:55 -0800461 * optional packet type to block ( default tcp )
462 * optional iptables rule ( default DROP )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700463 WARNING:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800464 * This function uses root privilege iptables command which may result
465 in unwanted network errors. USE WITH CAUTION
kelvin-onlabedcff052015-01-16 12:53:55 -0800466 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700467 import re
468 import time
469
kelvin-onlabedcff052015-01-16 12:53:55 -0800470 # NOTE*********
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700471 # The strict checking methods of this driver function is intentional
472 # to discourage any misuse or error of iptables, which can cause
473 # severe network errors
kelvin-onlabd3b64892015-01-20 13:26:24 -0800474 # *************
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700475
kelvin-onlabd3b64892015-01-20 13:26:24 -0800476 # NOTE: Sleep needed to give some time
477 # for rule to be added and registered
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700478 # to the instance
kelvin-onlabedcff052015-01-16 12:53:55 -0800479 time.sleep( 5 )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700480
kelvin-onlabd3b64892015-01-20 13:26:24 -0800481 actionType = action.lower()
482 if actionType != 'add' and actionType != 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800483 main.log.error(
484 "Invalid action type. 'add' or 'remove' table rule" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700485 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
kelvin-onlabedcff052015-01-16 12:53:55 -0800486 # NOTE: Currently only supports rules DROP, ACCEPT, and LOG
487 main.log.error(
488 "Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700489 return
490 return
491 else:
492
kelvin-onlabedcff052015-01-16 12:53:55 -0800493 # If there is no existing rule in the iptables, we will see an
kelvin-onlabd3b64892015-01-20 13:26:24 -0800494 # 'iptables:'... message. We expect to see this message.
kelvin-onlabedcff052015-01-16 12:53:55 -0800495 # Otherwise, if there IS an existing rule, we will get the prompt
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700496 # back, hence why we expect $ for remove type. We want to remove
497 # an already existing rule
498
kelvin-onlabd3b64892015-01-20 13:26:24 -0800499 if actionType == 'add':
500 # NOTE: "iptables:" expect is a result of
501 # return from the command
502 # iptables -C ...
503 # Any changes by the iptables command return string
504 # will result in failure of the function. ( deemed unlikely
505 # at the time of writing this function )
kelvin-onlabedcff052015-01-16 12:53:55 -0800506 # Check for existing rules on current input
507 self.handle.sendline( "" )
508 self.handle.expect( "\$" )
509 self.handle.sendline(
510 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800511 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800512 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800513 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800514 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800515 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800516 " -j " +
517 str( rule ) )
518 i = self.handle.expect( [ "iptables:", "\$" ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700519 print i
520 print self.handle.before
521 print "after: "
522 print self.handle.after
523
kelvin-onlabd3b64892015-01-20 13:26:24 -0800524 elif actionType == 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800525 # Check for existing rules on current input
526 self.handle.sendline( "" )
527 self.handle.expect( "\$" )
528 self.handle.sendline(
529 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800530 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800531 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800532 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800533 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800534 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800535 " -j " +
536 str( rule ) )
537 self.handle.expect( "\$" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700538 print "before: "
539 print self.handle.before
kelvin-onlabd3b64892015-01-20 13:26:24 -0800540 actualString = self.handle.after
541 expectString = "iptables:"
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700542 print "Actual String:"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800543 print actualString
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700544
kelvin-onlabd3b64892015-01-20 13:26:24 -0800545 if re.search( expectString, actualString ):
546 matchResult = main.TRUE
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700547 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800548 matchResult = main.FALSE
549 # If matchResult is main.TRUE, it means there is no matching rule.
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700550
kelvin-onlabd3b64892015-01-20 13:26:24 -0800551 # If tables does not exist and expected prompt is returned,
552 # go ahead and add iptables rule
553 if matchResult == main.TRUE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800554 # Ensure action type is add
kelvin-onlabd3b64892015-01-20 13:26:24 -0800555 if actionType == 'add':
556 # -A is the 'append' action of iptables
557 actionAdd = '-A'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700558 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800559 self.handle.sendline( "" )
560 self.handle.sendline(
561 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800562 actionAdd +
kelvin-onlabedcff052015-01-16 12:53:55 -0800563 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800564 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800565 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800566 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800567 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800568 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800569 " -j " +
570 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700571
kelvin-onlabd3b64892015-01-20 13:26:24 -0800572 infoString = "Rules added to " + str( self.name )
573 infoString += "iptable rule added to block IP: " + \
574 str( dstIp )
575 infoString += "Port: " + \
576 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700577
kelvin-onlabd3b64892015-01-20 13:26:24 -0800578 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700579
kelvin-onlabedcff052015-01-16 12:53:55 -0800580 self.handle.expect(
581 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700582 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800583 main.log.error(
584 self.name +
585 ": Timeout exception in setIpTables function" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700586 except:
kelvin-onlab64b33712015-01-21 15:26:15 -0800587 main.log.error( traceback.print_exc() )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700588 main.cleanup()
589 main.exit()
590 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800591 main.log.error(
592 "Given rule already exists, but attempted to add it" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800593 # If matchResult is 0, it means there IS a matching rule provided
594 elif matchResult == main.FALSE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800595 # Ensure action type is remove
kelvin-onlabd3b64892015-01-20 13:26:24 -0800596 if actionType == 'remove':
597 # -D is the 'delete' rule of iptables
598 actionRemove = '-D'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700599 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800600 self.handle.sendline( "" )
601 # Delete a specific rule specified into the function
602 self.handle.sendline(
603 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800604 actionRemove +
kelvin-onlabedcff052015-01-16 12:53:55 -0800605 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800606 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800607 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800608 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800609 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800610 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800611 " -j " +
612 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700613
kelvin-onlabd3b64892015-01-20 13:26:24 -0800614 infoString = "Rules removed from " + str( self.name )
615 infoString += " iptables rule removed \
616 from blocking IP: " + \
617 str( dstIp )
618 infoString += " Port: " + \
619 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700620
kelvin-onlabd3b64892015-01-20 13:26:24 -0800621 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700622
kelvin-onlabedcff052015-01-16 12:53:55 -0800623 self.handle.expect(
624 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700625 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800626 main.log.error(
627 self.name +
628 ": Timeout exception in setIpTables function" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700629 except:
kelvin-onlab64b33712015-01-21 15:26:15 -0800630 main.log.error( traceback.print_exc() )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700631 main.cleanup()
632 main.exit()
633 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800634 main.log.error(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800635 "Given rule does not exist,\
636 but attempted to remove it" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700637 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800638 # NOTE: If a bad usage of this function occurs, exit the entire
639 # test
640 main.log.error( "Bad rule given for iptables. Exiting..." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700641 main.cleanup()
642 main.exit()
643
644
adminbae64d82013-08-01 10:50:15 -0700645if __name__ != "__main__":
646 import sys
kelvin-onlabedcff052015-01-16 12:53:55 -0800647 sys.modules[ __name__ ] = RemoteMininetDriver()