blob: c7406518ad8e7939313e2700f081fac150b7745a [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
Jon Hallefbd9792015-03-05 16:11:36 -080042 self.name = None
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
Jon Hallfbc828e2015-01-06 17:30:19 -080062 # Copying the readme file to process the
kelvin-onlabedcff052015-01-16 12:53:55 -080063 if self.handle:
adminbae64d82013-08-01 10:50:15 -070064 return main.TRUE
65
kelvin-onlabedcff052015-01-16 12:53:55 -080066 else:
67 main.log.error(
68 "Connection failed to the host " +
kelvin-onlab08679eb2015-01-21 16:11:48 -080069 self.user_name +
kelvin-onlabedcff052015-01-16 12:53:55 -080070 "@" +
kelvin-onlab08679eb2015-01-21 16:11:48 -080071 self.ip_address )
kelvin-onlabedcff052015-01-16 12:53:55 -080072 main.log.error( "Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -070073 return main.FALSE
admin98ad0092014-07-23 16:51:07 -070074
kelvin-onlabedcff052015-01-16 12:53:55 -080075 def checkForLoss( self, pingList ):
76 """
Jon Hall6c794f32014-08-14 13:33:13 -070077 Returns main.FALSE for 0% packet loss and
78 Returns main.ERROR if "found multiple mininet" is found and
79 Returns main.TRUE else
kelvin-onlabedcff052015-01-16 12:53:55 -080080 """
kelvin-onlabedcff052015-01-16 12:53:55 -080081 self.handle.sendline( "" )
82 self.handle.expect( "\$" )
kelvin-onlabedcff052015-01-16 12:53:55 -080083 self.handle.sendline( "" )
84 self.handle.expect( "\$" )
85 self.handle.sendline( "cat " + pingList )
86 self.handle.expect( pingList )
87 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -070088 outputs = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -080089 if re.search( " 0% packet loss", outputs ):
admin98ad0092014-07-23 16:51:07 -070090 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -080091 elif re.search( "found multiple mininet", outputs ):
admin2580a0e2014-07-29 11:24:34 -070092 return main.ERROR
shahshreyaf4d4d0c2014-10-10 12:11:10 -070093 else:
Jon Hall80daded2015-05-27 16:07:00 -070094 # TODO: Parse for failed pings, give some truncated output
kelvin-onlabedcff052015-01-16 12:53:55 -080095 main.log.error( "Error, unexpected output in the ping file" )
Jon Hall80daded2015-05-27 16:07:00 -070096 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 """
Jon Hallefbd9792015-03-05 16:11:36 -0800101 Starts a continuous ping on the mininet host outputting
kelvin-onlabd3b64892015-01-20 13:26:24 -0800102 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 " +\
Jon Hallefbd9792015-03-05 16:11:36 -0800111 args[ "TARGET" ] + " -i .2 -w " +\
112 str( args[ 'PINGTIME' ] ) + " -D > /tmp/ping." +\
113 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 """
Jon Hallefbd9792015-03-05 16:11:36 -0800185 This function is only for Packet 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 """
Jon Hallefbd9792015-03-05 16:11:36 -0800284 Runs tcpdump on an interface and saves the file
admin2a9548d2014-06-17 14:08:07 -0700285 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 )
Jon Hall61282e32015-03-19 11:34:11 -0700303 main.log.info( 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()
Jon Hallfebb1c72015-03-05 13:30:09 -0800326 except Exception:
327 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700328 main.cleanup()
329 main.exit()
330
kelvin-onlabd3b64892015-01-20 13:26:24 -0800331 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -0800332 """
333 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -0700334 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800335 self.handle.sendline( "sudo pkill tcpdump" )
336 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800337 self.handle.expect( "\$" )
admin2a9548d2014-06-17 14:08:07 -0700338 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800339 main.log.error( self.name + ": EOF exception found" )
340 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700341 main.cleanup()
342 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800343 except Exception:
344 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700345 main.cleanup()
346 main.exit()
347
shahshreya2c57c902015-04-06 20:40:20 -0700348 def runOpticalMnScript( self, ctrllerIP = None ):
349 import time
kelvin-onlabedcff052015-01-16 12:53:55 -0800350 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800351 This function is only meant for Packet Optical.
shahshreya2c57c902015-04-06 20:40:20 -0700352 It runs python script "opticalTest.py" to create the
353 packet layer( mn ) and optical topology
354
355 TODO: If no ctrllerIP is provided, a default
356 $OC1 can be accepted
kelvin-onlabedcff052015-01-16 12:53:55 -0800357 """
shahshreya28bb18e2014-11-17 10:26:23 -0800358 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800359 self.handle.sendline( "" )
360 self.handle.expect( "\$" )
shahshreya2c57c902015-04-06 20:40:20 -0700361 self.handle.sendline( "cd ~/onos/tools/test/topos" )
362 self.handle.expect( "topos\$" )
363 if ctrllerIP == None:
364 main.log.info( "You need to specify the IP" )
365 return main.FALSE
366 else:
367 cmd = "sudo -E python opticalTest.py " + ctrllerIP
368 self.handle.sendline( cmd )
369 self.handle.expect( "Press ENTER to push Topology.json" )
370 time.sleep(15)
371 self.handle.sendline( "" )
372 self.handle.expect("mininet>")
373 return main.TRUE
374 except pexpect.EOF:
375 main.log.error( self.name + ": EOF exception found" )
376 main.log.error( self.name + ": " + self.handle.before )
377 return main.FALSE
378
379 def attachLincOESession( self ):
380 """
381 Since executing opticalTest.py will give you mininet
382 prompt, you would at some point require to get onto
383 console of LincOE ((linc@onosTestBench)1>) to execute
384 commands like bring a optical port up or down on a ROADM
385 You can attach to console of Linc-OE session by a cmd:
386 sudo ~/linc-oe/rel/linc/bin/linc attach
387 """
388 try:
389 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800390 self.handle.expect( "\$" )
shahshreya2c57c902015-04-06 20:40:20 -0700391 self.handle.sendline( "sudo ~/linc-oe/rel/linc/bin/linc attach" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800392 self.handle.expect( ">" )
shahshreya28bb18e2014-11-17 10:26:23 -0800393 return main.TRUE
394 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800395 main.log.error( self.name + ": EOF exception found" )
396 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800397 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700398
kelvin-onlabedcff052015-01-16 12:53:55 -0800399 def disconnect( self ):
400 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800401 Called at the end of the test to disconnect the handle.
kelvin-onlabedcff052015-01-16 12:53:55 -0800402 """
adminbae64d82013-08-01 10:50:15 -0700403 if self.handle:
shahshreya95dd6f82015-02-05 15:59:16 -0800404 # Close the ssh connection
405 self.handle.sendline( "" )
Jon Hallefbd9792015-03-05 16:11:36 -0800406 # self.handle.expect( "\$" )
Jon Hall390696c2015-05-05 17:13:41 -0700407 i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT,
408 pexpect.EOF ], timeout=2 )
shahshreyadccfbc62015-02-20 11:40:09 -0800409 if i == 0:
410 self.handle.sendline( "exit" )
411 self.handle.expect( "closed" )
412 elif i == 1:
413 self.handle.sendline( "exit" )
414 self.handle.expect( "exit" )
415 self.handle.expect('\$')
416 self.handle.sendline( "exit" )
417 self.handle.expect( "exit" )
418 self.handle.expect( "closed" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800419 else:
420 main.log.error( "Connection failed to the host" )
Jon Halld61331b2015-02-17 16:35:47 -0800421 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700422
kelvin-onlabd3b64892015-01-20 13:26:24 -0800423 def getFlowTable( self, protoVersion, sw ):
424 """
425 TODO document usage
Jon Hallefbd9792015-03-05 16:11:36 -0800426 TODO add option to look at cookies. ignoring them for now
kelvin-onlabd3b64892015-01-20 13:26:24 -0800427
428 print "get_flowTable(" + str( protoVersion ) +" " + str( sw ) +")"
429 NOTE: Use format to force consistent flow table output across
430 versions"""
kelvin-onlabedcff052015-01-16 12:53:55 -0800431 self.handle.sendline( "cd" )
432 self.handle.expect( [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
kelvin-onlabedcff052015-01-16 12:53:55 -0800433 if protoVersion == 1.0:
434 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800435 " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 \
436 $7 $8}' | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800437 self.handle.sendline( command )
438 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
439 self.handle.expect(
440 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700441 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800442 # print "response=", response
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700443 return response
kelvin-onlabedcff052015-01-16 12:53:55 -0800444 elif protoVersion == 1.3:
445 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800446 " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}'\
447 | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800448 self.handle.sendline( command )
449 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
450 self.handle.expect(
451 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700452 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800453 # print "response=", response
Jon Hall94fd0472014-12-08 11:52:42 -0800454 return response
455 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800456 main.log.error(
457 "Unknown protoVersion in get_flowTable(). given: (" +
458 str(
459 type( protoVersion ) ) +
460 ") '" +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800461 str( protoVersion ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800462 "'" )
Jon Hall94fd0472014-12-08 11:52:42 -0800463
kelvin-onlabd3b64892015-01-20 13:26:24 -0800464 def flowComp( self, flow1, flow2 ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800465 if flow1 == flow2:
santhosh19fd8032014-07-29 11:56:17 -0700466 return main.TRUE
467 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800468 main.log.info( "Flow tables do not match, printing tables:" )
469 main.log.info( "Flow Table 1:" )
470 main.log.info( flow1 )
471 main.log.info( "Flow Table 2:" )
472 main.log.info( flow2 )
santhosh19fd8032014-07-29 11:56:17 -0700473 return main.FALSE
474
kelvin-onlabd3b64892015-01-20 13:26:24 -0800475 def setIpTablesOUTPUT( self, dstIp, dstPort, action='add',
476 packetType='tcp', rule='DROP' ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800477 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700478 Description:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800479 add or remove iptables rule to DROP ( default )
480 packets from specific IP and PORT
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700481 Usage:
kelvin-onlabedcff052015-01-16 12:53:55 -0800482 * specify action ( 'add' or 'remove' )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700483 when removing, pass in the same argument as you would add. It will
Jon Hallfbc828e2015-01-06 17:30:19 -0800484 delete that specific rule.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800485 * specify the destination ip to block with dstIp
486 * specify destination port to block to dstPort
kelvin-onlabedcff052015-01-16 12:53:55 -0800487 * optional packet type to block ( default tcp )
488 * optional iptables rule ( default DROP )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700489 WARNING:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800490 * This function uses root privilege iptables command which may result
491 in unwanted network errors. USE WITH CAUTION
kelvin-onlabedcff052015-01-16 12:53:55 -0800492 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700493 import re
494 import time
495
kelvin-onlabedcff052015-01-16 12:53:55 -0800496 # NOTE*********
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700497 # The strict checking methods of this driver function is intentional
498 # to discourage any misuse or error of iptables, which can cause
499 # severe network errors
kelvin-onlabd3b64892015-01-20 13:26:24 -0800500 # *************
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700501
kelvin-onlabd3b64892015-01-20 13:26:24 -0800502 # NOTE: Sleep needed to give some time
503 # for rule to be added and registered
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700504 # to the instance
kelvin-onlabedcff052015-01-16 12:53:55 -0800505 time.sleep( 5 )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700506
kelvin-onlabd3b64892015-01-20 13:26:24 -0800507 actionType = action.lower()
508 if actionType != 'add' and actionType != 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800509 main.log.error(
510 "Invalid action type. 'add' or 'remove' table rule" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700511 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
kelvin-onlabedcff052015-01-16 12:53:55 -0800512 # NOTE: Currently only supports rules DROP, ACCEPT, and LOG
513 main.log.error(
514 "Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700515 return
516 return
517 else:
518
kelvin-onlabedcff052015-01-16 12:53:55 -0800519 # If there is no existing rule in the iptables, we will see an
kelvin-onlabd3b64892015-01-20 13:26:24 -0800520 # 'iptables:'... message. We expect to see this message.
kelvin-onlabedcff052015-01-16 12:53:55 -0800521 # Otherwise, if there IS an existing rule, we will get the prompt
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700522 # back, hence why we expect $ for remove type. We want to remove
523 # an already existing rule
524
kelvin-onlabd3b64892015-01-20 13:26:24 -0800525 if actionType == 'add':
526 # NOTE: "iptables:" expect is a result of
527 # return from the command
528 # iptables -C ...
529 # Any changes by the iptables command return string
530 # will result in failure of the function. ( deemed unlikely
531 # at the time of writing this function )
kelvin-onlabedcff052015-01-16 12:53:55 -0800532 # Check for existing rules on current input
533 self.handle.sendline( "" )
534 self.handle.expect( "\$" )
535 self.handle.sendline(
536 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800537 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800538 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800539 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800540 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800541 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800542 " -j " +
543 str( rule ) )
544 i = self.handle.expect( [ "iptables:", "\$" ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700545 print i
546 print self.handle.before
547 print "after: "
548 print self.handle.after
549
kelvin-onlabd3b64892015-01-20 13:26:24 -0800550 elif actionType == 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800551 # Check for existing rules on current input
552 self.handle.sendline( "" )
553 self.handle.expect( "\$" )
554 self.handle.sendline(
555 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800556 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800557 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800558 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800559 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800560 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800561 " -j " +
562 str( rule ) )
563 self.handle.expect( "\$" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700564 print "before: "
565 print self.handle.before
kelvin-onlabd3b64892015-01-20 13:26:24 -0800566 actualString = self.handle.after
567 expectString = "iptables:"
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700568 print "Actual String:"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800569 print actualString
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700570
kelvin-onlabd3b64892015-01-20 13:26:24 -0800571 if re.search( expectString, actualString ):
572 matchResult = main.TRUE
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700573 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800574 matchResult = main.FALSE
575 # If matchResult is main.TRUE, it means there is no matching rule.
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700576
kelvin-onlabd3b64892015-01-20 13:26:24 -0800577 # If tables does not exist and expected prompt is returned,
578 # go ahead and add iptables rule
579 if matchResult == main.TRUE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800580 # Ensure action type is add
kelvin-onlabd3b64892015-01-20 13:26:24 -0800581 if actionType == 'add':
582 # -A is the 'append' action of iptables
583 actionAdd = '-A'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700584 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800585 self.handle.sendline( "" )
586 self.handle.sendline(
587 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800588 actionAdd +
kelvin-onlabedcff052015-01-16 12:53:55 -0800589 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800590 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800591 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800592 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800593 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800594 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800595 " -j " +
596 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700597
kelvin-onlabd3b64892015-01-20 13:26:24 -0800598 infoString = "Rules added to " + str( self.name )
Jon Hallefbd9792015-03-05 16:11:36 -0800599 infoString += "iptables rule added to block IP: " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800600 str( dstIp )
601 infoString += "Port: " + \
602 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700603
kelvin-onlabd3b64892015-01-20 13:26:24 -0800604 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700605
kelvin-onlabedcff052015-01-16 12:53:55 -0800606 self.handle.expect(
607 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700608 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800609 main.log.error(
610 self.name +
611 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800612 except Exception:
613 main.log.exception( self.name +
614 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700615 main.cleanup()
616 main.exit()
617 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800618 main.log.error(
619 "Given rule already exists, but attempted to add it" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800620 # If matchResult is 0, it means there IS a matching rule provided
621 elif matchResult == main.FALSE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800622 # Ensure action type is remove
kelvin-onlabd3b64892015-01-20 13:26:24 -0800623 if actionType == 'remove':
624 # -D is the 'delete' rule of iptables
625 actionRemove = '-D'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700626 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800627 self.handle.sendline( "" )
628 # Delete a specific rule specified into the function
629 self.handle.sendline(
630 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800631 actionRemove +
kelvin-onlabedcff052015-01-16 12:53:55 -0800632 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800633 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800634 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800635 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800636 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800637 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800638 " -j " +
639 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700640
kelvin-onlabd3b64892015-01-20 13:26:24 -0800641 infoString = "Rules removed from " + str( self.name )
642 infoString += " iptables rule removed \
643 from blocking IP: " + \
644 str( dstIp )
645 infoString += " Port: " + \
646 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700647
kelvin-onlabd3b64892015-01-20 13:26:24 -0800648 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700649
kelvin-onlabedcff052015-01-16 12:53:55 -0800650 self.handle.expect(
651 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700652 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800653 main.log.error(
654 self.name +
655 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800656 except Exception:
657 main.log.exception( self.name +
658 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700659 main.cleanup()
660 main.exit()
661 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800662 main.log.error(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800663 "Given rule does not exist,\
664 but attempted to remove it" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700665 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800666 # NOTE: If a bad usage of this function occurs, exit the entire
667 # test
668 main.log.error( "Bad rule given for iptables. Exiting..." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700669 main.cleanup()
670 main.exit()
671
672
adminbae64d82013-08-01 10:50:15 -0700673if __name__ != "__main__":
674 import sys
kelvin-onlabedcff052015-01-16 12:53:55 -0800675 sys.modules[ __name__ ] = RemoteMininetDriver()