blob: 3b0b01b8f869493bf67305696b2ff3a607e66ac4 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
kelvin-onlabedcff052015-01-16 12:53:55 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 26-Oct-2012
4
kelvin-onlabedcff052015-01-16 12:53:55 -08005author:: Anil Kumar ( anilkumar.s@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07006
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
kelvin-onlabedcff052015-01-16 12:53:55 -080011 ( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070012
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
Jon Hallfbc828e2015-01-06 17:30:19 -080019 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
21
22MininetCliDriver is the basic driver which will handle the Mininet functions
kelvin-onlabedcff052015-01-16 12:53:55 -080023"""
adminbae64d82013-08-01 10:50:15 -070024import pexpect
adminbae64d82013-08-01 10:50:15 -070025import re
26import sys
kelvin-onlabedcff052015-01-16 12:53:55 -080027sys.path.append( "../" )
adminbae64d82013-08-01 10:50:15 -070028from drivers.common.cli.emulatordriver import Emulator
adminbae64d82013-08-01 10:50:15 -070029
kelvin-onlabedcff052015-01-16 12:53:55 -080030
31class RemoteMininetDriver( Emulator ):
32
33 """
kelvin-onlabd3b64892015-01-20 13:26:24 -080034 RemoteMininetCliDriver is the basic driver which will handle the Mininet
35 functions. The main different between this and the MininetCliDriver is that
36 this one does not build the mininet. It assumes that there is already a
37 mininet running on the target.
kelvin-onlabedcff052015-01-16 12:53:55 -080038 """
39 def __init__( self ):
40 super( Emulator, self ).__init__()
adminbae64d82013-08-01 10:50:15 -070041 self.handle = self
Jon Hallefbd9792015-03-05 16:11:36 -080042 self.name = None
kelvin-onlabedcff052015-01-16 12:53:55 -080043 self.wrapped = sys.modules[ __name__ ]
adminbae64d82013-08-01 10:50:15 -070044 self.flag = 0
45
kelvin-onlabedcff052015-01-16 12:53:55 -080046 def connect( self, **connectargs ):
kelvin-onlab08679eb2015-01-21 16:11:48 -080047 """,user_name, ip_address, pwd,options ):
kelvin-onlabd3b64892015-01-20 13:26:24 -080048 Here the main is the TestON instance after creating all the log
49 handles."""
adminbae64d82013-08-01 10:50:15 -070050 for key in connectargs:
kelvin-onlabedcff052015-01-16 12:53:55 -080051 vars( self )[ key ] = connectargs[ key ]
Jon Hallfbc828e2015-01-06 17:30:19 -080052
kelvin-onlabedcff052015-01-16 12:53:55 -080053 self.name = self.options[ 'name' ]
54 self.handle = super(
55 RemoteMininetDriver,
56 self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -080057 user_name=self.user_name,
58 ip_address=self.ip_address,
kelvin-onlabedcff052015-01-16 12:53:55 -080059 port=None,
60 pwd=self.pwd )
Jon Hallfbc828e2015-01-06 17:30:19 -080061
Jon Hallfbc828e2015-01-06 17:30:19 -080062 # Copying the readme file to process the
kelvin-onlabedcff052015-01-16 12:53:55 -080063 if self.handle:
adminbae64d82013-08-01 10:50:15 -070064 return main.TRUE
65
kelvin-onlabedcff052015-01-16 12:53:55 -080066 else:
67 main.log.error(
68 "Connection failed to the host " +
kelvin-onlab08679eb2015-01-21 16:11:48 -080069 self.user_name +
kelvin-onlabedcff052015-01-16 12:53:55 -080070 "@" +
kelvin-onlab08679eb2015-01-21 16:11:48 -080071 self.ip_address )
kelvin-onlabedcff052015-01-16 12:53:55 -080072 main.log.error( "Failed to connect to the Mininet" )
adminbae64d82013-08-01 10:50:15 -070073 return main.FALSE
admin98ad0092014-07-23 16:51:07 -070074
kelvin-onlabedcff052015-01-16 12:53:55 -080075 def checkForLoss( self, pingList ):
76 """
Jon Hall6c794f32014-08-14 13:33:13 -070077 Returns main.FALSE for 0% packet loss and
78 Returns main.ERROR if "found multiple mininet" is found and
79 Returns main.TRUE else
kelvin-onlabedcff052015-01-16 12:53:55 -080080 """
kelvin-onlabedcff052015-01-16 12:53:55 -080081 self.handle.sendline( "" )
82 self.handle.expect( "\$" )
kelvin-onlabedcff052015-01-16 12:53:55 -080083 self.handle.sendline( "" )
84 self.handle.expect( "\$" )
85 self.handle.sendline( "cat " + pingList )
86 self.handle.expect( pingList )
87 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -070088 outputs = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -080089 if re.search( " 0% packet loss", outputs ):
admin98ad0092014-07-23 16:51:07 -070090 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -080091 elif re.search( "found multiple mininet", outputs ):
admin2580a0e2014-07-29 11:24:34 -070092 return main.ERROR
shahshreyaf4d4d0c2014-10-10 12:11:10 -070093 else:
Jon Hall80daded2015-05-27 16:07:00 -070094 # TODO: Parse for failed pings, give some truncated output
kelvin-onlabedcff052015-01-16 12:53:55 -080095 main.log.error( "Error, unexpected output in the ping file" )
Jon Hall80daded2015-05-27 16:07:00 -070096 main.log.warn( outputs )
shahshreyaf4d4d0c2014-10-10 12:11:10 -070097 return main.TRUE
98
kelvin-onlab65782a82015-05-07 14:12:13 -070099 def arping( self, host="", ip="10.128.20.211" ):
100 """
101 Description:
102 Sends arp message from mininet host for hosts discovery
103 Required:
104 host - hosts name
105 Optional:
106 ip - ip address that does not exist in the network so there would
107 be no reply.
108 """
109 cmd = " py " + host + ".cmd(\"arping -c 1 " + ip + "\")"
110 try:
111 main.log.warn( "Sending: " + cmd )
112 self.handle.sendline( cmd )
113 response = self.handle.before
114 self.handle.sendline( "" )
115 self.handle.expect( "mininet>" )
116 return main.TRUE
117
118 except pexpect.EOF:
119 main.log.error( self.name + ": EOF exception found" )
120 main.log.error( self.name + ": " + self.handle.before )
121 main.cleanup()
122 main.exit()
123
kelvin-onlabedcff052015-01-16 12:53:55 -0800124 def pingLong( self, **pingParams ):
125 """
Jon Hallefbd9792015-03-05 16:11:36 -0800126 Starts a continuous ping on the mininet host outputting
kelvin-onlabd3b64892015-01-20 13:26:24 -0800127 to a file in the /tmp dir.
kelvin-onlabedcff052015-01-16 12:53:55 -0800128 """
129 self.handle.sendline( "" )
130 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800131 args = utilities.parse_args(
kelvin-onlabedcff052015-01-16 12:53:55 -0800132 [ "SRC", "TARGET", "PINGTIME" ], **pingParams )
133 precmd = "sudo rm /tmp/ping." + args[ "SRC" ]
134 self.execute( cmd=precmd, prompt="(.*)", timeout=10 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800135 command = "sudo mininet/util/m " + args[ "SRC" ] + " ping " +\
Jon Hallefbd9792015-03-05 16:11:36 -0800136 args[ "TARGET" ] + " -i .2 -w " +\
137 str( args[ 'PINGTIME' ] ) + " -D > /tmp/ping." +\
138 args[ "SRC" ] + " &"
Jon Hallfbc828e2015-01-06 17:30:19 -0800139 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800140 self.execute( cmd=command, prompt="(.*)", timeout=10 )
141 self.handle.sendline( "" )
142 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700143 return main.TRUE
144
kelvin-onlabedcff052015-01-16 12:53:55 -0800145 def pingstatus( self, **pingParams ):
146 """
kelvin-onlabd3b64892015-01-20 13:26:24 -0800147 Tails the respective ping output file and check that
148 there is a moving "64 bytes"
kelvin-onlabedcff052015-01-16 12:53:55 -0800149 """
150 self.handle.sendline( "" )
151 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800152 args = utilities.parse_args( [ "SRC" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800153 self.handle.sendline( "tail /tmp/ping." + args[ "SRC" ] )
154 self.handle.expect( "tail" )
155 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700156 result = self.handle.before + self.handle.after
kelvin-onlabedcff052015-01-16 12:53:55 -0800157 self.handle.sendline( "" )
158 self.handle.expect( "\$" )
159 if re.search( 'Unreachable', result ):
160 main.log.info( "Unreachable found in ping logs..." )
adminbae64d82013-08-01 10:50:15 -0700161 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800162 elif re.search( '64\sbytes', result ):
163 main.log.info( "Pings look good" )
adminbae64d82013-08-01 10:50:15 -0700164 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800165 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800166 main.log.info( "No, or faulty ping data..." )
adminbae64d82013-08-01 10:50:15 -0700167 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800168
kelvin-onlabedcff052015-01-16 12:53:55 -0800169 def pingKill( self, testONUser, testONIP ):
170 """
adminaeedddd2013-08-02 15:14:15 -0700171 Kills all continuous ping processes.
172 Then copies all the ping files to the TestStation.
kelvin-onlabedcff052015-01-16 12:53:55 -0800173 """
174 self.handle.sendline( "" )
175 self.handle.expect( "\$" )
Jon Hallfbc828e2015-01-06 17:30:19 -0800176 command = "sudo kill -SIGINT `pgrep ping`"
177 main.log.info( command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800178 self.execute( cmd=command, prompt="(.*)", timeout=10 )
Jon Hallfbc828e2015-01-06 17:30:19 -0800179
adminbae64d82013-08-01 10:50:15 -0700180 main.log.info( "Transferring ping files to TestStation" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800181 command = "scp /tmp/ping.* " + \
182 str( testONUser ) + "@" + str( testONIP ) + ":/tmp/"
183 self.execute( cmd=command, prompt="100%", timeout=20 )
184 # Make sure the output is cleared
185 self.handle.sendline( "" )
186 self.handle.expect( "\$" )
187 self.handle.sendline( "" )
188 self.handle.expect( "\$" )
189 self.handle.sendline( "" )
190 i = self.handle.expect( [ "password", "\$" ] )
Jon Hall368769f2014-11-19 15:43:35 -0800191 if i == 0:
kelvin-onlabedcff052015-01-16 12:53:55 -0800192 main.log.error( "Error, sudo asking for password" )
193 main.log.error( self.handle.before )
Jon Hall368769f2014-11-19 15:43:35 -0800194 return main.FALSE
195 else:
196 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800197
kelvin-onlabedcff052015-01-16 12:53:55 -0800198 def pingLongKill( self ):
199 self.handle.sendline( "" )
200 self.handle.expect( "\$" )
admin2580a0e2014-07-29 11:24:34 -0700201 command = "sudo kill -SIGING `pgrep ping`"
kelvin-onlabedcff052015-01-16 12:53:55 -0800202 main.log.info( command )
203 self.execute( cmd=command, prompt="(.*)", timeout=10 )
204 self.handle.sendline( "" )
205 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700206 return main.TRUE
Jon Hallfbc828e2015-01-06 17:30:19 -0800207
kelvin-onlabedcff052015-01-16 12:53:55 -0800208 def pingHostOptical( self, **pingParams ):
209 """
Jon Hallefbd9792015-03-05 16:11:36 -0800210 This function is only for Packet Optical related ping
kelvin-onlabedcff052015-01-16 12:53:55 -0800211 Use the next pingHost() function for all normal scenarios )
shahshreya28bb18e2014-11-17 10:26:23 -0800212 Ping from one mininet host to another
213 Currently the only supported Params: SRC and TARGET
kelvin-onlabedcff052015-01-16 12:53:55 -0800214 """
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800215 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800216 command = args[ "SRC" ] + " ping " + \
217 args[ "TARGET" ] + " -c 1 -i 1 -W 8"
shahshreya28bb18e2014-11-17 10:26:23 -0800218 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800219 main.log.warn( "Sending: " + command )
kelvin-onlabedcff052015-01-16 12:53:55 -0800220 self.handle.sendline( command )
221 i = self.handle.expect( [ command, pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800222 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800223 main.log.error(
224 self.name +
225 ": timeout when waiting for response from mininet" )
226 main.log.error( "response: " + str( self.handle.before ) )
227 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] )
shahshreya28bb18e2014-11-17 10:26:23 -0800228 if i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800229 main.log.error(
230 self.name +
231 ": timeout when waiting for response from mininet" )
232 main.log.error( "response: " + str( self.handle.before ) )
shahshreya28bb18e2014-11-17 10:26:23 -0800233 response = self.handle.before
234 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800235 main.log.error( self.name + ": EOF exception found" )
236 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800237 main.cleanup()
238 main.exit()
kelvin-onlabedcff052015-01-16 12:53:55 -0800239 main.log.info( self.name + ": Ping Response: " + response )
kelvin-onlabedcff052015-01-16 12:53:55 -0800240 if re.search( ',\s0\%\spacket\sloss', response ):
241 main.log.info( self.name + ": no packets lost, host is reachable" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800242 main.lastResult = main.TRUE
shahshreya28bb18e2014-11-17 10:26:23 -0800243 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800244 else:
245 main.log.error(
246 self.name +
247 ": PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800248 main.lastResult = main.FALSE
shahshreya28bb18e2014-11-17 10:26:23 -0800249 return main.FALSE
250
kelvin-onlabedcff052015-01-16 12:53:55 -0800251 def pingHost( self, **pingParams ):
252 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800253 Pings between two hosts on remote mininet
kelvin-onlabedcff052015-01-16 12:53:55 -0800254 """
255 self.handle.sendline( "" )
256 self.handle.expect( "\$" )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800257 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams )
kelvin-onlabedcff052015-01-16 12:53:55 -0800258 command = "mininet/util/m " + \
259 args[ "SRC" ] + " ping " + args[ "TARGET" ] + " -c 4 -W 1 -i .2"
260 main.log.info( command )
261 response = self.execute( cmd=command, prompt="rtt", timeout=10 )
kelvin-onlab7d0c9672015-01-20 15:56:22 -0800262 if utilities.assert_matches(
kelvin-onlabedcff052015-01-16 12:53:55 -0800263 expect=',\s0\%\spacket\sloss',
264 actual=response,
265 onpass="No Packet loss",
266 onfail="Host is not reachable" ):
267 main.log.info( "NO PACKET LOSS, HOST IS REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800268 main.lastResult = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700269 return main.TRUE
kelvin-onlabedcff052015-01-16 12:53:55 -0800270 else:
271 main.log.error( "PACKET LOST, HOST IS NOT REACHABLE" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800272 main.lastResult = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700273 return main.FALSE
Jon Hallfbc828e2015-01-06 17:30:19 -0800274
kelvin-onlabedcff052015-01-16 12:53:55 -0800275 def checknum( self, num ):
276 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800277 Verifies the correct number of switches are running
kelvin-onlabedcff052015-01-16 12:53:55 -0800278 """
279 if self.handle:
280 self.handle.sendline( "" )
281 self.handle.expect( "\$" )
282 self.handle.sendline( 'ifconfig -a | grep "sw.. " | wc -l' )
283 self.handle.expect( "wc" )
284 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700285 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800286 self.handle.sendline(
287 'ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l' )
288 self.handle.expect( "color" )
289 self.handle.expect( "\$" )
adminbae64d82013-08-01 10:50:15 -0700290 response2 = self.handle.before
291
kelvin-onlabedcff052015-01-16 12:53:55 -0800292 if re.search( num, response ):
293 if re.search( num, response2 ):
adminbae64d82013-08-01 10:50:15 -0700294 return main.TRUE
295 else:
296 return main.FALSE
297 else:
298 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800299 else:
300 main.log.error( "Connection failed to the host" )
adminbae64d82013-08-01 10:50:15 -0700301
kelvin-onlabd3b64892015-01-20 13:26:24 -0800302 def startTcpdump(
kelvin-onlabedcff052015-01-16 12:53:55 -0800303 self,
304 filename,
305 intf="eth0",
306 port="port 6633",
307 user="admin" ):
308 """
Jon Hallefbd9792015-03-05 16:11:36 -0800309 Runs tcpdump on an interface and saves the file
admin2a9548d2014-06-17 14:08:07 -0700310 intf can be specified, or the default eth0 is used
kelvin-onlabedcff052015-01-16 12:53:55 -0800311 """
admin2a9548d2014-06-17 14:08:07 -0700312 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800313 self.handle.sendline( "" )
314 self.handle.sendline(
315 "sudo tcpdump -n -i " +
316 intf +
317 " " +
318 port +
319 " -w " +
320 filename.strip() +
321 " -Z " +
322 user +
323 " &" )
324 self.handle.sendline( "" )
325 self.handle.sendline( "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800326 i = self.handle.expect( [ 'No\ssuch\device', 'listening\son',
327 pexpect.TIMEOUT, "\$" ], timeout=10 )
Jon Hall61282e32015-03-19 11:34:11 -0700328 main.log.info( self.handle.before + self.handle.after )
admin2a9548d2014-06-17 14:08:07 -0700329 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800330 main.log.error( self.name + ": tcpdump - No such device exists.\
331 tcpdump attempted on: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700332 return main.FALSE
333 elif i == 1:
kelvin-onlabedcff052015-01-16 12:53:55 -0800334 main.log.info( self.name + ": tcpdump started on " + intf )
admin2a9548d2014-06-17 14:08:07 -0700335 return main.TRUE
336 elif i == 2:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800337 main.log.error( self.name + ": tcpdump command timed out!\
338 Check interface name, given interface was: " + intf )
admin2a9548d2014-06-17 14:08:07 -0700339 return main.FALSE
kelvin-onlabedcff052015-01-16 12:53:55 -0800340 elif i == 3:
341 main.log.info( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700342 return main.TRUE
343 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800344 main.log.error( self.name + ": tcpdump - unexpected response" )
admin2a9548d2014-06-17 14:08:07 -0700345 return main.FALSE
346 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800347 main.log.error( self.name + ": EOF exception found" )
348 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700349 main.cleanup()
350 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800351 except Exception:
352 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700353 main.cleanup()
354 main.exit()
355
kelvin-onlabd3b64892015-01-20 13:26:24 -0800356 def stopTcpdump( self ):
Jon Hallefbd9792015-03-05 16:11:36 -0800357 """
358 pkills tcpdump"""
admin2a9548d2014-06-17 14:08:07 -0700359 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800360 self.handle.sendline( "sudo pkill tcpdump" )
361 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800362 self.handle.expect( "\$" )
admin2a9548d2014-06-17 14:08:07 -0700363 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800364 main.log.error( self.name + ": EOF exception found" )
365 main.log.error( self.name + ": " + self.handle.before )
admin2a9548d2014-06-17 14:08:07 -0700366 main.cleanup()
367 main.exit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800368 except Exception:
369 main.log.exception( self.name + ": Uncaught exception!" )
admin2a9548d2014-06-17 14:08:07 -0700370 main.cleanup()
371 main.exit()
372
kelvin-onlab65782a82015-05-07 14:12:13 -0700373 def runOpticalMnScript( self,name = 'onos', ctrllerIP = None ):
shahshreya2c57c902015-04-06 20:40:20 -0700374 import time
kelvin-onlab65782a82015-05-07 14:12:13 -0700375 import types
kelvin-onlabedcff052015-01-16 12:53:55 -0800376 """
kelvin-onlab65782a82015-05-07 14:12:13 -0700377 Description:
378 This function is only meant for Packet Optical.
379 It runs python script "opticalTest.py" to create the
380 packet layer( mn ) and optical topology
381 Optional:
382 name - Name of onos directory. (ONOS | onos)
383 Required:
384 ctrllerIP = Controller(s) IP address
385 TODO: If no ctrllerIP is provided, a default
shahshreya2c57c902015-04-06 20:40:20 -0700386 $OC1 can be accepted
kelvin-onlabedcff052015-01-16 12:53:55 -0800387 """
shahshreya28bb18e2014-11-17 10:26:23 -0800388 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800389 self.handle.sendline( "" )
390 self.handle.expect( "\$" )
kelvin-onlab65782a82015-05-07 14:12:13 -0700391 self.handle.sendline( "cd ~/" + name + "/tools/test/topos" )
shahshreya2c57c902015-04-06 20:40:20 -0700392 self.handle.expect( "topos\$" )
393 if ctrllerIP == None:
394 main.log.info( "You need to specify the IP" )
395 return main.FALSE
396 else:
kelvin-onlab65782a82015-05-07 14:12:13 -0700397 controller = ''
398 if isinstance( ctrllerIP, types.ListType ):
399 for i in xrange( len( ctrllerIP ) ):
400 controller += ctrllerIP[i] + ' '
401 main.log.info( "Mininet topology is being loaded with " +
402 "controllers: " + controller )
403 elif isinstance( ctrllerIP, types.StringType ):
404 controller = ctrllerIP
405 main.log.info( "Mininet topology is being loaded with " +
406 "controller: " + controller )
407 else:
408 main.log.info( "You need to specify a valid IP" )
409 return main.FALSE
410 cmd = "sudo -E python opticalTest.py " + controller
411 main.log.info( self.name + ": cmd = " + cmd )
shahshreya2c57c902015-04-06 20:40:20 -0700412 self.handle.sendline( cmd )
413 self.handle.expect( "Press ENTER to push Topology.json" )
kelvin-onlab65782a82015-05-07 14:12:13 -0700414 time.sleep(30)
415 self.handle.sendline( "" )
shahshreya2c57c902015-04-06 20:40:20 -0700416 self.handle.sendline( "" )
417 self.handle.expect("mininet>")
418 return main.TRUE
419 except pexpect.EOF:
420 main.log.error( self.name + ": EOF exception found" )
421 main.log.error( self.name + ": " + self.handle.before )
422 return main.FALSE
423
424 def attachLincOESession( self ):
425 """
426 Since executing opticalTest.py will give you mininet
427 prompt, you would at some point require to get onto
428 console of LincOE ((linc@onosTestBench)1>) to execute
429 commands like bring a optical port up or down on a ROADM
430 You can attach to console of Linc-OE session by a cmd:
431 sudo ~/linc-oe/rel/linc/bin/linc attach
432 """
433 try:
434 self.handle.sendline( "" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800435 self.handle.expect( "\$" )
shahshreya2c57c902015-04-06 20:40:20 -0700436 self.handle.sendline( "sudo ~/linc-oe/rel/linc/bin/linc attach" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800437 self.handle.expect( ">" )
shahshreya28bb18e2014-11-17 10:26:23 -0800438 return main.TRUE
439 except pexpect.EOF:
kelvin-onlabedcff052015-01-16 12:53:55 -0800440 main.log.error( self.name + ": EOF exception found" )
441 main.log.error( self.name + ": " + self.handle.before )
shahshreya28bb18e2014-11-17 10:26:23 -0800442 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700443
kelvin-onlabedcff052015-01-16 12:53:55 -0800444 def disconnect( self ):
445 """
Jon Hallfbc828e2015-01-06 17:30:19 -0800446 Called at the end of the test to disconnect the handle.
kelvin-onlabedcff052015-01-16 12:53:55 -0800447 """
adminbae64d82013-08-01 10:50:15 -0700448 if self.handle:
shahshreya95dd6f82015-02-05 15:59:16 -0800449 # Close the ssh connection
450 self.handle.sendline( "" )
Jon Hallefbd9792015-03-05 16:11:36 -0800451 # self.handle.expect( "\$" )
Jon Hall390696c2015-05-05 17:13:41 -0700452 i = self.handle.expect( [ '\$', 'mininet>', pexpect.TIMEOUT,
453 pexpect.EOF ], timeout=2 )
shahshreyadccfbc62015-02-20 11:40:09 -0800454 if i == 0:
455 self.handle.sendline( "exit" )
456 self.handle.expect( "closed" )
457 elif i == 1:
458 self.handle.sendline( "exit" )
459 self.handle.expect( "exit" )
460 self.handle.expect('\$')
461 self.handle.sendline( "exit" )
462 self.handle.expect( "exit" )
463 self.handle.expect( "closed" )
kelvin-onlabedcff052015-01-16 12:53:55 -0800464 else:
465 main.log.error( "Connection failed to the host" )
Jon Halld61331b2015-02-17 16:35:47 -0800466 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700467
kelvin-onlabd3b64892015-01-20 13:26:24 -0800468 def getFlowTable( self, protoVersion, sw ):
469 """
470 TODO document usage
Jon Hallefbd9792015-03-05 16:11:36 -0800471 TODO add option to look at cookies. ignoring them for now
kelvin-onlabd3b64892015-01-20 13:26:24 -0800472
473 print "get_flowTable(" + str( protoVersion ) +" " + str( sw ) +")"
474 NOTE: Use format to force consistent flow table output across
475 versions"""
kelvin-onlabedcff052015-01-16 12:53:55 -0800476 self.handle.sendline( "cd" )
477 self.handle.expect( [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
kelvin-onlabedcff052015-01-16 12:53:55 -0800478 if protoVersion == 1.0:
479 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800480 " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 \
481 $7 $8}' | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800482 self.handle.sendline( command )
483 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
484 self.handle.expect(
485 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700486 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800487 # print "response=", response
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700488 return response
kelvin-onlabedcff052015-01-16 12:53:55 -0800489 elif protoVersion == 1.3:
490 command = "sudo ovs-ofctl dump-flows " + sw + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800491 " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}'\
492 | cut -d ',' -f 2- | sort -n -k1 -r"
kelvin-onlabedcff052015-01-16 12:53:55 -0800493 self.handle.sendline( command )
494 self.handle.expect( [ "k1 -r", pexpect.EOF, pexpect.TIMEOUT ] )
495 self.handle.expect(
496 [ "OFPST_FLOW", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700497 response = self.handle.before
kelvin-onlabedcff052015-01-16 12:53:55 -0800498 # print "response=", response
Jon Hall94fd0472014-12-08 11:52:42 -0800499 return response
500 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800501 main.log.error(
502 "Unknown protoVersion in get_flowTable(). given: (" +
503 str(
504 type( protoVersion ) ) +
505 ") '" +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800506 str( protoVersion ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800507 "'" )
Jon Hall94fd0472014-12-08 11:52:42 -0800508
kelvin-onlabd3b64892015-01-20 13:26:24 -0800509 def flowComp( self, flow1, flow2 ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800510 if flow1 == flow2:
santhosh19fd8032014-07-29 11:56:17 -0700511 return main.TRUE
512 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800513 main.log.info( "Flow tables do not match, printing tables:" )
514 main.log.info( "Flow Table 1:" )
515 main.log.info( flow1 )
516 main.log.info( "Flow Table 2:" )
517 main.log.info( flow2 )
santhosh19fd8032014-07-29 11:56:17 -0700518 return main.FALSE
519
kelvin-onlabd3b64892015-01-20 13:26:24 -0800520 def setIpTablesOUTPUT( self, dstIp, dstPort, action='add',
521 packetType='tcp', rule='DROP' ):
kelvin-onlabedcff052015-01-16 12:53:55 -0800522 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700523 Description:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800524 add or remove iptables rule to DROP ( default )
525 packets from specific IP and PORT
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700526 Usage:
kelvin-onlabedcff052015-01-16 12:53:55 -0800527 * specify action ( 'add' or 'remove' )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700528 when removing, pass in the same argument as you would add. It will
Jon Hallfbc828e2015-01-06 17:30:19 -0800529 delete that specific rule.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800530 * specify the destination ip to block with dstIp
531 * specify destination port to block to dstPort
kelvin-onlabedcff052015-01-16 12:53:55 -0800532 * optional packet type to block ( default tcp )
533 * optional iptables rule ( default DROP )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700534 WARNING:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800535 * This function uses root privilege iptables command which may result
536 in unwanted network errors. USE WITH CAUTION
kelvin-onlabedcff052015-01-16 12:53:55 -0800537 """
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700538 import re
539 import time
540
kelvin-onlabedcff052015-01-16 12:53:55 -0800541 # NOTE*********
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700542 # The strict checking methods of this driver function is intentional
543 # to discourage any misuse or error of iptables, which can cause
544 # severe network errors
kelvin-onlabd3b64892015-01-20 13:26:24 -0800545 # *************
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700546
kelvin-onlabd3b64892015-01-20 13:26:24 -0800547 # NOTE: Sleep needed to give some time
548 # for rule to be added and registered
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700549 # to the instance
kelvin-onlabedcff052015-01-16 12:53:55 -0800550 time.sleep( 5 )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700551
kelvin-onlabd3b64892015-01-20 13:26:24 -0800552 actionType = action.lower()
553 if actionType != 'add' and actionType != 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800554 main.log.error(
555 "Invalid action type. 'add' or 'remove' table rule" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700556 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
kelvin-onlabedcff052015-01-16 12:53:55 -0800557 # NOTE: Currently only supports rules DROP, ACCEPT, and LOG
558 main.log.error(
559 "Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700560 return
561 return
562 else:
563
kelvin-onlabedcff052015-01-16 12:53:55 -0800564 # If there is no existing rule in the iptables, we will see an
kelvin-onlabd3b64892015-01-20 13:26:24 -0800565 # 'iptables:'... message. We expect to see this message.
kelvin-onlabedcff052015-01-16 12:53:55 -0800566 # Otherwise, if there IS an existing rule, we will get the prompt
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700567 # back, hence why we expect $ for remove type. We want to remove
568 # an already existing rule
569
kelvin-onlabd3b64892015-01-20 13:26:24 -0800570 if actionType == 'add':
571 # NOTE: "iptables:" expect is a result of
572 # return from the command
573 # iptables -C ...
574 # Any changes by the iptables command return string
575 # will result in failure of the function. ( deemed unlikely
576 # at the time of writing this function )
kelvin-onlabedcff052015-01-16 12:53:55 -0800577 # Check for existing rules on current input
578 self.handle.sendline( "" )
579 self.handle.expect( "\$" )
580 self.handle.sendline(
581 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800582 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800583 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800584 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800585 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800586 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800587 " -j " +
588 str( rule ) )
589 i = self.handle.expect( [ "iptables:", "\$" ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700590 print i
591 print self.handle.before
592 print "after: "
593 print self.handle.after
594
kelvin-onlabd3b64892015-01-20 13:26:24 -0800595 elif actionType == 'remove':
kelvin-onlabedcff052015-01-16 12:53:55 -0800596 # Check for existing rules on current input
597 self.handle.sendline( "" )
598 self.handle.expect( "\$" )
599 self.handle.sendline(
600 "sudo iptables -C OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800601 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800602 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800603 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800604 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800605 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800606 " -j " +
607 str( rule ) )
608 self.handle.expect( "\$" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700609 print "before: "
610 print self.handle.before
kelvin-onlabd3b64892015-01-20 13:26:24 -0800611 actualString = self.handle.after
612 expectString = "iptables:"
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700613 print "Actual String:"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800614 print actualString
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700615
kelvin-onlabd3b64892015-01-20 13:26:24 -0800616 if re.search( expectString, actualString ):
617 matchResult = main.TRUE
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700618 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800619 matchResult = main.FALSE
620 # If matchResult is main.TRUE, it means there is no matching rule.
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700621
kelvin-onlabd3b64892015-01-20 13:26:24 -0800622 # If tables does not exist and expected prompt is returned,
623 # go ahead and add iptables rule
624 if matchResult == main.TRUE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800625 # Ensure action type is add
kelvin-onlabd3b64892015-01-20 13:26:24 -0800626 if actionType == 'add':
627 # -A is the 'append' action of iptables
628 actionAdd = '-A'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700629 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800630 self.handle.sendline( "" )
631 self.handle.sendline(
632 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800633 actionAdd +
kelvin-onlabedcff052015-01-16 12:53:55 -0800634 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800635 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800636 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800637 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800638 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800639 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800640 " -j " +
641 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700642
kelvin-onlabd3b64892015-01-20 13:26:24 -0800643 infoString = "Rules added to " + str( self.name )
Jon Hallefbd9792015-03-05 16:11:36 -0800644 infoString += "iptables rule added to block IP: " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -0800645 str( dstIp )
646 infoString += "Port: " + \
647 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700648
kelvin-onlabd3b64892015-01-20 13:26:24 -0800649 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700650
kelvin-onlabedcff052015-01-16 12:53:55 -0800651 self.handle.expect(
652 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700653 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800654 main.log.error(
655 self.name +
656 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800657 except Exception:
658 main.log.exception( self.name +
659 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700660 main.cleanup()
661 main.exit()
662 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800663 main.log.error(
664 "Given rule already exists, but attempted to add it" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800665 # If matchResult is 0, it means there IS a matching rule provided
666 elif matchResult == main.FALSE:
kelvin-onlabedcff052015-01-16 12:53:55 -0800667 # Ensure action type is remove
kelvin-onlabd3b64892015-01-20 13:26:24 -0800668 if actionType == 'remove':
669 # -D is the 'delete' rule of iptables
670 actionRemove = '-D'
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700671 try:
kelvin-onlabedcff052015-01-16 12:53:55 -0800672 self.handle.sendline( "" )
673 # Delete a specific rule specified into the function
674 self.handle.sendline(
675 "sudo iptables " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800676 actionRemove +
kelvin-onlabedcff052015-01-16 12:53:55 -0800677 " OUTPUT -p " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800678 str( packetType ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800679 " -d " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800680 str( dstIp ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800681 " --dport " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800682 str( dstPort ) +
kelvin-onlabedcff052015-01-16 12:53:55 -0800683 " -j " +
684 str( rule ) )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700685
kelvin-onlabd3b64892015-01-20 13:26:24 -0800686 infoString = "Rules removed from " + str( self.name )
687 infoString += " iptables rule removed \
688 from blocking IP: " + \
689 str( dstIp )
690 infoString += " Port: " + \
691 str( dstPort ) + " Rule: " + str( rule )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700692
kelvin-onlabd3b64892015-01-20 13:26:24 -0800693 main.log.info( infoString )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700694
kelvin-onlabedcff052015-01-16 12:53:55 -0800695 self.handle.expect(
696 [ "\$", pexpect.EOF, pexpect.TIMEOUT ] )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700697 except pexpect.TIMEOUT:
kelvin-onlabedcff052015-01-16 12:53:55 -0800698 main.log.error(
699 self.name +
700 ": Timeout exception in setIpTables function" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800701 except Exception:
702 main.log.exception( self.name +
703 ": Uncaught exception!" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700704 main.cleanup()
705 main.exit()
706 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800707 main.log.error(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800708 "Given rule does not exist,\
709 but attempted to remove it" )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700710 else:
kelvin-onlabedcff052015-01-16 12:53:55 -0800711 # NOTE: If a bad usage of this function occurs, exit the entire
712 # test
713 main.log.error( "Bad rule given for iptables. Exiting..." )
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700714 main.cleanup()
715 main.exit()
716
717
adminbae64d82013-08-01 10:50:15 -0700718if __name__ != "__main__":
719 import sys
kelvin-onlabedcff052015-01-16 12:53:55 -0800720 sys.modules[ __name__ ] = RemoteMininetDriver()