blob: d842cbb71e0ef501bae93e69dd28959a79a65c66 [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-onlabedcff052015-01-16 12:53:55 -080027sys.path.append( "../" )
adminbae64d82013-08-01 10:50:15 -070028from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070029
kelvin-onlabedcff052015-01-16 12:53:55 -080030
31class RemoteMininetDriver( Emulator ):
32
33 """
kelvin-onlabd3b64892015-01-20 13:26:24 -080034 RemoteMininetCliDriver is the basic driver which will handle the Mininet
35 functions. The main different between this and the MininetCliDriver is that
36 this one does not build the mininet. It assumes that there is already a
37 mininet running on the target.
kelvin-onlabedcff052015-01-16 12:53:55 -080038 """
39 def __init__( self ):
40 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070041 self.handle = self
kelvin-onlabedcff052015-01-16 12:53:55 -080042 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070043 self.flag = 0
44
kelvin-onlabedcff052015-01-16 12:53:55 -080045 def connect( self, **connectargs ):
kelvin-onlab08679eb2015-01-21 16:11:48 -080046 """,user_name, ip_address, pwd,options ):
kelvin-onlabd3b64892015-01-20 13:26:24 -080047 Here the main is the TestON instance after creating all the log
48 handles."""
adminbae64d82013-08-01 10:50:15 -070049 for key in connectargs:
kelvin-onlabedcff052015-01-16 12:53:55 -080050 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080051
kelvin-onlabedcff052015-01-16 12:53:55 -080052 self.name = self.options[ 'name' ]
53 self.handle = super(
54 RemoteMininetDriver,
55 self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080056 user_name=self.user_name,
57 ip_address=self.ip_address,
kelvin-onlabedcff052015-01-16 12:53:55 -080058 port=None,
59 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080060
kelvin-onlabd3b64892015-01-20 13:26:24 -080061 self.sshHandle = self.handle
Jon Hallfbc828e2015-01-06 17:30:19 -080062
63 # Copying the readme file to process the
kelvin-onlabedcff052015-01-16 12:53:55 -080064 if self.handle:
adminbae64d82013-08-01 10:50:15 -070065 return main.TRUE
66
kelvin-onlabedcff052015-01-16 12:53:55 -080067 else:
68 main.log.error(
69 "Connection failed to the host " +
kelvin-onlab08679eb2015-01-21 16:11:48 -080070 self.user_name +
kelvin-onlabedcff052015-01-16 12:53:55 -080071 "@" +
kelvin-onlab08679eb2015-01-21 16:11:48 -080072 self.ip_address )
kelvin-onlabedcff052015-01-16 12:53:55 -080073 main.log.error( "Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -070074 return main.FALSE
admin98ad0092014-07-23 16:51:07 -070075
kelvin-onlabedcff052015-01-16 12:53:55 -080076 def checkForLoss( self, pingList ):
77 """
Jon Hall6c794f32014-08-14 13:33:13 -070078 Returns main.FALSE for 0% packet loss and
79 Returns main.ERROR if "found multiple mininet" is found and
80 Returns main.TRUE else
kelvin-onlabedcff052015-01-16 12:53:55 -080081 """
kelvin-onlabedcff052015-01-16 12:53:55 -080082 self.handle.sendline( "" )
83 self.handle.expect( "\$" )
kelvin-onlabedcff052015-01-16 12:53:55 -080084 self.handle.sendline( "" )
85 self.handle.expect( "\$" )
86 self.handle.sendline( "cat " + pingList )
87 self.handle.expect( pingList )
88 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -070089 outputs = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -080090 if re.search( " 0% packet loss", outputs ):
admin98ad0092014-07-23 16:51:07 -070091 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -080092 elif re.search( "found multiple mininet", outputs ):
admin2580a0e2014-07-29 11:24:34 -070093 return main.ERROR
shahshreyaf4d4d0c2014-10-10 12:11:10 -070094 else:
kelvin-onlabedcff052015-01-16 12:53:55 -080095 main.log.error( "Error, unexpected output in the ping file" )
Jon Hall2ef1e9e2014-11-18 14:27:05 -050096 main.log.warn( outputs )
shahshreyaf4d4d0c2014-10-10 12:11:10 -070097 return main.TRUE
98
kelvin-onlabedcff052015-01-16 12:53:55 -080099 def pingLong( self, **pingParams ):
100 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800101 Starts a continuous ping on the mininet host outputing
102 to a file in the /tmp dir.
kelvin-onlabedcff052015-01-16 12:53:55 -0800103 """
104 self.handle.sendline( "" )
105 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800106 args = utilities.parse_args(
kelvin-onlabedcff052015-01-16 12:53:55 -0800107 [ "SRC", "TARGET", "PINGTIME" ], **pingParams )
108 precmd = "sudo rm /tmp/ping." + args[ "SRC" ]
109 self.execute( cmd=precmd, prompt="(.*)", timeout=10 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800110 command = "sudo mininet/util/m " + args[ "SRC" ] + " ping " +\
111 args[ "TARGET" ] + " -i .2 -w " + str( args[ 'PINGTIME' ] ) +\
112 " -D > /tmp/ping." + args[ "SRC" ] + " &"
Jon Hallfbc828e2015-01-06 17:30:19 -0800113 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800114 self.execute( cmd=command, prompt="(.*)", timeout=10 )
115 self.handle.sendline( "" )
116 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700117 return main.TRUE
118
kelvin-onlabedcff052015-01-16 12:53:55 -0800119 def pingstatus( self, **pingParams ):
120 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800121 Tails the respective ping output file and check that
122 there is a moving "64 bytes"
kelvin-onlabedcff052015-01-16 12:53:55 -0800123 """
124 self.handle.sendline( "" )
125 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800126 args = utilities.parse_args( [ "SRC" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800127 self.handle.sendline( "tail /tmp/ping." + args[ "SRC" ] )
128 self.handle.expect( "tail" )
129 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700130 result = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800131 self.handle.sendline( "" )
132 self.handle.expect( "\$" )
133 if re.search( 'Unreachable', result ):
134 main.log.info( "Unreachable found in ping logs..." )
adminbae64d82013-08-01 10:50:15 -0700135 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800136 elif re.search( '64\sbytes', result ):
137 main.log.info( "Pings look good" )
adminbae64d82013-08-01 10:50:15 -0700138 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800139 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800140 main.log.info( "No, or faulty ping data..." )
adminbae64d82013-08-01 10:50:15 -0700141 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800142
kelvin-onlabedcff052015-01-16 12:53:55 -0800143 def pingKill( self, testONUser, testONIP ):
144 """
adminaeedddd2013-08-02 15:14:15 -0700145 Kills all continuous ping processes.
146 Then copies all the ping files to the TestStation.
kelvin-onlabedcff052015-01-16 12:53:55 -0800147 """
148 self.handle.sendline( "" )
149 self.handle.expect( "\$" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800150 command = "sudo kill -SIGINT `pgrep ping`"
151 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800152 self.execute( cmd=command, prompt="(.*)", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800153
adminbae64d82013-08-01 10:50:15 -0700154 main.log.info( "Transferring ping files to TestStation" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800155 command = "scp /tmp/ping.* " + \
156 str( testONUser ) + "@" + str( testONIP ) + ":/tmp/"
157 self.execute( cmd=command, prompt="100%", timeout=20 )
158 # Make sure the output is cleared
159 self.handle.sendline( "" )
160 self.handle.expect( "\$" )
161 self.handle.sendline( "" )
162 self.handle.expect( "\$" )
163 self.handle.sendline( "" )
164 i = self.handle.expect( [ "password", "\$" ] )
Jon Hall368769f2014-11-19 15:43:35 -0800165 if i == 0:
kelvin-onlabedcff052015-01-16 12:53:55 -0800166 main.log.error( "Error, sudo asking for password" )
167 main.log.error( self.handle.before )
Jon Hall368769f2014-11-19 15:43:35 -0800168 return main.FALSE
169 else:
170 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800171
kelvin-onlabedcff052015-01-16 12:53:55 -0800172 def pingLongKill( self ):
173 self.handle.sendline( "" )
174 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700175 command = "sudo kill -SIGING `pgrep ping`"
kelvin-onlabedcff052015-01-16 12:53:55 -0800176 main.log.info( command )
177 self.execute( cmd=command, prompt="(.*)", timeout=10 )
178 self.handle.sendline( "" )
179 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700180 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800181
kelvin-onlabedcff052015-01-16 12:53:55 -0800182 def pingHostOptical( self, **pingParams ):
183 """
shahshreya28bb18e2014-11-17 10:26:23 -0800184 This function is only for Packey Optical related ping
kelvin-onlabedcff052015-01-16 12:53:55 -0800185 Use the next pingHost() function for all normal scenarios )
shahshreya28bb18e2014-11-17 10:26:23 -0800186 Ping from one mininet host to another
187 Currently the only supported Params: SRC and TARGET
kelvin-onlabedcff052015-01-16 12:53:55 -0800188 """
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800189 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800190 command = args[ "SRC" ] + " ping " + \
191 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
shahshreya28bb18e2014-11-17 10:26:23 -0800192 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800193 main.log.warn( "Sending: " + command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800194 self.handle.sendline( command )
195 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800196 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800197 main.log.error(
198 self.name +
199 ": timeout when waiting for response from mininet" )
200 main.log.error( "response: " + str( self.handle.before ) )
201 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800202 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800203 main.log.error(
204 self.name +
205 ": timeout when waiting for response from mininet" )
206 main.log.error( "response: " + str( self.handle.before ) )
shahshreya28bb18e2014-11-17 10:26:23 -0800207 response = self.handle.before
208 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800209 main.log.error( self.name + ": EOF exception found" )
210 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800211 main.cleanup()
212 main.exit()
kelvin-onlabedcff052015-01-16 12:53:55 -0800213 main.log.info( self.name + ": Ping Response: " + response )
kelvin-onlabedcff052015-01-16 12:53:55 -0800214 if re.search( ',\s0\%\spacket\sloss', response ):
215 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800216 main.lastResult = main.TRUE
shahshreya28bb18e2014-11-17 10:26:23 -0800217 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800218 else:
219 main.log.error(
220 self.name +
221 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800222 main.lastResult = main.FALSE
shahshreya28bb18e2014-11-17 10:26:23 -0800223 return main.FALSE
224
kelvin-onlabedcff052015-01-16 12:53:55 -0800225 def pingHost( self, **pingParams ):
226 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800227 Pings between two hosts on remote mininet
kelvin-onlabedcff052015-01-16 12:53:55 -0800228 """
229 self.handle.sendline( "" )
230 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800231 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800232 command = "mininet/util/m " + \
233 args[ "SRC" ] + " ping " + args[ "TARGET" ] + " -c 4 -W 1 -i .2"
234 main.log.info( command )
235 response = self.execute( cmd=command, prompt="rtt", timeout=10 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800236 if utilities.assert_matches(
kelvin-onlabedcff052015-01-16 12:53:55 -0800237 expect=',\s0\%\spacket\sloss',
238 actual=response,
239 onpass="No Packet loss",
240 onfail="Host is not reachable" ):
241 main.log.info( "NO PACKET LOSS, HOST IS REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800242 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700243 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800244 else:
245 main.log.error( "PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800246 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700247 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800248
kelvin-onlabedcff052015-01-16 12:53:55 -0800249 def checknum( self, num ):
250 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800251 Verifies the correct number of switches are running
kelvin-onlabedcff052015-01-16 12:53:55 -0800252 """
253 if self.handle:
254 self.handle.sendline( "" )
255 self.handle.expect( "\$" )
256 self.handle.sendline( 'ifconfig -a | grep "sw.. " | wc -l' )
257 self.handle.expect( "wc" )
258 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700259 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800260 self.handle.sendline(
261 'ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l' )
262 self.handle.expect( "color" )
263 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700264 response2 = self.handle.before
265
kelvin-onlabedcff052015-01-16 12:53:55 -0800266 if re.search( num, response ):
267 if re.search( num, response2 ):
adminbae64d82013-08-01 10:50:15 -0700268 return main.TRUE
269 else:
270 return main.FALSE
271 else:
272 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800273 else:
274 main.log.error( "Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -0700275
kelvin-onlabd3b64892015-01-20 13:26:24 -0800276 def startTcpdump(
kelvin-onlabedcff052015-01-16 12:53:55 -0800277 self,
278 filename,
279 intf="eth0",
280 port="port 6633",
281 user="admin" ):
282 """
admin2a9548d2014-06-17 14:08:07 -0700283 Runs tpdump on an intferface and saves the file
284 intf can be specified, or the default eth0 is used
kelvin-onlabedcff052015-01-16 12:53:55 -0800285 """
admin2a9548d2014-06-17 14:08:07 -0700286 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800287 self.handle.sendline( "" )
288 self.handle.sendline(
289 "sudo tcpdump -n -i " +
290 intf +
291 " " +
292 port +
293 " -w " +
294 filename.strip() +
295 " -Z " +
296 user +
297 " &" )
298 self.handle.sendline( "" )
299 self.handle.sendline( "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800300 i = self.handle.expect( [ 'No\ssuch\device', 'listening\son',
301 pexpect.TIMEOUT, "\$" ], timeout=10 )
kelvin-onlabedcff052015-01-16 12:53:55 -0800302 main.log.warn( self.handle.before + self.handle.after )
admin2a9548d2014-06-17 14:08:07 -0700303 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800304 main.log.error( self.name + ": tcpdump - No such device exists.\
305 tcpdump attempted on: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700306 return main.FALSE
307 elif i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800308 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -0700309 return main.TRUE
310 elif i == 2:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800311 main.log.error( self.name + ": tcpdump command timed out!\
312 Check interface name, given interface was: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700313 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800314 elif i == 3:
315 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700316 return main.TRUE
317 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800318 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -0700319 return main.FALSE
320 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800321 main.log.error( self.name + ": EOF exception found" )
322 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700323 main.cleanup()
324 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800325 except Exception:
326 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700327 main.cleanup()
328 main.exit()
329
kelvin-onlabd3b64892015-01-20 13:26:24 -0800330 def stopTcpdump( self ):
admin2a9548d2014-06-17 14:08:07 -0700331 "pkills tcpdump"
332 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800333 self.handle.sendline( "sudo pkill tcpdump" )
334 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800335 self.handle.expect( "\$" )
admin2a9548d2014-06-17 14:08:07 -0700336 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800337 main.log.error( self.name + ": EOF exception found" )
338 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700339 main.cleanup()
340 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800341 except Exception:
342 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700343 main.cleanup()
344 main.exit()
345
kelvin-onlabd3b64892015-01-20 13:26:24 -0800346 def runOpticalMnScript( self ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800347 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800348 This function is only meant for Packet Optical.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800349 It runs the python script "optical.py" to create the
350 packet layer( mn ) topology
kelvin-onlabedcff052015-01-16 12:53:55 -0800351 """
shahshreya28bb18e2014-11-17 10:26:23 -0800352 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800353 self.handle.sendline( "" )
354 self.handle.expect( "\$" )
355 self.handle.sendline( "cd ~" )
356 self.handle.expect( "\$" )
357 self.handle.sendline( "sudo python optical.py" )
358 self.handle.expect( ">" )
shahshreya28bb18e2014-11-17 10:26:23 -0800359 return main.TRUE
360 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800361 main.log.error( self.name + ": EOF exception found" )
362 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800363 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700364
kelvin-onlabedcff052015-01-16 12:53:55 -0800365 def disconnect( self ):
366 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800367 Called at the end of the test to disconnect the handle.
kelvin-onlabedcff052015-01-16 12:53:55 -0800368 """
adminbae64d82013-08-01 10:50:15 -0700369 if self.handle:
shahshreya95dd6f82015-02-05 15:59:16 -0800370 # Close the ssh connection
371 self.handle.sendline( "" )
shahshreyadccfbc62015-02-20 11:40:09 -0800372 #self.handle.expect( "\$" )
373 i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT ],
374 timeout = 2)
375 if i == 0:
376 self.handle.sendline( "exit" )
377 self.handle.expect( "closed" )
378 elif i == 1:
379 self.handle.sendline( "exit" )
380 self.handle.expect( "exit" )
381 self.handle.expect('\$')
382 self.handle.sendline( "exit" )
383 self.handle.expect( "exit" )
384 self.handle.expect( "closed" )
385
kelvin-onlabedcff052015-01-16 12:53:55 -0800386 else:
387 main.log.error( "Connection failed to the host" )
Jon Halld61331b2015-02-17 16:35:47 -0800388 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700389
kelvin-onlabd3b64892015-01-20 13:26:24 -0800390 def getFlowTable( self, protoVersion, sw ):
391 """
392 TODO document usage
393 TODO add option to look at cookies. ignoreing them for now
394
395 print "get_flowTable(" + str( protoVersion ) +" " + str( sw ) +")"
396 NOTE: Use format to force consistent flow table output across
397 versions"""
kelvin-onlabedcff052015-01-16 12:53:55 -0800398 self.handle.sendline( "cd" )
399 self.handle.expect( [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
kelvin-onlabedcff052015-01-16 12:53:55 -0800400 if protoVersion == 1.0:
401 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800402 " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 \
403 $7 $8}' | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800404 self.handle.sendline( command )
405 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
406 self.handle.expect(
407 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700408 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800409 # print "response=", response
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700410 return response
kelvin-onlabedcff052015-01-16 12:53:55 -0800411 elif protoVersion == 1.3:
412 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800413 " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}'\
414 | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800415 self.handle.sendline( command )
416 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
417 self.handle.expect(
418 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700419 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800420 # print "response=", response
Jon Hall94fd0472014-12-08 11:52:42 -0800421 return response
422 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800423 main.log.error(
424 "Unknown protoVersion in get_flowTable(). given: (" +
425 str(
426 type( protoVersion ) ) +
427 ") '" +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800428 str( protoVersion ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800429 "'" )
Jon Hall94fd0472014-12-08 11:52:42 -0800430
kelvin-onlabd3b64892015-01-20 13:26:24 -0800431 def flowComp( self, flow1, flow2 ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800432 if flow1 == flow2:
santhosh19fd8032014-07-29 11:56:17 -0700433 return main.TRUE
434 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800435 main.log.info( "Flow tables do not match, printing tables:" )
436 main.log.info( "Flow Table 1:" )
437 main.log.info( flow1 )
438 main.log.info( "Flow Table 2:" )
439 main.log.info( flow2 )
santhosh19fd8032014-07-29 11:56:17 -0700440 return main.FALSE
441
kelvin-onlabd3b64892015-01-20 13:26:24 -0800442 def setIpTablesOUTPUT( self, dstIp, dstPort, action='add',
443 packetType='tcp', rule='DROP' ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800444 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700445 Description:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800446 add or remove iptables rule to DROP ( default )
447 packets from specific IP and PORT
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700448 Usage:
kelvin-onlabedcff052015-01-16 12:53:55 -0800449 * specify action ( 'add' or 'remove' )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700450 when removing, pass in the same argument as you would add. It will
Jon Hallfbc828e2015-01-06 17:30:19 -0800451 delete that specific rule.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800452 * specify the destination ip to block with dstIp
453 * specify destination port to block to dstPort
kelvin-onlabedcff052015-01-16 12:53:55 -0800454 * optional packet type to block ( default tcp )
455 * optional iptables rule ( default DROP )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700456 WARNING:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800457 * This function uses root privilege iptables command which may result
458 in unwanted network errors. USE WITH CAUTION
kelvin-onlabedcff052015-01-16 12:53:55 -0800459 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700460 import re
461 import time
462
kelvin-onlabedcff052015-01-16 12:53:55 -0800463 # NOTE*********
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700464 # The strict checking methods of this driver function is intentional
465 # to discourage any misuse or error of iptables, which can cause
466 # severe network errors
kelvin-onlabd3b64892015-01-20 13:26:24 -0800467 # *************
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700468
kelvin-onlabd3b64892015-01-20 13:26:24 -0800469 # NOTE: Sleep needed to give some time
470 # for rule to be added and registered
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700471 # to the instance
kelvin-onlabedcff052015-01-16 12:53:55 -0800472 time.sleep( 5 )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700473
kelvin-onlabd3b64892015-01-20 13:26:24 -0800474 actionType = action.lower()
475 if actionType != 'add' and actionType != 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800476 main.log.error(
477 "Invalid action type. 'add' or 'remove' table rule" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700478 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
kelvin-onlabedcff052015-01-16 12:53:55 -0800479 # NOTE: Currently only supports rules DROP, ACCEPT, and LOG
480 main.log.error(
481 "Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700482 return
483 return
484 else:
485
kelvin-onlabedcff052015-01-16 12:53:55 -0800486 # If there is no existing rule in the iptables, we will see an
kelvin-onlabd3b64892015-01-20 13:26:24 -0800487 # 'iptables:'... message. We expect to see this message.
kelvin-onlabedcff052015-01-16 12:53:55 -0800488 # Otherwise, if there IS an existing rule, we will get the prompt
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700489 # back, hence why we expect $ for remove type. We want to remove
490 # an already existing rule
491
kelvin-onlabd3b64892015-01-20 13:26:24 -0800492 if actionType == 'add':
493 # NOTE: "iptables:" expect is a result of
494 # return from the command
495 # iptables -C ...
496 # Any changes by the iptables command return string
497 # will result in failure of the function. ( deemed unlikely
498 # at the time of writing this function )
kelvin-onlabedcff052015-01-16 12:53:55 -0800499 # Check for existing rules on current input
500 self.handle.sendline( "" )
501 self.handle.expect( "\$" )
502 self.handle.sendline(
503 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800504 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800505 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800506 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800507 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800508 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800509 " -j " +
510 str( rule ) )
511 i = self.handle.expect( [ "iptables:", "\$" ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700512 print i
513 print self.handle.before
514 print "after: "
515 print self.handle.after
516
kelvin-onlabd3b64892015-01-20 13:26:24 -0800517 elif actionType == 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800518 # Check for existing rules on current input
519 self.handle.sendline( "" )
520 self.handle.expect( "\$" )
521 self.handle.sendline(
522 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800523 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800524 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800525 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800526 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800527 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800528 " -j " +
529 str( rule ) )
530 self.handle.expect( "\$" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700531 print "before: "
532 print self.handle.before
kelvin-onlabd3b64892015-01-20 13:26:24 -0800533 actualString = self.handle.after
534 expectString = "iptables:"
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700535 print "Actual String:"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800536 print actualString
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700537
kelvin-onlabd3b64892015-01-20 13:26:24 -0800538 if re.search( expectString, actualString ):
539 matchResult = main.TRUE
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700540 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800541 matchResult = main.FALSE
542 # If matchResult is main.TRUE, it means there is no matching rule.
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700543
kelvin-onlabd3b64892015-01-20 13:26:24 -0800544 # If tables does not exist and expected prompt is returned,
545 # go ahead and add iptables rule
546 if matchResult == main.TRUE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800547 # Ensure action type is add
kelvin-onlabd3b64892015-01-20 13:26:24 -0800548 if actionType == 'add':
549 # -A is the 'append' action of iptables
550 actionAdd = '-A'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700551 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800552 self.handle.sendline( "" )
553 self.handle.sendline(
554 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800555 actionAdd +
kelvin-onlabedcff052015-01-16 12:53:55 -0800556 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800557 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800558 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800559 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800560 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800561 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800562 " -j " +
563 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700564
kelvin-onlabd3b64892015-01-20 13:26:24 -0800565 infoString = "Rules added to " + str( self.name )
566 infoString += "iptable rule added to block IP: " + \
567 str( dstIp )
568 infoString += "Port: " + \
569 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700570
kelvin-onlabd3b64892015-01-20 13:26:24 -0800571 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700572
kelvin-onlabedcff052015-01-16 12:53:55 -0800573 self.handle.expect(
574 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700575 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800576 main.log.error(
577 self.name +
578 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800579 except Exception:
580 main.log.exception( self.name +
581 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700582 main.cleanup()
583 main.exit()
584 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800585 main.log.error(
586 "Given rule already exists, but attempted to add it" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800587 # If matchResult is 0, it means there IS a matching rule provided
588 elif matchResult == main.FALSE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800589 # Ensure action type is remove
kelvin-onlabd3b64892015-01-20 13:26:24 -0800590 if actionType == 'remove':
591 # -D is the 'delete' rule of iptables
592 actionRemove = '-D'
Jon Hallfebb1c72015-03-05 13:30:09 -0800593 # noinspection PyBroadException
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700594 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800595 self.handle.sendline( "" )
596 # Delete a specific rule specified into the function
597 self.handle.sendline(
598 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800599 actionRemove +
kelvin-onlabedcff052015-01-16 12:53:55 -0800600 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800601 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800602 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800603 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800604 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800605 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800606 " -j " +
607 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700608
kelvin-onlabd3b64892015-01-20 13:26:24 -0800609 infoString = "Rules removed from " + str( self.name )
610 infoString += " iptables rule removed \
611 from blocking IP: " + \
612 str( dstIp )
613 infoString += " Port: " + \
614 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700615
kelvin-onlabd3b64892015-01-20 13:26:24 -0800616 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700617
kelvin-onlabedcff052015-01-16 12:53:55 -0800618 self.handle.expect(
619 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700620 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800621 main.log.error(
622 self.name +
623 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800624 except Exception:
625 main.log.exception( self.name +
626 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700627 main.cleanup()
628 main.exit()
629 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800630 main.log.error(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800631 "Given rule does not exist,\
632 but attempted to remove it" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700633 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800634 # NOTE: If a bad usage of this function occurs, exit the entire
635 # test
636 main.log.error( "Bad rule given for iptables. Exiting..." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700637 main.cleanup()
638 main.exit()
639
640
adminbae64d82013-08-01 10:50:15 -0700641if __name__ != "__main__":
642 import sys
kelvin-onlabedcff052015-01-16 12:53:55 -0800643 sys.modules[ __name__ ] = RemoteMininetDriver()