blob: 6ee414e5ae417417f4adb532558fa2b63bf5eb2e [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:
kelvin-onlabedcff052015-01-16 12:53:55 -080094 main.log.error( "Error, unexpected output in the ping file" )
Jon Hall2ef1e9e2014-11-18 14:27:05 -050095 main.log.warn( outputs )
shahshreyaf4d4d0c2014-10-10 12:11:10 -070096 return main.TRUE
97
kelvin-onlabedcff052015-01-16 12:53:55 -080098 def pingLong( self, **pingParams ):
99 """
Jon Hallefbd9792015-03-05 16:11:36 -0800100 Starts a continuous ping on the mininet host outputting
kelvin-onlabd3b64892015-01-20 13:26:24 -0800101 to a file in the /tmp dir.
kelvin-onlabedcff052015-01-16 12:53:55 -0800102 """
103 self.handle.sendline( "" )
104 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800105 args = utilities.parse_args(
kelvin-onlabedcff052015-01-16 12:53:55 -0800106 [ "SRC", "TARGET", "PINGTIME" ], **pingParams )
107 precmd = "sudo rm /tmp/ping." + args[ "SRC" ]
108 self.execute( cmd=precmd, prompt="(.*)", timeout=10 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800109 command = "sudo mininet/util/m " + args[ "SRC" ] + " ping " +\
Jon Hallefbd9792015-03-05 16:11:36 -0800110 args[ "TARGET" ] + " -i .2 -w " +\
111 str( args[ 'PINGTIME' ] ) + " -D > /tmp/ping." +\
112 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 """
Jon Hallefbd9792015-03-05 16:11:36 -0800184 This function is only for Packet 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 """
Jon Hallefbd9792015-03-05 16:11:36 -0800283 Runs tcpdump on an interface and saves the file
admin2a9548d2014-06-17 14:08:07 -0700284 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 )
Jon Hall61282e32015-03-19 11:34:11 -0700302 main.log.info( 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 ):
Jon Hallefbd9792015-03-05 16:11:36 -0800331 """
332 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -0700333 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800334 self.handle.sendline( "sudo pkill tcpdump" )
335 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800336 self.handle.expect( "\$" )
admin2a9548d2014-06-17 14:08:07 -0700337 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800338 main.log.error( self.name + ": EOF exception found" )
339 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700340 main.cleanup()
341 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800342 except Exception:
343 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700344 main.cleanup()
345 main.exit()
346
shahshreya1f119da2015-04-21 17:16:46 -0700347 def runOpticalMnScript( self,name = 'onos', ctrllerIP = None ):
shahshreya2c57c902015-04-06 20:40:20 -0700348 import time
shahshreya1f119da2015-04-21 17:16:46 -0700349 import types
kelvin-onlabedcff052015-01-16 12:53:55 -0800350 """
shahshreya1f119da2015-04-21 17:16:46 -0700351 Description:
352 This function is only meant for Packet Optical.
353 It runs python script "opticalTest.py" to create the
354 packet layer( mn ) and optical topology
355 Optional:
356 name - Name of onos directory. (ONOS | onos)
357 Required:
358 ctrllerIP = Controller(s) IP address
359 TODO: If no ctrllerIP is provided, a default
shahshreya2c57c902015-04-06 20:40:20 -0700360 $OC1 can be accepted
kelvin-onlabedcff052015-01-16 12:53:55 -0800361 """
shahshreya28bb18e2014-11-17 10:26:23 -0800362 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800363 self.handle.sendline( "" )
364 self.handle.expect( "\$" )
shahshreya1f119da2015-04-21 17:16:46 -0700365 self.handle.sendline( "cd ~/" + name + "/tools/test/topos" )
shahshreya2c57c902015-04-06 20:40:20 -0700366 self.handle.expect( "topos\$" )
367 if ctrllerIP == None:
368 main.log.info( "You need to specify the IP" )
369 return main.FALSE
370 else:
shahshreya1f119da2015-04-21 17:16:46 -0700371 controller = ''
372 if isinstance( ctrllerIP, types.ListType ):
373 for i in xrange( len( ctrllerIP ) ):
374 controller += ctrllerIP[i] + ' '
375 main.log.info( "Mininet topology is being loaded with " +
376 "controllers: " + controller )
377 elif isinstance( ctrllerIP, types.StringType ):
378 controller = ctrllerIP
379 main.log.info( "Mininet topology is being loaded with " +
380 "controller: " + controller )
381 else:
382 main.log.info( "You need to specify a valid IP" )
383 return main.FALSE
384 cmd = "sudo -E python opticalTest.py " + controller
385 main.log.info( self.name + ": cmd = " + cmd )
shahshreya2c57c902015-04-06 20:40:20 -0700386 self.handle.sendline( cmd )
387 self.handle.expect( "Press ENTER to push Topology.json" )
shahshreyad524a942015-04-21 09:55:16 -0700388 time.sleep(30)
shahshreya2c57c902015-04-06 20:40:20 -0700389 self.handle.sendline( "" )
390 self.handle.expect("mininet>")
391 return main.TRUE
392 except pexpect.EOF:
393 main.log.error( self.name + ": EOF exception found" )
394 main.log.error( self.name + ": " + self.handle.before )
395 return main.FALSE
396
397 def attachLincOESession( self ):
398 """
399 Since executing opticalTest.py will give you mininet
400 prompt, you would at some point require to get onto
401 console of LincOE ((linc@onosTestBench)1>) to execute
402 commands like bring a optical port up or down on a ROADM
403 You can attach to console of Linc-OE session by a cmd:
404 sudo ~/linc-oe/rel/linc/bin/linc attach
405 """
406 try:
407 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800408 self.handle.expect( "\$" )
shahshreya2c57c902015-04-06 20:40:20 -0700409 self.handle.sendline( "sudo ~/linc-oe/rel/linc/bin/linc attach" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800410 self.handle.expect( ">" )
shahshreya28bb18e2014-11-17 10:26:23 -0800411 return main.TRUE
412 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800413 main.log.error( self.name + ": EOF exception found" )
414 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800415 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700416
kelvin-onlabedcff052015-01-16 12:53:55 -0800417 def disconnect( self ):
418 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800419 Called at the end of the test to disconnect the handle.
kelvin-onlabedcff052015-01-16 12:53:55 -0800420 """
adminbae64d82013-08-01 10:50:15 -0700421 if self.handle:
shahshreya95dd6f82015-02-05 15:59:16 -0800422 # Close the ssh connection
423 self.handle.sendline( "" )
Jon Hallefbd9792015-03-05 16:11:36 -0800424 # self.handle.expect( "\$" )
shahshreyadccfbc62015-02-20 11:40:09 -0800425 i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT ],
Jon Hallefbd9792015-03-05 16:11:36 -0800426 timeout=2)
shahshreyadccfbc62015-02-20 11:40:09 -0800427 if i == 0:
428 self.handle.sendline( "exit" )
429 self.handle.expect( "closed" )
430 elif i == 1:
431 self.handle.sendline( "exit" )
432 self.handle.expect( "exit" )
433 self.handle.expect('\$')
434 self.handle.sendline( "exit" )
435 self.handle.expect( "exit" )
436 self.handle.expect( "closed" )
437
kelvin-onlabedcff052015-01-16 12:53:55 -0800438 else:
439 main.log.error( "Connection failed to the host" )
Jon Halld61331b2015-02-17 16:35:47 -0800440 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700441
kelvin-onlabd3b64892015-01-20 13:26:24 -0800442 def getFlowTable( self, protoVersion, sw ):
443 """
444 TODO document usage
Jon Hallefbd9792015-03-05 16:11:36 -0800445 TODO add option to look at cookies. ignoring them for now
kelvin-onlabd3b64892015-01-20 13:26:24 -0800446
447 print "get_flowTable(" + str( protoVersion ) +" " + str( sw ) +")"
448 NOTE: Use format to force consistent flow table output across
449 versions"""
kelvin-onlabedcff052015-01-16 12:53:55 -0800450 self.handle.sendline( "cd" )
451 self.handle.expect( [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
kelvin-onlabedcff052015-01-16 12:53:55 -0800452 if protoVersion == 1.0:
453 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800454 " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 \
455 $7 $8}' | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800456 self.handle.sendline( command )
457 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
458 self.handle.expect(
459 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700460 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800461 # print "response=", response
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700462 return response
kelvin-onlabedcff052015-01-16 12:53:55 -0800463 elif protoVersion == 1.3:
464 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800465 " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}'\
466 | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800467 self.handle.sendline( command )
468 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
469 self.handle.expect(
470 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700471 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800472 # print "response=", response
Jon Hall94fd0472014-12-08 11:52:42 -0800473 return response
474 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800475 main.log.error(
476 "Unknown protoVersion in get_flowTable(). given: (" +
477 str(
478 type( protoVersion ) ) +
479 ") '" +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800480 str( protoVersion ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800481 "'" )
Jon Hall94fd0472014-12-08 11:52:42 -0800482
kelvin-onlabd3b64892015-01-20 13:26:24 -0800483 def flowComp( self, flow1, flow2 ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800484 if flow1 == flow2:
santhosh19fd8032014-07-29 11:56:17 -0700485 return main.TRUE
486 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800487 main.log.info( "Flow tables do not match, printing tables:" )
488 main.log.info( "Flow Table 1:" )
489 main.log.info( flow1 )
490 main.log.info( "Flow Table 2:" )
491 main.log.info( flow2 )
santhosh19fd8032014-07-29 11:56:17 -0700492 return main.FALSE
493
kelvin-onlabd3b64892015-01-20 13:26:24 -0800494 def setIpTablesOUTPUT( self, dstIp, dstPort, action='add',
495 packetType='tcp', rule='DROP' ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800496 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700497 Description:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800498 add or remove iptables rule to DROP ( default )
499 packets from specific IP and PORT
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700500 Usage:
kelvin-onlabedcff052015-01-16 12:53:55 -0800501 * specify action ( 'add' or 'remove' )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700502 when removing, pass in the same argument as you would add. It will
Jon Hallfbc828e2015-01-06 17:30:19 -0800503 delete that specific rule.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800504 * specify the destination ip to block with dstIp
505 * specify destination port to block to dstPort
kelvin-onlabedcff052015-01-16 12:53:55 -0800506 * optional packet type to block ( default tcp )
507 * optional iptables rule ( default DROP )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700508 WARNING:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800509 * This function uses root privilege iptables command which may result
510 in unwanted network errors. USE WITH CAUTION
kelvin-onlabedcff052015-01-16 12:53:55 -0800511 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700512 import re
513 import time
514
kelvin-onlabedcff052015-01-16 12:53:55 -0800515 # NOTE*********
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700516 # The strict checking methods of this driver function is intentional
517 # to discourage any misuse or error of iptables, which can cause
518 # severe network errors
kelvin-onlabd3b64892015-01-20 13:26:24 -0800519 # *************
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700520
kelvin-onlabd3b64892015-01-20 13:26:24 -0800521 # NOTE: Sleep needed to give some time
522 # for rule to be added and registered
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700523 # to the instance
kelvin-onlabedcff052015-01-16 12:53:55 -0800524 time.sleep( 5 )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700525
kelvin-onlabd3b64892015-01-20 13:26:24 -0800526 actionType = action.lower()
527 if actionType != 'add' and actionType != 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800528 main.log.error(
529 "Invalid action type. 'add' or 'remove' table rule" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700530 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
kelvin-onlabedcff052015-01-16 12:53:55 -0800531 # NOTE: Currently only supports rules DROP, ACCEPT, and LOG
532 main.log.error(
533 "Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700534 return
535 return
536 else:
537
kelvin-onlabedcff052015-01-16 12:53:55 -0800538 # If there is no existing rule in the iptables, we will see an
kelvin-onlabd3b64892015-01-20 13:26:24 -0800539 # 'iptables:'... message. We expect to see this message.
kelvin-onlabedcff052015-01-16 12:53:55 -0800540 # Otherwise, if there IS an existing rule, we will get the prompt
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700541 # back, hence why we expect $ for remove type. We want to remove
542 # an already existing rule
543
kelvin-onlabd3b64892015-01-20 13:26:24 -0800544 if actionType == 'add':
545 # NOTE: "iptables:" expect is a result of
546 # return from the command
547 # iptables -C ...
548 # Any changes by the iptables command return string
549 # will result in failure of the function. ( deemed unlikely
550 # at the time of writing this function )
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 i = self.handle.expect( [ "iptables:", "\$" ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700564 print i
565 print self.handle.before
566 print "after: "
567 print self.handle.after
568
kelvin-onlabd3b64892015-01-20 13:26:24 -0800569 elif actionType == 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800570 # Check for existing rules on current input
571 self.handle.sendline( "" )
572 self.handle.expect( "\$" )
573 self.handle.sendline(
574 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800575 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800576 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800577 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800578 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800579 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800580 " -j " +
581 str( rule ) )
582 self.handle.expect( "\$" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700583 print "before: "
584 print self.handle.before
kelvin-onlabd3b64892015-01-20 13:26:24 -0800585 actualString = self.handle.after
586 expectString = "iptables:"
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700587 print "Actual String:"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800588 print actualString
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700589
kelvin-onlabd3b64892015-01-20 13:26:24 -0800590 if re.search( expectString, actualString ):
591 matchResult = main.TRUE
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700592 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800593 matchResult = main.FALSE
594 # If matchResult is main.TRUE, it means there is no matching rule.
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700595
kelvin-onlabd3b64892015-01-20 13:26:24 -0800596 # If tables does not exist and expected prompt is returned,
597 # go ahead and add iptables rule
598 if matchResult == main.TRUE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800599 # Ensure action type is add
kelvin-onlabd3b64892015-01-20 13:26:24 -0800600 if actionType == 'add':
601 # -A is the 'append' action of iptables
602 actionAdd = '-A'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700603 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800604 self.handle.sendline( "" )
605 self.handle.sendline(
606 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800607 actionAdd +
kelvin-onlabedcff052015-01-16 12:53:55 -0800608 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800609 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800610 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800611 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800612 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800613 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800614 " -j " +
615 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700616
kelvin-onlabd3b64892015-01-20 13:26:24 -0800617 infoString = "Rules added to " + str( self.name )
Jon Hallefbd9792015-03-05 16:11:36 -0800618 infoString += "iptables rule added to block IP: " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800619 str( dstIp )
620 infoString += "Port: " + \
621 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700622
kelvin-onlabd3b64892015-01-20 13:26:24 -0800623 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700624
kelvin-onlabedcff052015-01-16 12:53:55 -0800625 self.handle.expect(
626 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700627 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800628 main.log.error(
629 self.name +
630 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800631 except Exception:
632 main.log.exception( self.name +
633 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700634 main.cleanup()
635 main.exit()
636 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800637 main.log.error(
638 "Given rule already exists, but attempted to add it" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800639 # If matchResult is 0, it means there IS a matching rule provided
640 elif matchResult == main.FALSE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800641 # Ensure action type is remove
kelvin-onlabd3b64892015-01-20 13:26:24 -0800642 if actionType == 'remove':
643 # -D is the 'delete' rule of iptables
644 actionRemove = '-D'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700645 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800646 self.handle.sendline( "" )
647 # Delete a specific rule specified into the function
648 self.handle.sendline(
649 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800650 actionRemove +
kelvin-onlabedcff052015-01-16 12:53:55 -0800651 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800652 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800653 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800654 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800655 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800656 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800657 " -j " +
658 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700659
kelvin-onlabd3b64892015-01-20 13:26:24 -0800660 infoString = "Rules removed from " + str( self.name )
661 infoString += " iptables rule removed \
662 from blocking IP: " + \
663 str( dstIp )
664 infoString += " Port: " + \
665 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700666
kelvin-onlabd3b64892015-01-20 13:26:24 -0800667 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700668
kelvin-onlabedcff052015-01-16 12:53:55 -0800669 self.handle.expect(
670 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700671 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800672 main.log.error(
673 self.name +
674 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800675 except Exception:
676 main.log.exception( self.name +
677 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700678 main.cleanup()
679 main.exit()
680 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800681 main.log.error(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800682 "Given rule does not exist,\
683 but attempted to remove it" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700684 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800685 # NOTE: If a bad usage of this function occurs, exit the entire
686 # test
687 main.log.error( "Bad rule given for iptables. Exiting..." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700688 main.cleanup()
689 main.exit()
690
691
adminbae64d82013-08-01 10:50:15 -0700692if __name__ != "__main__":
693 import sys
kelvin-onlabedcff052015-01-16 12:53:55 -0800694 sys.modules[ __name__ ] = RemoteMininetDriver()