blob: f11c172874e8fd55c7ec03645f07d7c69f178296 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
kelvin-onlabedcff052015-01-16 12:53:55 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
kelvin-onlabedcff052015-01-16 12:53:55 -08005author:: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
kelvin-onlabedcff052015-01-16 12:53:55 -080011 ( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
Jon Hallfbc828e2015-01-06 17:30:19 -080019 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
21
22MininetCliDriver is the basic driver which will handle the Mininet functions
kelvin-onlabedcff052015-01-16 12:53:55 -080023"""
adminbae64d82013-08-01 10:50:15 -070024import pexpect
adminbae64d82013-08-01 10:50:15 -070025import re
26import sys
kelvin-onlaba4074292015-07-09 15:19:49 -070027import os
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' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070054
55 try:
56 if os.getenv( str( self.ip_address ) ) != None:
57 self.ip_address = os.getenv( str( self.ip_address ) )
58 else:
59 main.log.info( self.name +
60 ": Trying to connect to " +
61 self.ip_address )
62
63 except KeyError:
64 main.log.info( "Invalid host name," +
65 " connecting to local host instead" )
66 self.ip_address = 'localhost'
67 except Exception as inst:
68 main.log.error( "Uncaught exception: " + str( inst ) )
69
kelvin-onlabedcff052015-01-16 12:53:55 -080070 self.handle = super(
71 RemoteMininetDriver,
72 self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080073 user_name=self.user_name,
74 ip_address=self.ip_address,
kelvin-onlabedcff052015-01-16 12:53:55 -080075 port=None,
76 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080077
Jon Hallfbc828e2015-01-06 17:30:19 -080078 # Copying the readme file to process the
kelvin-onlabedcff052015-01-16 12:53:55 -080079 if self.handle:
adminbae64d82013-08-01 10:50:15 -070080 return main.TRUE
81
kelvin-onlabedcff052015-01-16 12:53:55 -080082 else:
83 main.log.error(
84 "Connection failed to the host " +
kelvin-onlab08679eb2015-01-21 16:11:48 -080085 self.user_name +
kelvin-onlabedcff052015-01-16 12:53:55 -080086 "@" +
kelvin-onlab08679eb2015-01-21 16:11:48 -080087 self.ip_address )
kelvin-onlabedcff052015-01-16 12:53:55 -080088 main.log.error( "Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -070089 return main.FALSE
admin98ad0092014-07-23 16:51:07 -070090
kelvin-onlabedcff052015-01-16 12:53:55 -080091 def checkForLoss( self, pingList ):
92 """
Jon Hall6c794f32014-08-14 13:33:13 -070093 Returns main.FALSE for 0% packet loss and
94 Returns main.ERROR if "found multiple mininet" is found and
95 Returns main.TRUE else
kelvin-onlabedcff052015-01-16 12:53:55 -080096 """
kelvin-onlabedcff052015-01-16 12:53:55 -080097 self.handle.sendline( "" )
98 self.handle.expect( "\$" )
kelvin-onlabedcff052015-01-16 12:53:55 -080099 self.handle.sendline( "" )
100 self.handle.expect( "\$" )
101 self.handle.sendline( "cat " + pingList )
102 self.handle.expect( pingList )
103 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700104 outputs = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800105 if re.search( " 0% packet loss", outputs ):
admin98ad0092014-07-23 16:51:07 -0700106 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800107 elif re.search( "found multiple mininet", outputs ):
admin2580a0e2014-07-29 11:24:34 -0700108 return main.ERROR
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700109 else:
Jon Hall80daded2015-05-27 16:07:00 -0700110 # TODO: Parse for failed pings, give some truncated output
kelvin-onlabedcff052015-01-16 12:53:55 -0800111 main.log.error( "Error, unexpected output in the ping file" )
Jon Hall2ef1e9e2014-11-18 14:27:05 -0500112 main.log.warn( outputs )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700113 return main.TRUE
114
shahshreya3140b1a2015-04-28 14:22:15 -0700115 def arping( self, host="", ip="10.128.20.211" ):
116 """
117 Description:
118 Sends arp message from mininet host for hosts discovery
119 Required:
120 host - hosts name
121 Optional:
122 ip - ip address that does not exist in the network so there would
123 be no reply.
124 """
125 cmd = " py " + host + ".cmd(\"arping -c 1 " + ip + "\")"
126 try:
127 main.log.warn( "Sending: " + cmd )
128 self.handle.sendline( cmd )
129 response = self.handle.before
130 self.handle.sendline( "" )
131 self.handle.expect( "mininet>" )
132 return main.TRUE
133
134 except pexpect.EOF:
135 main.log.error( self.name + ": EOF exception found" )
136 main.log.error( self.name + ": " + self.handle.before )
137 main.cleanup()
138 main.exit()
139
kelvin-onlabedcff052015-01-16 12:53:55 -0800140 def pingLong( self, **pingParams ):
141 """
Jon Hallefbd9792015-03-05 16:11:36 -0800142 Starts a continuous ping on the mininet host outputting
kelvin-onlabd3b64892015-01-20 13:26:24 -0800143 to a file in the /tmp dir.
kelvin-onlabedcff052015-01-16 12:53:55 -0800144 """
145 self.handle.sendline( "" )
146 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800147 args = utilities.parse_args(
kelvin-onlabedcff052015-01-16 12:53:55 -0800148 [ "SRC", "TARGET", "PINGTIME" ], **pingParams )
149 precmd = "sudo rm /tmp/ping." + args[ "SRC" ]
150 self.execute( cmd=precmd, prompt="(.*)", timeout=10 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800151 command = "sudo mininet/util/m " + args[ "SRC" ] + " ping " +\
Jon Hallefbd9792015-03-05 16:11:36 -0800152 args[ "TARGET" ] + " -i .2 -w " +\
153 str( args[ 'PINGTIME' ] ) + " -D > /tmp/ping." +\
154 args[ "SRC" ] + " &"
Jon Hallfbc828e2015-01-06 17:30:19 -0800155 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800156 self.execute( cmd=command, prompt="(.*)", timeout=10 )
157 self.handle.sendline( "" )
158 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700159 return main.TRUE
160
kelvin-onlabedcff052015-01-16 12:53:55 -0800161 def pingstatus( self, **pingParams ):
162 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800163 Tails the respective ping output file and check that
164 there is a moving "64 bytes"
kelvin-onlabedcff052015-01-16 12:53:55 -0800165 """
166 self.handle.sendline( "" )
167 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800168 args = utilities.parse_args( [ "SRC" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800169 self.handle.sendline( "tail /tmp/ping." + args[ "SRC" ] )
170 self.handle.expect( "tail" )
171 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700172 result = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800173 self.handle.sendline( "" )
174 self.handle.expect( "\$" )
175 if re.search( 'Unreachable', result ):
176 main.log.info( "Unreachable found in ping logs..." )
adminbae64d82013-08-01 10:50:15 -0700177 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800178 elif re.search( '64\sbytes', result ):
179 main.log.info( "Pings look good" )
adminbae64d82013-08-01 10:50:15 -0700180 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800181 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800182 main.log.info( "No, or faulty ping data..." )
adminbae64d82013-08-01 10:50:15 -0700183 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800184
kelvin-onlabedcff052015-01-16 12:53:55 -0800185 def pingKill( self, testONUser, testONIP ):
186 """
adminaeedddd2013-08-02 15:14:15 -0700187 Kills all continuous ping processes.
188 Then copies all the ping files to the TestStation.
kelvin-onlabedcff052015-01-16 12:53:55 -0800189 """
190 self.handle.sendline( "" )
191 self.handle.expect( "\$" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800192 command = "sudo kill -SIGINT `pgrep ping`"
193 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800194 self.execute( cmd=command, prompt="(.*)", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800195
adminbae64d82013-08-01 10:50:15 -0700196 main.log.info( "Transferring ping files to TestStation" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800197 command = "scp /tmp/ping.* " + \
198 str( testONUser ) + "@" + str( testONIP ) + ":/tmp/"
199 self.execute( cmd=command, prompt="100%", timeout=20 )
200 # Make sure the output is cleared
201 self.handle.sendline( "" )
202 self.handle.expect( "\$" )
203 self.handle.sendline( "" )
204 self.handle.expect( "\$" )
205 self.handle.sendline( "" )
206 i = self.handle.expect( [ "password", "\$" ] )
Jon Hall368769f2014-11-19 15:43:35 -0800207 if i == 0:
kelvin-onlabedcff052015-01-16 12:53:55 -0800208 main.log.error( "Error, sudo asking for password" )
209 main.log.error( self.handle.before )
Jon Hall368769f2014-11-19 15:43:35 -0800210 return main.FALSE
211 else:
212 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800213
kelvin-onlabedcff052015-01-16 12:53:55 -0800214 def pingLongKill( self ):
215 self.handle.sendline( "" )
216 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700217 command = "sudo kill -SIGING `pgrep ping`"
kelvin-onlabedcff052015-01-16 12:53:55 -0800218 main.log.info( command )
219 self.execute( cmd=command, prompt="(.*)", timeout=10 )
220 self.handle.sendline( "" )
221 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700222 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800223
kelvin-onlabedcff052015-01-16 12:53:55 -0800224 def pingHostOptical( self, **pingParams ):
225 """
Jon Hallefbd9792015-03-05 16:11:36 -0800226 This function is only for Packet Optical related ping
kelvin-onlabedcff052015-01-16 12:53:55 -0800227 Use the next pingHost() function for all normal scenarios )
shahshreya28bb18e2014-11-17 10:26:23 -0800228 Ping from one mininet host to another
229 Currently the only supported Params: SRC and TARGET
kelvin-onlabedcff052015-01-16 12:53:55 -0800230 """
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800231 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800232 command = args[ "SRC" ] + " ping " + \
233 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
shahshreya28bb18e2014-11-17 10:26:23 -0800234 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800235 main.log.warn( "Sending: " + command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800236 self.handle.sendline( command )
237 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800238 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800239 main.log.error(
240 self.name +
241 ": timeout when waiting for response from mininet" )
242 main.log.error( "response: " + str( self.handle.before ) )
243 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800244 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800245 main.log.error(
246 self.name +
247 ": timeout when waiting for response from mininet" )
248 main.log.error( "response: " + str( self.handle.before ) )
shahshreya28bb18e2014-11-17 10:26:23 -0800249 response = self.handle.before
250 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800251 main.log.error( self.name + ": EOF exception found" )
252 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800253 main.cleanup()
254 main.exit()
kelvin-onlabedcff052015-01-16 12:53:55 -0800255 main.log.info( self.name + ": Ping Response: " + response )
kelvin-onlabedcff052015-01-16 12:53:55 -0800256 if re.search( ',\s0\%\spacket\sloss', response ):
257 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800258 main.lastResult = main.TRUE
shahshreya28bb18e2014-11-17 10:26:23 -0800259 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800260 else:
261 main.log.error(
262 self.name +
263 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800264 main.lastResult = main.FALSE
shahshreya28bb18e2014-11-17 10:26:23 -0800265 return main.FALSE
266
kelvin-onlabedcff052015-01-16 12:53:55 -0800267 def pingHost( self, **pingParams ):
268 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800269 Pings between two hosts on remote mininet
kelvin-onlabedcff052015-01-16 12:53:55 -0800270 """
271 self.handle.sendline( "" )
272 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800273 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800274 command = "mininet/util/m " + \
275 args[ "SRC" ] + " ping " + args[ "TARGET" ] + " -c 4 -W 1 -i .2"
276 main.log.info( command )
277 response = self.execute( cmd=command, prompt="rtt", timeout=10 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800278 if utilities.assert_matches(
kelvin-onlabedcff052015-01-16 12:53:55 -0800279 expect=',\s0\%\spacket\sloss',
280 actual=response,
281 onpass="No Packet loss",
282 onfail="Host is not reachable" ):
283 main.log.info( "NO PACKET LOSS, HOST IS REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800284 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700285 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800286 else:
287 main.log.error( "PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800288 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700289 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800290
kelvin-onlabedcff052015-01-16 12:53:55 -0800291 def checknum( self, num ):
292 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800293 Verifies the correct number of switches are running
kelvin-onlabedcff052015-01-16 12:53:55 -0800294 """
295 if self.handle:
296 self.handle.sendline( "" )
297 self.handle.expect( "\$" )
298 self.handle.sendline( 'ifconfig -a | grep "sw.. " | wc -l' )
299 self.handle.expect( "wc" )
300 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700301 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800302 self.handle.sendline(
303 'ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l' )
304 self.handle.expect( "color" )
305 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700306 response2 = self.handle.before
307
kelvin-onlabedcff052015-01-16 12:53:55 -0800308 if re.search( num, response ):
309 if re.search( num, response2 ):
adminbae64d82013-08-01 10:50:15 -0700310 return main.TRUE
311 else:
312 return main.FALSE
313 else:
314 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800315 else:
316 main.log.error( "Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -0700317
kelvin-onlabd3b64892015-01-20 13:26:24 -0800318 def startTcpdump(
kelvin-onlabedcff052015-01-16 12:53:55 -0800319 self,
320 filename,
321 intf="eth0",
322 port="port 6633",
323 user="admin" ):
324 """
Jon Hallefbd9792015-03-05 16:11:36 -0800325 Runs tcpdump on an interface and saves the file
admin2a9548d2014-06-17 14:08:07 -0700326 intf can be specified, or the default eth0 is used
kelvin-onlabedcff052015-01-16 12:53:55 -0800327 """
admin2a9548d2014-06-17 14:08:07 -0700328 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800329 self.handle.sendline( "" )
330 self.handle.sendline(
331 "sudo tcpdump -n -i " +
332 intf +
333 " " +
334 port +
335 " -w " +
336 filename.strip() +
337 " -Z " +
338 user +
339 " &" )
340 self.handle.sendline( "" )
341 self.handle.sendline( "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800342 i = self.handle.expect( [ 'No\ssuch\device', 'listening\son',
343 pexpect.TIMEOUT, "\$" ], timeout=10 )
Jon Hall61282e32015-03-19 11:34:11 -0700344 main.log.info( self.handle.before + self.handle.after )
admin2a9548d2014-06-17 14:08:07 -0700345 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800346 main.log.error( self.name + ": tcpdump - No such device exists.\
347 tcpdump attempted on: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700348 return main.FALSE
349 elif i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800350 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -0700351 return main.TRUE
352 elif i == 2:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800353 main.log.error( self.name + ": tcpdump command timed out!\
354 Check interface name, given interface was: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700355 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800356 elif i == 3:
357 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700358 return main.TRUE
359 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800360 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -0700361 return main.FALSE
362 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800363 main.log.error( self.name + ": EOF exception found" )
364 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700365 main.cleanup()
366 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800367 except Exception:
368 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700369 main.cleanup()
370 main.exit()
371
kelvin-onlabd3b64892015-01-20 13:26:24 -0800372 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -0800373 """
374 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -0700375 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800376 self.handle.sendline( "sudo pkill tcpdump" )
377 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800378 self.handle.expect( "\$" )
admin2a9548d2014-06-17 14:08:07 -0700379 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800380 main.log.error( self.name + ": EOF exception found" )
381 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700382 main.cleanup()
383 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800384 except Exception:
385 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700386 main.cleanup()
387 main.exit()
388
shahshreya1f119da2015-04-21 17:16:46 -0700389 def runOpticalMnScript( self,name = 'onos', ctrllerIP = None ):
shahshreya2c57c902015-04-06 20:40:20 -0700390 import time
shahshreya1f119da2015-04-21 17:16:46 -0700391 import types
kelvin-onlabedcff052015-01-16 12:53:55 -0800392 """
shahshreya1f119da2015-04-21 17:16:46 -0700393 Description:
394 This function is only meant for Packet Optical.
395 It runs python script "opticalTest.py" to create the
396 packet layer( mn ) and optical topology
397 Optional:
398 name - Name of onos directory. (ONOS | onos)
399 Required:
400 ctrllerIP = Controller(s) IP address
401 TODO: If no ctrllerIP is provided, a default
shahshreya2c57c902015-04-06 20:40:20 -0700402 $OC1 can be accepted
kelvin-onlabedcff052015-01-16 12:53:55 -0800403 """
shahshreya28bb18e2014-11-17 10:26:23 -0800404 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800405 self.handle.sendline( "" )
406 self.handle.expect( "\$" )
shahshreya1f119da2015-04-21 17:16:46 -0700407 self.handle.sendline( "cd ~/" + name + "/tools/test/topos" )
shahshreya2c57c902015-04-06 20:40:20 -0700408 self.handle.expect( "topos\$" )
409 if ctrllerIP == None:
410 main.log.info( "You need to specify the IP" )
411 return main.FALSE
412 else:
shahshreya1f119da2015-04-21 17:16:46 -0700413 controller = ''
414 if isinstance( ctrllerIP, types.ListType ):
415 for i in xrange( len( ctrllerIP ) ):
416 controller += ctrllerIP[i] + ' '
417 main.log.info( "Mininet topology is being loaded with " +
418 "controllers: " + controller )
419 elif isinstance( ctrllerIP, types.StringType ):
420 controller = ctrllerIP
421 main.log.info( "Mininet topology is being loaded with " +
422 "controller: " + controller )
423 else:
424 main.log.info( "You need to specify a valid IP" )
425 return main.FALSE
426 cmd = "sudo -E python opticalTest.py " + controller
427 main.log.info( self.name + ": cmd = " + cmd )
shahshreya2c57c902015-04-06 20:40:20 -0700428 self.handle.sendline( cmd )
shahshreyad524a942015-04-21 09:55:16 -0700429 time.sleep(30)
shahshreya2c57c902015-04-06 20:40:20 -0700430 self.handle.sendline( "" )
shahshreya3140b1a2015-04-28 14:22:15 -0700431 self.handle.sendline( "" )
shahshreya2c57c902015-04-06 20:40:20 -0700432 self.handle.expect("mininet>")
433 return main.TRUE
434 except pexpect.EOF:
435 main.log.error( self.name + ": EOF exception found" )
436 main.log.error( self.name + ": " + self.handle.before )
437 return main.FALSE
438
439 def attachLincOESession( self ):
440 """
441 Since executing opticalTest.py will give you mininet
442 prompt, you would at some point require to get onto
443 console of LincOE ((linc@onosTestBench)1>) to execute
444 commands like bring a optical port up or down on a ROADM
445 You can attach to console of Linc-OE session by a cmd:
446 sudo ~/linc-oe/rel/linc/bin/linc attach
447 """
448 try:
449 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800450 self.handle.expect( "\$" )
shahshreya2c57c902015-04-06 20:40:20 -0700451 self.handle.sendline( "sudo ~/linc-oe/rel/linc/bin/linc attach" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800452 self.handle.expect( ">" )
shahshreya28bb18e2014-11-17 10:26:23 -0800453 return main.TRUE
454 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800455 main.log.error( self.name + ": EOF exception found" )
456 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800457 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700458
kelvin-onlabedcff052015-01-16 12:53:55 -0800459 def disconnect( self ):
460 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800461 Called at the end of the test to disconnect the handle.
kelvin-onlabedcff052015-01-16 12:53:55 -0800462 """
adminbae64d82013-08-01 10:50:15 -0700463 if self.handle:
shahshreya95dd6f82015-02-05 15:59:16 -0800464 # Close the ssh connection
465 self.handle.sendline( "" )
Jon Hallefbd9792015-03-05 16:11:36 -0800466 # self.handle.expect( "\$" )
Jon Hall390696c2015-05-05 17:13:41 -0700467 i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT,
468 pexpect.EOF ], timeout=2 )
shahshreyadccfbc62015-02-20 11:40:09 -0800469 if i == 0:
470 self.handle.sendline( "exit" )
471 self.handle.expect( "closed" )
472 elif i == 1:
473 self.handle.sendline( "exit" )
474 self.handle.expect( "exit" )
475 self.handle.expect('\$')
476 self.handle.sendline( "exit" )
477 self.handle.expect( "exit" )
478 self.handle.expect( "closed" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800479 else:
480 main.log.error( "Connection failed to the host" )
Jon Halld61331b2015-02-17 16:35:47 -0800481 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700482
kelvin-onlabd3b64892015-01-20 13:26:24 -0800483 def getFlowTable( self, protoVersion, sw ):
484 """
485 TODO document usage
Jon Hallefbd9792015-03-05 16:11:36 -0800486 TODO add option to look at cookies. ignoring them for now
kelvin-onlabd3b64892015-01-20 13:26:24 -0800487
488 print "get_flowTable(" + str( protoVersion ) +" " + str( sw ) +")"
489 NOTE: Use format to force consistent flow table output across
Jon Hallde5ef2a2015-07-22 14:45:24 -0700490 versions
491 """
492 try:
493 self.handle.sendline( "cd" )
494 self.handle.expect( "\$" )
495 if protoVersion == 1.0:
496 command = "sudo ovs-ofctl dump-flows " + sw + \
497 " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 \
498 $7 $8}' | cut -d ',' -f 2- | sort -n -k1 -r"
499 self.handle.sendline( command )
Jon Hall7d7ef3f2015-07-22 15:39:24 -0700500 self.handle.expect( "sort" )
Jon Hallde5ef2a2015-07-22 14:45:24 -0700501 self.handle.expect( "OFPST_FLOW" )
502 response = self.handle.before
503 # print "response=", response
504 return response
505 elif protoVersion == 1.3:
506 command = "sudo ovs-ofctl dump-flows " + sw + \
507 " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}'\
508 | cut -d ',' -f 2- | sort -n -k1 -r"
509 self.handle.sendline( command )
Jon Hall7d7ef3f2015-07-22 15:39:24 -0700510 self.handle.expect( "sort" )
Jon Hallde5ef2a2015-07-22 14:45:24 -0700511 self.handle.expect( "OFPST_FLOW" )
512 response = self.handle.before
513 # print "response=", response
514 return response
515 else:
516 main.log.error(
517 "Unknown protoVersion in get_flowTable(). given: (" +
518 str( type( protoVersion ) ) +
519 ") '" + str( protoVersion ) + "'" )
520 except pexpect.EOF:
521 main.log.error( self.name + ": EOF exception found" )
522 main.log.error( self.name + ": " + self.handle.before )
523 main.cleanup()
524 main.exit()
525 except pexpect.TIMEOUT:
526 main.log.exception( self.name + ": Timeout exception: " )
527 return None
Jon Hall94fd0472014-12-08 11:52:42 -0800528
kelvin-onlabd3b64892015-01-20 13:26:24 -0800529 def flowComp( self, flow1, flow2 ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800530 if flow1 == flow2:
santhosh19fd8032014-07-29 11:56:17 -0700531 return main.TRUE
532 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800533 main.log.info( "Flow tables do not match, printing tables:" )
534 main.log.info( "Flow Table 1:" )
535 main.log.info( flow1 )
536 main.log.info( "Flow Table 2:" )
537 main.log.info( flow2 )
santhosh19fd8032014-07-29 11:56:17 -0700538 return main.FALSE
539
kelvin-onlabd3b64892015-01-20 13:26:24 -0800540 def setIpTablesOUTPUT( self, dstIp, dstPort, action='add',
541 packetType='tcp', rule='DROP' ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800542 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700543 Description:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800544 add or remove iptables rule to DROP ( default )
545 packets from specific IP and PORT
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700546 Usage:
kelvin-onlabedcff052015-01-16 12:53:55 -0800547 * specify action ( 'add' or 'remove' )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700548 when removing, pass in the same argument as you would add. It will
Jon Hallfbc828e2015-01-06 17:30:19 -0800549 delete that specific rule.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800550 * specify the destination ip to block with dstIp
551 * specify destination port to block to dstPort
kelvin-onlabedcff052015-01-16 12:53:55 -0800552 * optional packet type to block ( default tcp )
553 * optional iptables rule ( default DROP )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700554 WARNING:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800555 * This function uses root privilege iptables command which may result
556 in unwanted network errors. USE WITH CAUTION
kelvin-onlabedcff052015-01-16 12:53:55 -0800557 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700558 import re
559 import time
560
kelvin-onlabedcff052015-01-16 12:53:55 -0800561 # NOTE*********
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700562 # The strict checking methods of this driver function is intentional
563 # to discourage any misuse or error of iptables, which can cause
564 # severe network errors
kelvin-onlabd3b64892015-01-20 13:26:24 -0800565 # *************
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700566
kelvin-onlabd3b64892015-01-20 13:26:24 -0800567 # NOTE: Sleep needed to give some time
568 # for rule to be added and registered
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700569 # to the instance
kelvin-onlabedcff052015-01-16 12:53:55 -0800570 time.sleep( 5 )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700571
kelvin-onlabd3b64892015-01-20 13:26:24 -0800572 actionType = action.lower()
573 if actionType != 'add' and actionType != 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800574 main.log.error(
575 "Invalid action type. 'add' or 'remove' table rule" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700576 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
kelvin-onlabedcff052015-01-16 12:53:55 -0800577 # NOTE: Currently only supports rules DROP, ACCEPT, and LOG
578 main.log.error(
579 "Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700580 return
581 return
582 else:
583
kelvin-onlabedcff052015-01-16 12:53:55 -0800584 # If there is no existing rule in the iptables, we will see an
kelvin-onlabd3b64892015-01-20 13:26:24 -0800585 # 'iptables:'... message. We expect to see this message.
kelvin-onlabedcff052015-01-16 12:53:55 -0800586 # Otherwise, if there IS an existing rule, we will get the prompt
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700587 # back, hence why we expect $ for remove type. We want to remove
588 # an already existing rule
589
kelvin-onlabd3b64892015-01-20 13:26:24 -0800590 if actionType == 'add':
591 # NOTE: "iptables:" expect is a result of
592 # return from the command
593 # iptables -C ...
594 # Any changes by the iptables command return string
595 # will result in failure of the function. ( deemed unlikely
596 # at the time of writing this function )
kelvin-onlabedcff052015-01-16 12:53:55 -0800597 # Check for existing rules on current input
598 self.handle.sendline( "" )
599 self.handle.expect( "\$" )
600 self.handle.sendline(
601 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800602 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800603 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800604 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800605 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800606 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800607 " -j " +
608 str( rule ) )
609 i = self.handle.expect( [ "iptables:", "\$" ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700610 print i
611 print self.handle.before
612 print "after: "
613 print self.handle.after
614
kelvin-onlabd3b64892015-01-20 13:26:24 -0800615 elif actionType == 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800616 # Check for existing rules on current input
617 self.handle.sendline( "" )
618 self.handle.expect( "\$" )
619 self.handle.sendline(
620 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800621 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800622 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800623 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800624 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800625 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800626 " -j " +
627 str( rule ) )
628 self.handle.expect( "\$" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700629 print "before: "
630 print self.handle.before
kelvin-onlabd3b64892015-01-20 13:26:24 -0800631 actualString = self.handle.after
632 expectString = "iptables:"
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700633 print "Actual String:"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800634 print actualString
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700635
kelvin-onlabd3b64892015-01-20 13:26:24 -0800636 if re.search( expectString, actualString ):
637 matchResult = main.TRUE
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700638 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800639 matchResult = main.FALSE
640 # If matchResult is main.TRUE, it means there is no matching rule.
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700641
kelvin-onlabd3b64892015-01-20 13:26:24 -0800642 # If tables does not exist and expected prompt is returned,
643 # go ahead and add iptables rule
644 if matchResult == main.TRUE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800645 # Ensure action type is add
kelvin-onlabd3b64892015-01-20 13:26:24 -0800646 if actionType == 'add':
647 # -A is the 'append' action of iptables
648 actionAdd = '-A'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700649 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800650 self.handle.sendline( "" )
651 self.handle.sendline(
652 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800653 actionAdd +
kelvin-onlabedcff052015-01-16 12:53:55 -0800654 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800655 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800656 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800657 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800658 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800659 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800660 " -j " +
661 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700662
kelvin-onlabd3b64892015-01-20 13:26:24 -0800663 infoString = "Rules added to " + str( self.name )
Jon Hallefbd9792015-03-05 16:11:36 -0800664 infoString += "iptables rule added to block IP: " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800665 str( dstIp )
666 infoString += "Port: " + \
667 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700668
kelvin-onlabd3b64892015-01-20 13:26:24 -0800669 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700670
kelvin-onlabedcff052015-01-16 12:53:55 -0800671 self.handle.expect(
672 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700673 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800674 main.log.error(
675 self.name +
676 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800677 except Exception:
678 main.log.exception( self.name +
679 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700680 main.cleanup()
681 main.exit()
682 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800683 main.log.error(
684 "Given rule already exists, but attempted to add it" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800685 # If matchResult is 0, it means there IS a matching rule provided
686 elif matchResult == main.FALSE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800687 # Ensure action type is remove
kelvin-onlabd3b64892015-01-20 13:26:24 -0800688 if actionType == 'remove':
689 # -D is the 'delete' rule of iptables
690 actionRemove = '-D'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700691 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800692 self.handle.sendline( "" )
693 # Delete a specific rule specified into the function
694 self.handle.sendline(
695 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800696 actionRemove +
kelvin-onlabedcff052015-01-16 12:53:55 -0800697 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800698 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800699 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800700 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800701 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800702 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800703 " -j " +
704 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700705
kelvin-onlabd3b64892015-01-20 13:26:24 -0800706 infoString = "Rules removed from " + str( self.name )
707 infoString += " iptables rule removed \
708 from blocking IP: " + \
709 str( dstIp )
710 infoString += " Port: " + \
711 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700712
kelvin-onlabd3b64892015-01-20 13:26:24 -0800713 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700714
kelvin-onlabedcff052015-01-16 12:53:55 -0800715 self.handle.expect(
716 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700717 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800718 main.log.error(
719 self.name +
720 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800721 except Exception:
722 main.log.exception( self.name +
723 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700724 main.cleanup()
725 main.exit()
726 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800727 main.log.error(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800728 "Given rule does not exist,\
729 but attempted to remove it" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700730 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800731 # NOTE: If a bad usage of this function occurs, exit the entire
732 # test
733 main.log.error( "Bad rule given for iptables. Exiting..." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700734 main.cleanup()
735 main.exit()
736
737
adminbae64d82013-08-01 10:50:15 -0700738if __name__ != "__main__":
739 import sys
kelvin-onlabedcff052015-01-16 12:53:55 -0800740 sys.modules[ __name__ ] = RemoteMininetDriver()