blob: bf1c6c6a3c1983c908322d9d643cc747116389b7 [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
Jeremy Songsterae01bba2016-07-11 15:39:17 -07004Modified 2016 by ON.Lab
adminbae64d82013-08-01 10:50:15 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
10 TestON is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 2 of the License, or
kelvin-onlabedcff052015-01-16 12:53:55 -080013 ( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070014
15 TestON is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
Jon Hallfbc828e2015-01-06 17:30:19 -080021 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
23
24MininetCliDriver is the basic driver which will handle the Mininet functions
kelvin-onlabedcff052015-01-16 12:53:55 -080025"""
adminbae64d82013-08-01 10:50:15 -070026import pexpect
adminbae64d82013-08-01 10:50:15 -070027import re
28import sys
kelvin-onlaba4074292015-07-09 15:19:49 -070029import os
adminbae64d82013-08-01 10:50:15 -070030from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070031
kelvin-onlabedcff052015-01-16 12:53:55 -080032
33class RemoteMininetDriver( Emulator ):
34
35 """
kelvin-onlabd3b64892015-01-20 13:26:24 -080036 RemoteMininetCliDriver is the basic driver which will handle the Mininet
37 functions. The main different between this and the MininetCliDriver is that
38 this one does not build the mininet. It assumes that there is already a
39 mininet running on the target.
kelvin-onlabedcff052015-01-16 12:53:55 -080040 """
41 def __init__( self ):
42 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070043 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080044 self.name = None
kelvin-onlabedcff052015-01-16 12:53:55 -080045 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070046 self.flag = 0
47
kelvin-onlabedcff052015-01-16 12:53:55 -080048 def connect( self, **connectargs ):
kelvin-onlab08679eb2015-01-21 16:11:48 -080049 """,user_name, ip_address, pwd,options ):
kelvin-onlabd3b64892015-01-20 13:26:24 -080050 Here the main is the TestON instance after creating all the log
51 handles."""
adminbae64d82013-08-01 10:50:15 -070052 for key in connectargs:
kelvin-onlabedcff052015-01-16 12:53:55 -080053 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080054
kelvin-onlabedcff052015-01-16 12:53:55 -080055 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070056
57 try:
58 if os.getenv( str( self.ip_address ) ) != None:
59 self.ip_address = os.getenv( str( self.ip_address ) )
60 else:
61 main.log.info( self.name +
62 ": Trying to connect to " +
63 self.ip_address )
64
65 except KeyError:
66 main.log.info( "Invalid host name," +
67 " connecting to local host instead" )
68 self.ip_address = 'localhost'
69 except Exception as inst:
70 main.log.error( "Uncaught exception: " + str( inst ) )
71
kelvin-onlabedcff052015-01-16 12:53:55 -080072 self.handle = super(
73 RemoteMininetDriver,
74 self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080075 user_name=self.user_name,
76 ip_address=self.ip_address,
kelvin-onlabedcff052015-01-16 12:53:55 -080077 port=None,
78 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080079
Jon Hallfbc828e2015-01-06 17:30:19 -080080 # Copying the readme file to process the
kelvin-onlabedcff052015-01-16 12:53:55 -080081 if self.handle:
adminbae64d82013-08-01 10:50:15 -070082 return main.TRUE
83
kelvin-onlabedcff052015-01-16 12:53:55 -080084 else:
85 main.log.error(
86 "Connection failed to the host " +
kelvin-onlab08679eb2015-01-21 16:11:48 -080087 self.user_name +
kelvin-onlabedcff052015-01-16 12:53:55 -080088 "@" +
kelvin-onlab08679eb2015-01-21 16:11:48 -080089 self.ip_address )
kelvin-onlabedcff052015-01-16 12:53:55 -080090 main.log.error( "Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -070091 return main.FALSE
admin98ad0092014-07-23 16:51:07 -070092
kelvin-onlabedcff052015-01-16 12:53:55 -080093 def checkForLoss( self, pingList ):
94 """
Jon Hall6c794f32014-08-14 13:33:13 -070095 Returns main.FALSE for 0% packet loss and
96 Returns main.ERROR if "found multiple mininet" is found and
97 Returns main.TRUE else
kelvin-onlabedcff052015-01-16 12:53:55 -080098 """
kelvin-onlabedcff052015-01-16 12:53:55 -080099 self.handle.sendline( "" )
100 self.handle.expect( "\$" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800101 self.handle.sendline( "" )
102 self.handle.expect( "\$" )
103 self.handle.sendline( "cat " + pingList )
104 self.handle.expect( pingList )
105 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700106 outputs = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800107 if re.search( " 0% packet loss", outputs ):
admin98ad0092014-07-23 16:51:07 -0700108 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800109 elif re.search( "found multiple mininet", outputs ):
admin2580a0e2014-07-29 11:24:34 -0700110 return main.ERROR
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700111 else:
Jon Hall80daded2015-05-27 16:07:00 -0700112 # TODO: Parse for failed pings, give some truncated output
kelvin-onlabedcff052015-01-16 12:53:55 -0800113 main.log.error( "Error, unexpected output in the ping file" )
Jon Hall2ef1e9e2014-11-18 14:27:05 -0500114 main.log.warn( outputs )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700115 return main.TRUE
116
kelvin-onlabedcff052015-01-16 12:53:55 -0800117 def pingLong( self, **pingParams ):
118 """
Jon Hallefbd9792015-03-05 16:11:36 -0800119 Starts a continuous ping on the mininet host outputting
kelvin-onlabd3b64892015-01-20 13:26:24 -0800120 to a file in the /tmp dir.
kelvin-onlabedcff052015-01-16 12:53:55 -0800121 """
122 self.handle.sendline( "" )
123 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800124 args = utilities.parse_args(
kelvin-onlabedcff052015-01-16 12:53:55 -0800125 [ "SRC", "TARGET", "PINGTIME" ], **pingParams )
126 precmd = "sudo rm /tmp/ping." + args[ "SRC" ]
127 self.execute( cmd=precmd, prompt="(.*)", timeout=10 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800128 command = "sudo mininet/util/m " + args[ "SRC" ] + " ping " +\
Jon Hallefbd9792015-03-05 16:11:36 -0800129 args[ "TARGET" ] + " -i .2 -w " +\
130 str( args[ 'PINGTIME' ] ) + " -D > /tmp/ping." +\
131 args[ "SRC" ] + " &"
Jon Hallfbc828e2015-01-06 17:30:19 -0800132 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800133 self.execute( cmd=command, prompt="(.*)", timeout=10 )
134 self.handle.sendline( "" )
135 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700136 return main.TRUE
137
kelvin-onlabedcff052015-01-16 12:53:55 -0800138 def pingstatus( self, **pingParams ):
139 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800140 Tails the respective ping output file and check that
141 there is a moving "64 bytes"
kelvin-onlabedcff052015-01-16 12:53:55 -0800142 """
143 self.handle.sendline( "" )
144 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800145 args = utilities.parse_args( [ "SRC" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800146 self.handle.sendline( "tail /tmp/ping." + args[ "SRC" ] )
147 self.handle.expect( "tail" )
148 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700149 result = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800150 self.handle.sendline( "" )
151 self.handle.expect( "\$" )
152 if re.search( 'Unreachable', result ):
153 main.log.info( "Unreachable found in ping logs..." )
adminbae64d82013-08-01 10:50:15 -0700154 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800155 elif re.search( '64\sbytes', result ):
156 main.log.info( "Pings look good" )
adminbae64d82013-08-01 10:50:15 -0700157 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800158 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800159 main.log.info( "No, or faulty ping data..." )
adminbae64d82013-08-01 10:50:15 -0700160 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800161
kelvin-onlabedcff052015-01-16 12:53:55 -0800162 def pingKill( self, testONUser, testONIP ):
163 """
adminaeedddd2013-08-02 15:14:15 -0700164 Kills all continuous ping processes.
165 Then copies all the ping files to the TestStation.
kelvin-onlabedcff052015-01-16 12:53:55 -0800166 """
167 self.handle.sendline( "" )
168 self.handle.expect( "\$" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800169 command = "sudo kill -SIGINT `pgrep ping`"
170 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800171 self.execute( cmd=command, prompt="(.*)", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800172
adminbae64d82013-08-01 10:50:15 -0700173 main.log.info( "Transferring ping files to TestStation" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800174 command = "scp /tmp/ping.* " + \
175 str( testONUser ) + "@" + str( testONIP ) + ":/tmp/"
176 self.execute( cmd=command, prompt="100%", timeout=20 )
177 # Make sure the output is cleared
178 self.handle.sendline( "" )
179 self.handle.expect( "\$" )
180 self.handle.sendline( "" )
181 self.handle.expect( "\$" )
182 self.handle.sendline( "" )
183 i = self.handle.expect( [ "password", "\$" ] )
Jon Hall368769f2014-11-19 15:43:35 -0800184 if i == 0:
kelvin-onlabedcff052015-01-16 12:53:55 -0800185 main.log.error( "Error, sudo asking for password" )
186 main.log.error( self.handle.before )
Jon Hall368769f2014-11-19 15:43:35 -0800187 return main.FALSE
188 else:
189 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800190
kelvin-onlabedcff052015-01-16 12:53:55 -0800191 def pingLongKill( self ):
192 self.handle.sendline( "" )
193 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700194 command = "sudo kill -SIGING `pgrep ping`"
kelvin-onlabedcff052015-01-16 12:53:55 -0800195 main.log.info( command )
196 self.execute( cmd=command, prompt="(.*)", timeout=10 )
197 self.handle.sendline( "" )
198 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700199 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800200
kelvin-onlabedcff052015-01-16 12:53:55 -0800201 def pingHostOptical( self, **pingParams ):
202 """
Jon Hallefbd9792015-03-05 16:11:36 -0800203 This function is only for Packet Optical related ping
kelvin-onlabedcff052015-01-16 12:53:55 -0800204 Use the next pingHost() function for all normal scenarios )
shahshreya28bb18e2014-11-17 10:26:23 -0800205 Ping from one mininet host to another
206 Currently the only supported Params: SRC and TARGET
kelvin-onlabedcff052015-01-16 12:53:55 -0800207 """
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800208 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800209 command = args[ "SRC" ] + " ping " + \
210 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
shahshreya28bb18e2014-11-17 10:26:23 -0800211 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800212 main.log.warn( "Sending: " + command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800213 self.handle.sendline( command )
214 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800215 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800216 main.log.error(
217 self.name +
218 ": timeout when waiting for response from mininet" )
219 main.log.error( "response: " + str( self.handle.before ) )
220 i = self.handle.expect( [ "mininet>", 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 ) )
shahshreya28bb18e2014-11-17 10:26:23 -0800226 response = self.handle.before
227 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800228 main.log.error( self.name + ": EOF exception found" )
229 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800230 main.cleanup()
231 main.exit()
kelvin-onlabedcff052015-01-16 12:53:55 -0800232 main.log.info( self.name + ": Ping Response: " + response )
kelvin-onlabedcff052015-01-16 12:53:55 -0800233 if re.search( ',\s0\%\spacket\sloss', response ):
234 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800235 main.lastResult = main.TRUE
shahshreya28bb18e2014-11-17 10:26:23 -0800236 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800237 else:
238 main.log.error(
239 self.name +
240 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800241 main.lastResult = main.FALSE
shahshreya28bb18e2014-11-17 10:26:23 -0800242 return main.FALSE
243
kelvin-onlabedcff052015-01-16 12:53:55 -0800244 def pingHost( self, **pingParams ):
245 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800246 Pings between two hosts on remote mininet
kelvin-onlabedcff052015-01-16 12:53:55 -0800247 """
248 self.handle.sendline( "" )
249 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800250 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800251 command = "mininet/util/m " + \
252 args[ "SRC" ] + " ping " + args[ "TARGET" ] + " -c 4 -W 1 -i .2"
253 main.log.info( command )
254 response = self.execute( cmd=command, prompt="rtt", timeout=10 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800255 if utilities.assert_matches(
kelvin-onlabedcff052015-01-16 12:53:55 -0800256 expect=',\s0\%\spacket\sloss',
257 actual=response,
258 onpass="No Packet loss",
259 onfail="Host is not reachable" ):
260 main.log.info( "NO PACKET LOSS, HOST IS REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800261 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700262 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800263 else:
264 main.log.error( "PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800265 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700266 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800267
kelvin-onlabedcff052015-01-16 12:53:55 -0800268 def checknum( self, num ):
269 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800270 Verifies the correct number of switches are running
kelvin-onlabedcff052015-01-16 12:53:55 -0800271 """
272 if self.handle:
273 self.handle.sendline( "" )
274 self.handle.expect( "\$" )
275 self.handle.sendline( 'ifconfig -a | grep "sw.. " | wc -l' )
276 self.handle.expect( "wc" )
277 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700278 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800279 self.handle.sendline(
280 'ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l' )
281 self.handle.expect( "color" )
282 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700283 response2 = self.handle.before
284
kelvin-onlabedcff052015-01-16 12:53:55 -0800285 if re.search( num, response ):
286 if re.search( num, response2 ):
adminbae64d82013-08-01 10:50:15 -0700287 return main.TRUE
288 else:
289 return main.FALSE
290 else:
291 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800292 else:
293 main.log.error( "Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -0700294
kelvin-onlabd3b64892015-01-20 13:26:24 -0800295 def startTcpdump(
kelvin-onlabedcff052015-01-16 12:53:55 -0800296 self,
297 filename,
298 intf="eth0",
Charles Chan029be652015-08-24 01:46:10 +0800299 port="port 6653",
Jon Hall53c5e662016-04-13 16:06:56 -0700300 user="sdn" ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800301 """
Jon Hallefbd9792015-03-05 16:11:36 -0800302 Runs tcpdump on an interface and saves the file
admin2a9548d2014-06-17 14:08:07 -0700303 intf can be specified, or the default eth0 is used
kelvin-onlabedcff052015-01-16 12:53:55 -0800304 """
admin2a9548d2014-06-17 14:08:07 -0700305 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800306 self.handle.sendline( "" )
307 self.handle.sendline(
308 "sudo tcpdump -n -i " +
309 intf +
310 " " +
311 port +
312 " -w " +
313 filename.strip() +
314 " -Z " +
315 user +
316 " &" )
317 self.handle.sendline( "" )
318 self.handle.sendline( "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800319 i = self.handle.expect( [ 'No\ssuch\device', 'listening\son',
320 pexpect.TIMEOUT, "\$" ], timeout=10 )
Jon Hall61282e32015-03-19 11:34:11 -0700321 main.log.info( self.handle.before + self.handle.after )
admin2a9548d2014-06-17 14:08:07 -0700322 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800323 main.log.error( self.name + ": tcpdump - No such device exists.\
324 tcpdump attempted on: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700325 return main.FALSE
326 elif i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800327 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -0700328 return main.TRUE
329 elif i == 2:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800330 main.log.error( self.name + ": tcpdump command timed out!\
331 Check interface name, given interface was: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700332 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800333 elif i == 3:
334 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700335 return main.TRUE
336 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800337 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -0700338 return main.FALSE
339 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800340 main.log.error( self.name + ": EOF exception found" )
341 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700342 main.cleanup()
343 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800344 except Exception:
345 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700346 main.cleanup()
347 main.exit()
348
kelvin-onlabd3b64892015-01-20 13:26:24 -0800349 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -0800350 """
351 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -0700352 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800353 self.handle.sendline( "sudo pkill tcpdump" )
354 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800355 self.handle.expect( "\$" )
admin2a9548d2014-06-17 14:08:07 -0700356 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800357 main.log.error( self.name + ": EOF exception found" )
358 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700359 main.cleanup()
360 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800361 except Exception:
362 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700363 main.cleanup()
364 main.exit()
365
shahshreya1f119da2015-04-21 17:16:46 -0700366 def runOpticalMnScript( self,name = 'onos', ctrllerIP = None ):
shahshreya2c57c902015-04-06 20:40:20 -0700367 import time
shahshreya1f119da2015-04-21 17:16:46 -0700368 import types
kelvin-onlabedcff052015-01-16 12:53:55 -0800369 """
shahshreya1f119da2015-04-21 17:16:46 -0700370 Description:
371 This function is only meant for Packet Optical.
372 It runs python script "opticalTest.py" to create the
373 packet layer( mn ) and optical topology
374 Optional:
375 name - Name of onos directory. (ONOS | onos)
376 Required:
377 ctrllerIP = Controller(s) IP address
378 TODO: If no ctrllerIP is provided, a default
shahshreya2c57c902015-04-06 20:40:20 -0700379 $OC1 can be accepted
kelvin-onlabedcff052015-01-16 12:53:55 -0800380 """
shahshreya28bb18e2014-11-17 10:26:23 -0800381 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800382 self.handle.sendline( "" )
383 self.handle.expect( "\$" )
shahshreya1f119da2015-04-21 17:16:46 -0700384 self.handle.sendline( "cd ~/" + name + "/tools/test/topos" )
shahshreya2c57c902015-04-06 20:40:20 -0700385 self.handle.expect( "topos\$" )
386 if ctrllerIP == None:
387 main.log.info( "You need to specify the IP" )
388 return main.FALSE
389 else:
shahshreya1f119da2015-04-21 17:16:46 -0700390 controller = ''
391 if isinstance( ctrllerIP, types.ListType ):
392 for i in xrange( len( ctrllerIP ) ):
393 controller += ctrllerIP[i] + ' '
394 main.log.info( "Mininet topology is being loaded with " +
395 "controllers: " + controller )
396 elif isinstance( ctrllerIP, types.StringType ):
397 controller = ctrllerIP
398 main.log.info( "Mininet topology is being loaded with " +
399 "controller: " + controller )
400 else:
401 main.log.info( "You need to specify a valid IP" )
402 return main.FALSE
403 cmd = "sudo -E python opticalTest.py " + controller
404 main.log.info( self.name + ": cmd = " + cmd )
shahshreya2c57c902015-04-06 20:40:20 -0700405 self.handle.sendline( cmd )
shahshreyad524a942015-04-21 09:55:16 -0700406 time.sleep(30)
shahshreya2c57c902015-04-06 20:40:20 -0700407 self.handle.sendline( "" )
shahshreya3140b1a2015-04-28 14:22:15 -0700408 self.handle.sendline( "" )
shahshreya2c57c902015-04-06 20:40:20 -0700409 self.handle.expect("mininet>")
410 return main.TRUE
411 except pexpect.EOF:
412 main.log.error( self.name + ": EOF exception found" )
413 main.log.error( self.name + ": " + self.handle.before )
414 return main.FALSE
415
416 def attachLincOESession( self ):
417 """
418 Since executing opticalTest.py will give you mininet
419 prompt, you would at some point require to get onto
420 console of LincOE ((linc@onosTestBench)1>) to execute
421 commands like bring a optical port up or down on a ROADM
422 You can attach to console of Linc-OE session by a cmd:
423 sudo ~/linc-oe/rel/linc/bin/linc attach
424 """
425 try:
426 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800427 self.handle.expect( "\$" )
shahshreya2c57c902015-04-06 20:40:20 -0700428 self.handle.sendline( "sudo ~/linc-oe/rel/linc/bin/linc attach" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800429 self.handle.expect( ">" )
shahshreya28bb18e2014-11-17 10:26:23 -0800430 return main.TRUE
431 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800432 main.log.error( self.name + ": EOF exception found" )
433 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800434 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700435
kelvin-onlabedcff052015-01-16 12:53:55 -0800436 def disconnect( self ):
437 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800438 Called at the end of the test to disconnect the handle.
kelvin-onlabedcff052015-01-16 12:53:55 -0800439 """
adminbae64d82013-08-01 10:50:15 -0700440 if self.handle:
shahshreya95dd6f82015-02-05 15:59:16 -0800441 # Close the ssh connection
442 self.handle.sendline( "" )
Jon Hallefbd9792015-03-05 16:11:36 -0800443 # self.handle.expect( "\$" )
Jon Hall390696c2015-05-05 17:13:41 -0700444 i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT,
445 pexpect.EOF ], timeout=2 )
shahshreyadccfbc62015-02-20 11:40:09 -0800446 if i == 0:
447 self.handle.sendline( "exit" )
448 self.handle.expect( "closed" )
449 elif i == 1:
450 self.handle.sendline( "exit" )
451 self.handle.expect( "exit" )
452 self.handle.expect('\$')
453 self.handle.sendline( "exit" )
454 self.handle.expect( "exit" )
455 self.handle.expect( "closed" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800456 else:
457 main.log.error( "Connection failed to the host" )
Jon Halld61331b2015-02-17 16:35:47 -0800458 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700459
kelvin-onlabd3b64892015-01-20 13:26:24 -0800460 def setIpTablesOUTPUT( self, dstIp, dstPort, action='add',
461 packetType='tcp', rule='DROP' ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800462 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700463 Description:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800464 add or remove iptables rule to DROP ( default )
465 packets from specific IP and PORT
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700466 Usage:
kelvin-onlabedcff052015-01-16 12:53:55 -0800467 * specify action ( 'add' or 'remove' )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700468 when removing, pass in the same argument as you would add. It will
Jon Hallfbc828e2015-01-06 17:30:19 -0800469 delete that specific rule.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800470 * specify the destination ip to block with dstIp
471 * specify destination port to block to dstPort
kelvin-onlabedcff052015-01-16 12:53:55 -0800472 * optional packet type to block ( default tcp )
473 * optional iptables rule ( default DROP )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700474 WARNING:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800475 * This function uses root privilege iptables command which may result
476 in unwanted network errors. USE WITH CAUTION
kelvin-onlabedcff052015-01-16 12:53:55 -0800477 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700478 import re
479 import time
480
kelvin-onlabedcff052015-01-16 12:53:55 -0800481 # NOTE*********
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700482 # The strict checking methods of this driver function is intentional
483 # to discourage any misuse or error of iptables, which can cause
484 # severe network errors
kelvin-onlabd3b64892015-01-20 13:26:24 -0800485 # *************
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700486
kelvin-onlabd3b64892015-01-20 13:26:24 -0800487 # NOTE: Sleep needed to give some time
488 # for rule to be added and registered
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700489 # to the instance
kelvin-onlabedcff052015-01-16 12:53:55 -0800490 time.sleep( 5 )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700491
kelvin-onlabd3b64892015-01-20 13:26:24 -0800492 actionType = action.lower()
493 if actionType != 'add' and actionType != 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800494 main.log.error(
495 "Invalid action type. 'add' or 'remove' table rule" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700496 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
kelvin-onlabedcff052015-01-16 12:53:55 -0800497 # NOTE: Currently only supports rules DROP, ACCEPT, and LOG
498 main.log.error(
499 "Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700500 return
501 return
502 else:
503
kelvin-onlabedcff052015-01-16 12:53:55 -0800504 # If there is no existing rule in the iptables, we will see an
kelvin-onlabd3b64892015-01-20 13:26:24 -0800505 # 'iptables:'... message. We expect to see this message.
kelvin-onlabedcff052015-01-16 12:53:55 -0800506 # Otherwise, if there IS an existing rule, we will get the prompt
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700507 # back, hence why we expect $ for remove type. We want to remove
508 # an already existing rule
509
kelvin-onlabd3b64892015-01-20 13:26:24 -0800510 if actionType == 'add':
511 # NOTE: "iptables:" expect is a result of
512 # return from the command
513 # iptables -C ...
514 # Any changes by the iptables command return string
515 # will result in failure of the function. ( deemed unlikely
516 # at the time of writing this function )
kelvin-onlabedcff052015-01-16 12:53:55 -0800517 # Check for existing rules on current input
518 self.handle.sendline( "" )
519 self.handle.expect( "\$" )
520 self.handle.sendline(
521 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800522 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800523 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800524 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800525 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800526 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800527 " -j " +
528 str( rule ) )
529 i = self.handle.expect( [ "iptables:", "\$" ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700530 print i
531 print self.handle.before
532 print "after: "
533 print self.handle.after
534
kelvin-onlabd3b64892015-01-20 13:26:24 -0800535 elif actionType == 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800536 # Check for existing rules on current input
537 self.handle.sendline( "" )
538 self.handle.expect( "\$" )
539 self.handle.sendline(
540 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800541 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800542 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800543 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800544 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800545 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800546 " -j " +
547 str( rule ) )
548 self.handle.expect( "\$" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700549 print "before: "
550 print self.handle.before
kelvin-onlabd3b64892015-01-20 13:26:24 -0800551 actualString = self.handle.after
552 expectString = "iptables:"
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700553 print "Actual String:"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800554 print actualString
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700555
kelvin-onlabd3b64892015-01-20 13:26:24 -0800556 if re.search( expectString, actualString ):
557 matchResult = main.TRUE
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700558 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800559 matchResult = main.FALSE
560 # If matchResult is main.TRUE, it means there is no matching rule.
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700561
kelvin-onlabd3b64892015-01-20 13:26:24 -0800562 # If tables does not exist and expected prompt is returned,
563 # go ahead and add iptables rule
564 if matchResult == main.TRUE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800565 # Ensure action type is add
kelvin-onlabd3b64892015-01-20 13:26:24 -0800566 if actionType == 'add':
567 # -A is the 'append' action of iptables
568 actionAdd = '-A'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700569 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800570 self.handle.sendline( "" )
571 self.handle.sendline(
572 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800573 actionAdd +
kelvin-onlabedcff052015-01-16 12:53:55 -0800574 " 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 ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700582
kelvin-onlabd3b64892015-01-20 13:26:24 -0800583 infoString = "Rules added to " + str( self.name )
Jon Hallefbd9792015-03-05 16:11:36 -0800584 infoString += "iptables rule added to block IP: " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800585 str( dstIp )
586 infoString += "Port: " + \
587 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700588
kelvin-onlabd3b64892015-01-20 13:26:24 -0800589 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700590
kelvin-onlabedcff052015-01-16 12:53:55 -0800591 self.handle.expect(
592 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700593 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800594 main.log.error(
595 self.name +
596 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800597 except Exception:
598 main.log.exception( self.name +
599 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700600 main.cleanup()
601 main.exit()
602 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800603 main.log.error(
604 "Given rule already exists, but attempted to add it" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800605 # If matchResult is 0, it means there IS a matching rule provided
606 elif matchResult == main.FALSE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800607 # Ensure action type is remove
kelvin-onlabd3b64892015-01-20 13:26:24 -0800608 if actionType == 'remove':
609 # -D is the 'delete' rule of iptables
610 actionRemove = '-D'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700611 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800612 self.handle.sendline( "" )
613 # Delete a specific rule specified into the function
614 self.handle.sendline(
615 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800616 actionRemove +
kelvin-onlabedcff052015-01-16 12:53:55 -0800617 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800618 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800619 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800620 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800621 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800622 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800623 " -j " +
624 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700625
kelvin-onlabd3b64892015-01-20 13:26:24 -0800626 infoString = "Rules removed from " + str( self.name )
627 infoString += " iptables rule removed \
628 from blocking IP: " + \
629 str( dstIp )
630 infoString += " Port: " + \
631 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700632
kelvin-onlabd3b64892015-01-20 13:26:24 -0800633 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700634
kelvin-onlabedcff052015-01-16 12:53:55 -0800635 self.handle.expect(
636 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700637 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800638 main.log.error(
639 self.name +
640 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800641 except Exception:
642 main.log.exception( self.name +
643 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700644 main.cleanup()
645 main.exit()
646 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800647 main.log.error(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800648 "Given rule does not exist,\
649 but attempted to remove it" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700650 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800651 # NOTE: If a bad usage of this function occurs, exit the entire
652 # test
653 main.log.error( "Bad rule given for iptables. Exiting..." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700654 main.cleanup()
655 main.exit()
656
657
adminbae64d82013-08-01 10:50:15 -0700658if __name__ != "__main__":
659 import sys
kelvin-onlabedcff052015-01-16 12:53:55 -0800660 sys.modules[ __name__ ] = RemoteMininetDriver()