blob: 71bf4270b5a69a15b9fc33cfc2c2c7889a9d5b58 [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-onlab65782a82015-05-07 14:12:13 -070098 def arping( self, host="", ip="10.128.20.211" ):
99 """
100 Description:
101 Sends arp message from mininet host for hosts discovery
102 Required:
103 host - hosts name
104 Optional:
105 ip - ip address that does not exist in the network so there would
106 be no reply.
107 """
108 cmd = " py " + host + ".cmd(\"arping -c 1 " + ip + "\")"
109 try:
110 main.log.warn( "Sending: " + cmd )
111 self.handle.sendline( cmd )
112 response = self.handle.before
113 self.handle.sendline( "" )
114 self.handle.expect( "mininet>" )
115 return main.TRUE
116
117 except pexpect.EOF:
118 main.log.error( self.name + ": EOF exception found" )
119 main.log.error( self.name + ": " + self.handle.before )
120 main.cleanup()
121 main.exit()
122
kelvin-onlabedcff052015-01-16 12:53:55 -0800123 def pingLong( self, **pingParams ):
124 """
Jon Hallefbd9792015-03-05 16:11:36 -0800125 Starts a continuous ping on the mininet host outputting
kelvin-onlabd3b64892015-01-20 13:26:24 -0800126 to a file in the /tmp dir.
kelvin-onlabedcff052015-01-16 12:53:55 -0800127 """
128 self.handle.sendline( "" )
129 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800130 args = utilities.parse_args(
kelvin-onlabedcff052015-01-16 12:53:55 -0800131 [ "SRC", "TARGET", "PINGTIME" ], **pingParams )
132 precmd = "sudo rm /tmp/ping." + args[ "SRC" ]
133 self.execute( cmd=precmd, prompt="(.*)", timeout=10 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800134 command = "sudo mininet/util/m " + args[ "SRC" ] + " ping " +\
Jon Hallefbd9792015-03-05 16:11:36 -0800135 args[ "TARGET" ] + " -i .2 -w " +\
136 str( args[ 'PINGTIME' ] ) + " -D > /tmp/ping." +\
137 args[ "SRC" ] + " &"
Jon Hallfbc828e2015-01-06 17:30:19 -0800138 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800139 self.execute( cmd=command, prompt="(.*)", timeout=10 )
140 self.handle.sendline( "" )
141 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700142 return main.TRUE
143
kelvin-onlabedcff052015-01-16 12:53:55 -0800144 def pingstatus( self, **pingParams ):
145 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800146 Tails the respective ping output file and check that
147 there is a moving "64 bytes"
kelvin-onlabedcff052015-01-16 12:53:55 -0800148 """
149 self.handle.sendline( "" )
150 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800151 args = utilities.parse_args( [ "SRC" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800152 self.handle.sendline( "tail /tmp/ping." + args[ "SRC" ] )
153 self.handle.expect( "tail" )
154 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700155 result = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800156 self.handle.sendline( "" )
157 self.handle.expect( "\$" )
158 if re.search( 'Unreachable', result ):
159 main.log.info( "Unreachable found in ping logs..." )
adminbae64d82013-08-01 10:50:15 -0700160 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800161 elif re.search( '64\sbytes', result ):
162 main.log.info( "Pings look good" )
adminbae64d82013-08-01 10:50:15 -0700163 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800164 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800165 main.log.info( "No, or faulty ping data..." )
adminbae64d82013-08-01 10:50:15 -0700166 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800167
kelvin-onlabedcff052015-01-16 12:53:55 -0800168 def pingKill( self, testONUser, testONIP ):
169 """
adminaeedddd2013-08-02 15:14:15 -0700170 Kills all continuous ping processes.
171 Then copies all the ping files to the TestStation.
kelvin-onlabedcff052015-01-16 12:53:55 -0800172 """
173 self.handle.sendline( "" )
174 self.handle.expect( "\$" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800175 command = "sudo kill -SIGINT `pgrep ping`"
176 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800177 self.execute( cmd=command, prompt="(.*)", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800178
adminbae64d82013-08-01 10:50:15 -0700179 main.log.info( "Transferring ping files to TestStation" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800180 command = "scp /tmp/ping.* " + \
181 str( testONUser ) + "@" + str( testONIP ) + ":/tmp/"
182 self.execute( cmd=command, prompt="100%", timeout=20 )
183 # Make sure the output is cleared
184 self.handle.sendline( "" )
185 self.handle.expect( "\$" )
186 self.handle.sendline( "" )
187 self.handle.expect( "\$" )
188 self.handle.sendline( "" )
189 i = self.handle.expect( [ "password", "\$" ] )
Jon Hall368769f2014-11-19 15:43:35 -0800190 if i == 0:
kelvin-onlabedcff052015-01-16 12:53:55 -0800191 main.log.error( "Error, sudo asking for password" )
192 main.log.error( self.handle.before )
Jon Hall368769f2014-11-19 15:43:35 -0800193 return main.FALSE
194 else:
195 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800196
kelvin-onlabedcff052015-01-16 12:53:55 -0800197 def pingLongKill( self ):
198 self.handle.sendline( "" )
199 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700200 command = "sudo kill -SIGING `pgrep ping`"
kelvin-onlabedcff052015-01-16 12:53:55 -0800201 main.log.info( command )
202 self.execute( cmd=command, prompt="(.*)", timeout=10 )
203 self.handle.sendline( "" )
204 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700205 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800206
kelvin-onlabedcff052015-01-16 12:53:55 -0800207 def pingHostOptical( self, **pingParams ):
208 """
Jon Hallefbd9792015-03-05 16:11:36 -0800209 This function is only for Packet Optical related ping
kelvin-onlabedcff052015-01-16 12:53:55 -0800210 Use the next pingHost() function for all normal scenarios )
shahshreya28bb18e2014-11-17 10:26:23 -0800211 Ping from one mininet host to another
212 Currently the only supported Params: SRC and TARGET
kelvin-onlabedcff052015-01-16 12:53:55 -0800213 """
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800214 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800215 command = args[ "SRC" ] + " ping " + \
216 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
shahshreya28bb18e2014-11-17 10:26:23 -0800217 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800218 main.log.warn( "Sending: " + command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800219 self.handle.sendline( command )
220 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800221 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800222 main.log.error(
223 self.name +
224 ": timeout when waiting for response from mininet" )
225 main.log.error( "response: " + str( self.handle.before ) )
226 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800227 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800228 main.log.error(
229 self.name +
230 ": timeout when waiting for response from mininet" )
231 main.log.error( "response: " + str( self.handle.before ) )
shahshreya28bb18e2014-11-17 10:26:23 -0800232 response = self.handle.before
233 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800234 main.log.error( self.name + ": EOF exception found" )
235 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800236 main.cleanup()
237 main.exit()
kelvin-onlabedcff052015-01-16 12:53:55 -0800238 main.log.info( self.name + ": Ping Response: " + response )
kelvin-onlabedcff052015-01-16 12:53:55 -0800239 if re.search( ',\s0\%\spacket\sloss', response ):
240 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800241 main.lastResult = main.TRUE
shahshreya28bb18e2014-11-17 10:26:23 -0800242 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800243 else:
244 main.log.error(
245 self.name +
246 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800247 main.lastResult = main.FALSE
shahshreya28bb18e2014-11-17 10:26:23 -0800248 return main.FALSE
249
kelvin-onlabedcff052015-01-16 12:53:55 -0800250 def pingHost( self, **pingParams ):
251 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800252 Pings between two hosts on remote mininet
kelvin-onlabedcff052015-01-16 12:53:55 -0800253 """
254 self.handle.sendline( "" )
255 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800256 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800257 command = "mininet/util/m " + \
258 args[ "SRC" ] + " ping " + args[ "TARGET" ] + " -c 4 -W 1 -i .2"
259 main.log.info( command )
260 response = self.execute( cmd=command, prompt="rtt", timeout=10 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800261 if utilities.assert_matches(
kelvin-onlabedcff052015-01-16 12:53:55 -0800262 expect=',\s0\%\spacket\sloss',
263 actual=response,
264 onpass="No Packet loss",
265 onfail="Host is not reachable" ):
266 main.log.info( "NO PACKET LOSS, HOST IS REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800267 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700268 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800269 else:
270 main.log.error( "PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800271 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700272 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800273
kelvin-onlabedcff052015-01-16 12:53:55 -0800274 def checknum( self, num ):
275 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800276 Verifies the correct number of switches are running
kelvin-onlabedcff052015-01-16 12:53:55 -0800277 """
278 if self.handle:
279 self.handle.sendline( "" )
280 self.handle.expect( "\$" )
281 self.handle.sendline( 'ifconfig -a | grep "sw.. " | wc -l' )
282 self.handle.expect( "wc" )
283 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700284 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800285 self.handle.sendline(
286 'ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l' )
287 self.handle.expect( "color" )
288 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700289 response2 = self.handle.before
290
kelvin-onlabedcff052015-01-16 12:53:55 -0800291 if re.search( num, response ):
292 if re.search( num, response2 ):
adminbae64d82013-08-01 10:50:15 -0700293 return main.TRUE
294 else:
295 return main.FALSE
296 else:
297 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800298 else:
299 main.log.error( "Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -0700300
kelvin-onlabd3b64892015-01-20 13:26:24 -0800301 def startTcpdump(
kelvin-onlabedcff052015-01-16 12:53:55 -0800302 self,
303 filename,
304 intf="eth0",
305 port="port 6633",
306 user="admin" ):
307 """
Jon Hallefbd9792015-03-05 16:11:36 -0800308 Runs tcpdump on an interface and saves the file
admin2a9548d2014-06-17 14:08:07 -0700309 intf can be specified, or the default eth0 is used
kelvin-onlabedcff052015-01-16 12:53:55 -0800310 """
admin2a9548d2014-06-17 14:08:07 -0700311 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800312 self.handle.sendline( "" )
313 self.handle.sendline(
314 "sudo tcpdump -n -i " +
315 intf +
316 " " +
317 port +
318 " -w " +
319 filename.strip() +
320 " -Z " +
321 user +
322 " &" )
323 self.handle.sendline( "" )
324 self.handle.sendline( "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800325 i = self.handle.expect( [ 'No\ssuch\device', 'listening\son',
326 pexpect.TIMEOUT, "\$" ], timeout=10 )
Jon Hall61282e32015-03-19 11:34:11 -0700327 main.log.info( self.handle.before + self.handle.after )
admin2a9548d2014-06-17 14:08:07 -0700328 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800329 main.log.error( self.name + ": tcpdump - No such device exists.\
330 tcpdump attempted on: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700331 return main.FALSE
332 elif i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800333 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -0700334 return main.TRUE
335 elif i == 2:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800336 main.log.error( self.name + ": tcpdump command timed out!\
337 Check interface name, given interface was: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700338 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800339 elif i == 3:
340 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700341 return main.TRUE
342 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800343 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -0700344 return main.FALSE
345 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800346 main.log.error( self.name + ": EOF exception found" )
347 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700348 main.cleanup()
349 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800350 except Exception:
351 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700352 main.cleanup()
353 main.exit()
354
kelvin-onlabd3b64892015-01-20 13:26:24 -0800355 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -0800356 """
357 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -0700358 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800359 self.handle.sendline( "sudo pkill tcpdump" )
360 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800361 self.handle.expect( "\$" )
admin2a9548d2014-06-17 14:08:07 -0700362 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-onlab65782a82015-05-07 14:12:13 -0700372 def runOpticalMnScript( self,name = 'onos', ctrllerIP = None ):
shahshreya2c57c902015-04-06 20:40:20 -0700373 import time
kelvin-onlab65782a82015-05-07 14:12:13 -0700374 import types
kelvin-onlabedcff052015-01-16 12:53:55 -0800375 """
kelvin-onlab65782a82015-05-07 14:12:13 -0700376 Description:
377 This function is only meant for Packet Optical.
378 It runs python script "opticalTest.py" to create the
379 packet layer( mn ) and optical topology
380 Optional:
381 name - Name of onos directory. (ONOS | onos)
382 Required:
383 ctrllerIP = Controller(s) IP address
384 TODO: If no ctrllerIP is provided, a default
shahshreya2c57c902015-04-06 20:40:20 -0700385 $OC1 can be accepted
kelvin-onlabedcff052015-01-16 12:53:55 -0800386 """
shahshreya28bb18e2014-11-17 10:26:23 -0800387 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800388 self.handle.sendline( "" )
389 self.handle.expect( "\$" )
kelvin-onlab65782a82015-05-07 14:12:13 -0700390 self.handle.sendline( "cd ~/" + name + "/tools/test/topos" )
shahshreya2c57c902015-04-06 20:40:20 -0700391 self.handle.expect( "topos\$" )
392 if ctrllerIP == None:
393 main.log.info( "You need to specify the IP" )
394 return main.FALSE
395 else:
kelvin-onlab65782a82015-05-07 14:12:13 -0700396 controller = ''
397 if isinstance( ctrllerIP, types.ListType ):
398 for i in xrange( len( ctrllerIP ) ):
399 controller += ctrllerIP[i] + ' '
400 main.log.info( "Mininet topology is being loaded with " +
401 "controllers: " + controller )
402 elif isinstance( ctrllerIP, types.StringType ):
403 controller = ctrllerIP
404 main.log.info( "Mininet topology is being loaded with " +
405 "controller: " + controller )
406 else:
407 main.log.info( "You need to specify a valid IP" )
408 return main.FALSE
409 cmd = "sudo -E python opticalTest.py " + controller
410 main.log.info( self.name + ": cmd = " + cmd )
shahshreya2c57c902015-04-06 20:40:20 -0700411 self.handle.sendline( cmd )
412 self.handle.expect( "Press ENTER to push Topology.json" )
kelvin-onlab65782a82015-05-07 14:12:13 -0700413 time.sleep(30)
414 self.handle.sendline( "" )
shahshreya2c57c902015-04-06 20:40:20 -0700415 self.handle.sendline( "" )
416 self.handle.expect("mininet>")
417 return main.TRUE
418 except pexpect.EOF:
419 main.log.error( self.name + ": EOF exception found" )
420 main.log.error( self.name + ": " + self.handle.before )
421 return main.FALSE
422
423 def attachLincOESession( self ):
424 """
425 Since executing opticalTest.py will give you mininet
426 prompt, you would at some point require to get onto
427 console of LincOE ((linc@onosTestBench)1>) to execute
428 commands like bring a optical port up or down on a ROADM
429 You can attach to console of Linc-OE session by a cmd:
430 sudo ~/linc-oe/rel/linc/bin/linc attach
431 """
432 try:
433 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800434 self.handle.expect( "\$" )
shahshreya2c57c902015-04-06 20:40:20 -0700435 self.handle.sendline( "sudo ~/linc-oe/rel/linc/bin/linc attach" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800436 self.handle.expect( ">" )
shahshreya28bb18e2014-11-17 10:26:23 -0800437 return main.TRUE
438 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800439 main.log.error( self.name + ": EOF exception found" )
440 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800441 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700442
kelvin-onlabedcff052015-01-16 12:53:55 -0800443 def disconnect( self ):
444 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800445 Called at the end of the test to disconnect the handle.
kelvin-onlabedcff052015-01-16 12:53:55 -0800446 """
adminbae64d82013-08-01 10:50:15 -0700447 if self.handle:
shahshreya95dd6f82015-02-05 15:59:16 -0800448 # Close the ssh connection
449 self.handle.sendline( "" )
Jon Hallefbd9792015-03-05 16:11:36 -0800450 # self.handle.expect( "\$" )
Jon Hall390696c2015-05-05 17:13:41 -0700451 i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT,
452 pexpect.EOF ], timeout=2 )
shahshreyadccfbc62015-02-20 11:40:09 -0800453 if i == 0:
454 self.handle.sendline( "exit" )
455 self.handle.expect( "closed" )
456 elif i == 1:
457 self.handle.sendline( "exit" )
458 self.handle.expect( "exit" )
459 self.handle.expect('\$')
460 self.handle.sendline( "exit" )
461 self.handle.expect( "exit" )
462 self.handle.expect( "closed" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800463 else:
464 main.log.error( "Connection failed to the host" )
Jon Halld61331b2015-02-17 16:35:47 -0800465 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700466
kelvin-onlabd3b64892015-01-20 13:26:24 -0800467 def getFlowTable( self, protoVersion, sw ):
468 """
469 TODO document usage
Jon Hallefbd9792015-03-05 16:11:36 -0800470 TODO add option to look at cookies. ignoring them for now
kelvin-onlabd3b64892015-01-20 13:26:24 -0800471
472 print "get_flowTable(" + str( protoVersion ) +" " + str( sw ) +")"
473 NOTE: Use format to force consistent flow table output across
474 versions"""
kelvin-onlabedcff052015-01-16 12:53:55 -0800475 self.handle.sendline( "cd" )
476 self.handle.expect( [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
kelvin-onlabedcff052015-01-16 12:53:55 -0800477 if protoVersion == 1.0:
478 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800479 " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 \
480 $7 $8}' | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800481 self.handle.sendline( command )
482 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
483 self.handle.expect(
484 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700485 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800486 # print "response=", response
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700487 return response
kelvin-onlabedcff052015-01-16 12:53:55 -0800488 elif protoVersion == 1.3:
489 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800490 " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}'\
491 | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800492 self.handle.sendline( command )
493 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
494 self.handle.expect(
495 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700496 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800497 # print "response=", response
Jon Hall94fd0472014-12-08 11:52:42 -0800498 return response
499 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800500 main.log.error(
501 "Unknown protoVersion in get_flowTable(). given: (" +
502 str(
503 type( protoVersion ) ) +
504 ") '" +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800505 str( protoVersion ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800506 "'" )
Jon Hall94fd0472014-12-08 11:52:42 -0800507
kelvin-onlabd3b64892015-01-20 13:26:24 -0800508 def flowComp( self, flow1, flow2 ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800509 if flow1 == flow2:
santhosh19fd8032014-07-29 11:56:17 -0700510 return main.TRUE
511 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800512 main.log.info( "Flow tables do not match, printing tables:" )
513 main.log.info( "Flow Table 1:" )
514 main.log.info( flow1 )
515 main.log.info( "Flow Table 2:" )
516 main.log.info( flow2 )
santhosh19fd8032014-07-29 11:56:17 -0700517 return main.FALSE
518
kelvin-onlabd3b64892015-01-20 13:26:24 -0800519 def setIpTablesOUTPUT( self, dstIp, dstPort, action='add',
520 packetType='tcp', rule='DROP' ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800521 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700522 Description:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800523 add or remove iptables rule to DROP ( default )
524 packets from specific IP and PORT
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700525 Usage:
kelvin-onlabedcff052015-01-16 12:53:55 -0800526 * specify action ( 'add' or 'remove' )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700527 when removing, pass in the same argument as you would add. It will
Jon Hallfbc828e2015-01-06 17:30:19 -0800528 delete that specific rule.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800529 * specify the destination ip to block with dstIp
530 * specify destination port to block to dstPort
kelvin-onlabedcff052015-01-16 12:53:55 -0800531 * optional packet type to block ( default tcp )
532 * optional iptables rule ( default DROP )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700533 WARNING:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800534 * This function uses root privilege iptables command which may result
535 in unwanted network errors. USE WITH CAUTION
kelvin-onlabedcff052015-01-16 12:53:55 -0800536 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700537 import re
538 import time
539
kelvin-onlabedcff052015-01-16 12:53:55 -0800540 # NOTE*********
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700541 # The strict checking methods of this driver function is intentional
542 # to discourage any misuse or error of iptables, which can cause
543 # severe network errors
kelvin-onlabd3b64892015-01-20 13:26:24 -0800544 # *************
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700545
kelvin-onlabd3b64892015-01-20 13:26:24 -0800546 # NOTE: Sleep needed to give some time
547 # for rule to be added and registered
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700548 # to the instance
kelvin-onlabedcff052015-01-16 12:53:55 -0800549 time.sleep( 5 )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700550
kelvin-onlabd3b64892015-01-20 13:26:24 -0800551 actionType = action.lower()
552 if actionType != 'add' and actionType != 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800553 main.log.error(
554 "Invalid action type. 'add' or 'remove' table rule" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700555 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
kelvin-onlabedcff052015-01-16 12:53:55 -0800556 # NOTE: Currently only supports rules DROP, ACCEPT, and LOG
557 main.log.error(
558 "Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700559 return
560 return
561 else:
562
kelvin-onlabedcff052015-01-16 12:53:55 -0800563 # If there is no existing rule in the iptables, we will see an
kelvin-onlabd3b64892015-01-20 13:26:24 -0800564 # 'iptables:'... message. We expect to see this message.
kelvin-onlabedcff052015-01-16 12:53:55 -0800565 # Otherwise, if there IS an existing rule, we will get the prompt
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700566 # back, hence why we expect $ for remove type. We want to remove
567 # an already existing rule
568
kelvin-onlabd3b64892015-01-20 13:26:24 -0800569 if actionType == 'add':
570 # NOTE: "iptables:" expect is a result of
571 # return from the command
572 # iptables -C ...
573 # Any changes by the iptables command return string
574 # will result in failure of the function. ( deemed unlikely
575 # at the time of writing this function )
kelvin-onlabedcff052015-01-16 12:53:55 -0800576 # Check for existing rules on current input
577 self.handle.sendline( "" )
578 self.handle.expect( "\$" )
579 self.handle.sendline(
580 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800581 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800582 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800583 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800584 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800585 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800586 " -j " +
587 str( rule ) )
588 i = self.handle.expect( [ "iptables:", "\$" ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700589 print i
590 print self.handle.before
591 print "after: "
592 print self.handle.after
593
kelvin-onlabd3b64892015-01-20 13:26:24 -0800594 elif actionType == 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800595 # Check for existing rules on current input
596 self.handle.sendline( "" )
597 self.handle.expect( "\$" )
598 self.handle.sendline(
599 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800600 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800601 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800602 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800603 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800604 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800605 " -j " +
606 str( rule ) )
607 self.handle.expect( "\$" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700608 print "before: "
609 print self.handle.before
kelvin-onlabd3b64892015-01-20 13:26:24 -0800610 actualString = self.handle.after
611 expectString = "iptables:"
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700612 print "Actual String:"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800613 print actualString
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700614
kelvin-onlabd3b64892015-01-20 13:26:24 -0800615 if re.search( expectString, actualString ):
616 matchResult = main.TRUE
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700617 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800618 matchResult = main.FALSE
619 # If matchResult is main.TRUE, it means there is no matching rule.
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700620
kelvin-onlabd3b64892015-01-20 13:26:24 -0800621 # If tables does not exist and expected prompt is returned,
622 # go ahead and add iptables rule
623 if matchResult == main.TRUE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800624 # Ensure action type is add
kelvin-onlabd3b64892015-01-20 13:26:24 -0800625 if actionType == 'add':
626 # -A is the 'append' action of iptables
627 actionAdd = '-A'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700628 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800629 self.handle.sendline( "" )
630 self.handle.sendline(
631 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800632 actionAdd +
kelvin-onlabedcff052015-01-16 12:53:55 -0800633 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800634 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800635 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800636 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800637 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800638 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800639 " -j " +
640 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700641
kelvin-onlabd3b64892015-01-20 13:26:24 -0800642 infoString = "Rules added to " + str( self.name )
Jon Hallefbd9792015-03-05 16:11:36 -0800643 infoString += "iptables rule added to block IP: " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800644 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(
663 "Given rule already exists, but attempted to add it" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800664 # If matchResult is 0, it means there IS a matching rule provided
665 elif matchResult == main.FALSE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800666 # Ensure action type is remove
kelvin-onlabd3b64892015-01-20 13:26:24 -0800667 if actionType == 'remove':
668 # -D is the 'delete' rule of iptables
669 actionRemove = '-D'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700670 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800671 self.handle.sendline( "" )
672 # Delete a specific rule specified into the function
673 self.handle.sendline(
674 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800675 actionRemove +
kelvin-onlabedcff052015-01-16 12:53:55 -0800676 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800677 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800678 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800679 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800680 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800681 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800682 " -j " +
683 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700684
kelvin-onlabd3b64892015-01-20 13:26:24 -0800685 infoString = "Rules removed from " + str( self.name )
686 infoString += " iptables rule removed \
687 from blocking IP: " + \
688 str( dstIp )
689 infoString += " Port: " + \
690 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700691
kelvin-onlabd3b64892015-01-20 13:26:24 -0800692 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700693
kelvin-onlabedcff052015-01-16 12:53:55 -0800694 self.handle.expect(
695 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700696 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800697 main.log.error(
698 self.name +
699 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800700 except Exception:
701 main.log.exception( self.name +
702 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700703 main.cleanup()
704 main.exit()
705 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800706 main.log.error(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800707 "Given rule does not exist,\
708 but attempted to remove it" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700709 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800710 # NOTE: If a bad usage of this function occurs, exit the entire
711 # test
712 main.log.error( "Bad rule given for iptables. Exiting..." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700713 main.cleanup()
714 main.exit()
715
716
adminbae64d82013-08-01 10:50:15 -0700717if __name__ != "__main__":
718 import sys
kelvin-onlabedcff052015-01-16 12:53:55 -0800719 sys.modules[ __name__ ] = RemoteMininetDriver()