blob: bb03c07c38a032ce81f25d6c9d9f90c701cd0143 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
2'''
3Created on 26-Oct-2012
4
5@author: Anil Kumar (anilkumar.s@paxterrasolutions.com)
6
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
11 (at your option) any later version.
12
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
19 along with TestON. If not, see <http://www.gnu.org/licenses/>.
20
21
22MininetCliDriver is the basic driver which will handle the Mininet functions
23'''
admin2a9548d2014-06-17 14:08:07 -070024import traceback
adminbae64d82013-08-01 10:50:15 -070025import pexpect
26import struct
27import fcntl
28import os
29import signal
30import re
31import sys
32import core.teston
33sys.path.append("../")
34from drivers.common.cli.emulatordriver import Emulator
35from drivers.common.clidriver import CLI
36from time import time
37
38class RemoteMininetDriver(Emulator):
39 '''
adminaeedddd2013-08-02 15:14:15 -070040 RemoteMininetCliDriver is the basic driver which will handle the Mininet functions
41 The main different between this and the MininetCliDriver is that this one does not build the mininet.
42 It assumes that there is already a mininet running on the target.
adminbae64d82013-08-01 10:50:15 -070043 '''
44 def __init__(self):
45 super(Emulator, self).__init__()
46 self.handle = self
47 self.wrapped = sys.modules[__name__]
48 self.flag = 0
49
50 def connect(self, **connectargs):
51 #,user_name, ip_address, pwd,options):
52 # Here the main is the TestON instance after creating all the log handles.
53 for key in connectargs:
54 vars(self)[key] = connectargs[key]
55
56 self.name = self.options['name']
57 self.handle = super(RemoteMininetDriver, self).connect(user_name = self.user_name, ip_address = self.ip_address,port = None, pwd = self.pwd)
58
59 self.ssh_handle = self.handle
60
61 # Copying the readme file to process the
62 if self.handle :
63 return main.TRUE
64
65 else :
66 main.log.error("Connection failed to the host "+self.user_name+"@"+self.ip_address)
67 main.log.error("Failed to connect to the Mininet")
68 return main.FALSE
admin98ad0092014-07-23 16:51:07 -070069
70#*********************************************************************************************
71#*********************************************************************************************
72# checkForLoss will determine if any of the pings had any packets lost during the course of
73# the pingLong.
74#*********************************************************************************************
75#*********************************************************************************************
76
admin2580a0e2014-07-29 11:24:34 -070077 def checkForLoss(self, pingList):
Jon Hall6c794f32014-08-14 13:33:13 -070078 '''
79 Returns main.FALSE for 0% packet loss and
80 Returns main.ERROR if "found multiple mininet" is found and
81 Returns main.TRUE else
82 '''
admin98ad0092014-07-23 16:51:07 -070083 import os
admin2580a0e2014-07-29 11:24:34 -070084 self.handle.sendline("")
85 self.handle.expect("\$")
86 self.handle.sendline("cat " + pingList)
87 self.handle.expect(pingList)
88 self.handle.expect("\$")
89 outputs = self.handle.before + self.handle.after
90 if re.search(" 0% packet loss",outputs):
admin98ad0092014-07-23 16:51:07 -070091 return main.FALSE
admin2580a0e2014-07-29 11:24:34 -070092 elif re.search("found multiple mininet",outputs):
93 return main.ERROR
shahshreyaf4d4d0c2014-10-10 12:11:10 -070094 else:
95 print outputs
96 return main.TRUE
97
admin98ad0092014-07-23 16:51:07 -070098
99
adminbae64d82013-08-01 10:50:15 -0700100 def pingLong(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700101 '''
102 Starts a continuous ping on the mininet host outputing to a file in the /tmp dir.
103 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700104 self.handle.sendline("")
105 self.handle.expect("\$")
admin98ad0092014-07-23 16:51:07 -0700106 args = utilities.parse_args(["SRC","TARGET","PINGTIME"],**pingParams)
Jon Hall6c794f32014-08-14 13:33:13 -0700107 precmd = "sudo rm /tmp/ping." + args["SRC"]
admin530b4c92013-08-14 16:54:35 -0700108 self.execute(cmd=precmd,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700109 command = "sudo mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -i .2 -w " + str(args['PINGTIME']) + " > /tmp/ping." + args["SRC"] + " &"
adminbae64d82013-08-01 10:50:15 -0700110 main.log.info( command )
111 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700112 self.handle.sendline("")
113 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700114 return main.TRUE
115
116 def pingstatus(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700117 '''
118 Tails the respective ping output file and check that there is a moving "64 bytes"
119 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700120 self.handle.sendline("")
121 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700122 args = utilities.parse_args(["SRC"],**pingParams)
123 self.handle.sendline("tail /tmp/ping." + args["SRC"])
124 self.handle.expect("tail")
125 self.handle.expect("\$")
126 result = self.handle.before + self.handle.after
Jon Hall6c794f32014-08-14 13:33:13 -0700127 self.handle.sendline("")
128 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700129 if re.search('Unreachable', result ):
130 main.log.info("Unreachable found in ping logs...")
131 return main.FALSE
132 elif re.search('64\sbytes', result):
133 main.log.info("Pings look good")
134 return main.TRUE
135 else:
136 main.log.info("No, or faulty ping data...")
137 return main.FALSE
138
Jon Hall6c794f32014-08-14 13:33:13 -0700139 def pingKill(self, testONUser, testONIP):
adminaeedddd2013-08-02 15:14:15 -0700140 '''
141 Kills all continuous ping processes.
142 Then copies all the ping files to the TestStation.
143 '''
144 import time
Jon Hall6c794f32014-08-14 13:33:13 -0700145 self.handle.sendline("")
146 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700147 command = "sudo kill -SIGINT `pgrep ping`"
adminbae64d82013-08-01 10:50:15 -0700148 main.log.info( command )
149 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700150 #Commenting out in case TestON and MN are on the same machine. scp overrights the file anyways
151 #main.log.info( "Removing old ping data" )
152 #command = "rm /tmp/ping.*"
153 #os.popen(command)
154 #time.sleep(2)
adminbae64d82013-08-01 10:50:15 -0700155 main.log.info( "Transferring ping files to TestStation" )
Jon Hall6c794f32014-08-14 13:33:13 -0700156 command = "scp /tmp/ping.* "+ str(testONUser) + "@" + str(testONIP) + ":/tmp/"
adminbae64d82013-08-01 10:50:15 -0700157 self.execute(cmd=command,prompt="100%",timeout=20)
Jon Hall6c794f32014-08-14 13:33:13 -0700158 self.handle.sendline("")
159 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700160 return main.TRUE
161
162 def pingLongKill(self):
163 import time
Jon Hall6c794f32014-08-14 13:33:13 -0700164 self.handle.sendline("")
165 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700166 command = "sudo kill -SIGING `pgrep ping`"
167 main.log.info(command)
168 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700169 self.handle.sendline("")
170 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700171 return main.TRUE
shahshreya28bb18e2014-11-17 10:26:23 -0800172
173 def pingHostOptical(self,**pingParams):
174 '''
175 This function is only for Packey Optical related ping
176 Use the next pingHost() function for all normal scenarios)
177 Ping from one mininet host to another
178 Currently the only supported Params: SRC and TARGET
179 '''
180 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
181 #command = args["SRC"] + " ping -" + args["CONTROLLER"] + " " +args ["TARGET"]
182 command = args["SRC"] + " ping "+args ["TARGET"]+" -c 1 -i 1 -W 8"
183 try:
184 main.log.warn("Sending: " + command)
185 #response = self.execute(cmd=command,prompt="mininet",timeout=10 )
186 self.handle.sendline(command)
187 i = self.handle.expect([command,pexpect.TIMEOUT])
188 if i == 1:
189 main.log.error(self.name + ": timeout when waiting for response from mininet")
190 main.log.error("response: " + str(self.handle.before))
191 i = self.handle.expect(["mininet>",pexpect.TIMEOUT])
192 if i == 1:
193 main.log.error(self.name + ": timeout when waiting for response from mininet")
194 main.log.error("response: " + str(self.handle.before))
195 response = self.handle.before
196 except pexpect.EOF:
197 main.log.error(self.name + ": EOF exception found")
198 main.log.error(self.name + ": " + self.handle.before)
199 main.cleanup()
200 main.exit()
201 main.log.info(self.name+": Ping Response: "+ response )
202 #if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
203 if re.search(',\s0\%\spacket\sloss',response):
204 main.log.info(self.name+": no packets lost, host is reachable")
205 main.last_result = main.TRUE
206 return main.TRUE
207 else :
208 main.log.error(self.name+": PACKET LOST, HOST IS NOT REACHABLE")
209 main.last_result = main.FALSE
210 return main.FALSE
211
212
213 def pingall(self):
214 '''
215 Verifies the reachability of the hosts using pingall command.
216 This function is required by Packey Optical test
217 '''
218 if self.handle :
219 main.log.info(self.name+": Checking reachabilty to the hosts using pingall")
220 try:
221 response = self.execute(cmd="pingall",prompt="mininet>",timeout=120)
222 print "response: " + str(response)
223 except pexpect.EOF:
224 main.log.error(self.name + ": EOF exception found")
225 main.log.error(self.name + ": " + self.handle.before)
226 pattern = 'Results\:\s0\%\sdropped\s'
227 if re.search(pattern,response):
228 main.log.info(self.name+": All hosts are reachable")
229 return main.TRUE
230 else:
231 main.log.error(self.name+": Unable to reach all the hosts")
232 return main.FALSE
233 else :
234 main.log.error(self.name+": Connection failed to the host")
235 return main.FALSE
236
237
238
239
adminbae64d82013-08-01 10:50:15 -0700240 def pingHost(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700241 '''
242 Pings between two hosts on remote mininet
243 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700244 self.handle.sendline("")
245 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700246 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
shahshreya28bb18e2014-11-17 10:26:23 -0800247 #command = "mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -c 4 -W 1 -i .2"
adminbae64d82013-08-01 10:50:15 -0700248 command = "mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -c 4 -W 1 -i .2"
249 main.log.info ( command )
250 response = self.execute(cmd=command,prompt="rtt",timeout=10 )
shahshreya28bb18e2014-11-17 10:26:23 -0800251 #self.handle.sendline("")
252 #self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700253 if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
254 main.log.info("NO PACKET LOSS, HOST IS REACHABLE")
255 main.last_result = main.TRUE
256 return main.TRUE
257 else :
258 main.log.error("PACKET LOST, HOST IS NOT REACHABLE")
259 main.last_result = main.FALSE
260 return main.FALSE
261
262
263 def checknum(self,num):
264 '''
adminaeedddd2013-08-02 15:14:15 -0700265 Verifies the correct number of switches are running
adminbae64d82013-08-01 10:50:15 -0700266 '''
267 if self.handle :
268 self.handle.sendline("")
269 self.handle.expect("\$")
270 self.handle.sendline('ifconfig -a | grep "sw.. " | wc -l')
271 self.handle.expect("wc")
272 self.handle.expect("\$")
273 response = self.handle.before
274 self.handle.sendline('ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l')
275 self.handle.expect("color")
276 self.handle.expect("\$")
277 response2 = self.handle.before
278
279 if re.search(num, response):
280 if re.search(num, response2):
281 return main.TRUE
282 else:
283 return main.FALSE
284 else:
285 return main.FALSE
286 else :
287 main.log.error("Connection failed to the host")
288
289 def ctrl_none(self):
adminaeedddd2013-08-02 15:14:15 -0700290 '''
291 Sets all the switches to no controllers.
292 '''
adminbae64d82013-08-01 10:50:15 -0700293 self.execute(cmd="~/ONOS/scripts/test-ctrl-none.sh", prompt="\$",timeout=10)
294
295 def ctrl_one(self, ip):
adminaeedddd2013-08-02 15:14:15 -0700296 '''
297 Sets all the switches to point to the supplied IP
298 '''
adminbae64d82013-08-01 10:50:15 -0700299 self.execute(cmd="~/ONOS/scripts/test-ctrl-one.sh "+ip, prompt="\$",timeout=10)
300
301 def ctrl_local(self):
adminaeedddd2013-08-02 15:14:15 -0700302 '''
303 Sets all the switches to point to the Controller on the same machine that they are running on.
304 '''
adminbae64d82013-08-01 10:50:15 -0700305 self.execute(cmd="~/ONOS/scripts/test-ctrl-local.sh ", prompt="\$",timeout=10)
306
307 # def verifySSH(self,**connectargs):
308 # response = self.execute(cmd="h1 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
309 # response = self.execute(cmd="h4 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
310 # for key in connectargs:
311 # vars(self)[key] = connectargs[key]
312 # response = self.execute(cmd="xterm h1 h4 ",prompt="mininet>",timeout=10)
313 # import time
314 # time.sleep(20)
315 # if self.flag == 0:
316 # self.flag = 1
317 # return main.FALSE
318 # else :
319 # return main.TRUE
320 #
321 # def getMacAddress(self,host):
322 # '''
323 # Verifies the host's ip configured or not.
324 # '''
325 # if self.handle :
326 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
327
328 # pattern = "HWaddr\s(((\d|\w)+:)+(\d|\w))"
329 # mac_address_search = re.search(pattern, response)
330 # main.log.info("Mac-Address of Host "+host +" is "+mac_address_search.group(1))
331 # return mac_address_search.group(1)
332 # else :
333 # main.log.error("Connection failed to the host")
334 # def getIPAddress(self,host):
335 # '''
336 # Verifies the host's ip configured or not.
337 # '''
338 # if self.handle :
339 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
340
341 # pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
342 # ip_address_search = re.search(pattern, response)
343 # main.log.info("IP-Address of Host "+host +" is "+ip_address_search.group(1))
344 # return ip_address_search.group(1)
345 # else :
346 # main.log.error("Connection failed to the host")
347 #
348 # def dump(self):
349 # main.log.info("Dump node info")
350 # self.execute(cmd = 'dump',prompt = 'mininet>',timeout = 10)
351 # return main.TRUE
352 #
353 # def intfs(self):
354 # main.log.info("List interfaces")
355 # self.execute(cmd = 'intfs',prompt = 'mininet>',timeout = 10)
356 # return main.TRUE
357 #
358 # def net(self):
359 # main.log.info("List network connections")
360 # self.execute(cmd = 'net',prompt = 'mininet>',timeout = 10)
361 # return main.TRUE
362 #
363 # def iperf(self):
364 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
365 # self.execute(cmd = 'iperf',prompt = 'mininet>',timeout = 10)
366 # return main.TRUE
367 #
368 # def iperfudp(self):
369 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
370 # self.execute(cmd = 'iperfudp',prompt = 'mininet>',timeout = 10)
371 # return main.TRUE
372 #
373 # def nodes(self):
374 # main.log.info("List all nodes.")
375 # self.execute(cmd = 'nodes',prompt = 'mininet>',timeout = 10)
376 # return main.TRUE
377 #
378 # def pingpair(self):
379 # main.log.infoe("Ping between first two hosts")
380 # self.execute(cmd = 'pingpair',prompt = 'mininet>',timeout = 20)
381 #
382 # if utilities.assert_matches(expect='0% packet loss',actual=response,onpass="No Packet loss",onfail="Hosts not reachable"):
383 # main.log.info("Ping between two hosts SUCCESS")
384 # main.last_result = main.TRUE
385 # return main.TRUE
386 # else :
387 # main.log.error("PACKET LOST, HOSTS NOT REACHABLE")
388 # main.last_result = main.FALSE
389 # return main.FALSE
390 #
391 # def link(self,**linkargs):
392 # '''
393 # Bring link(s) between two nodes up or down
394 # '''
395 # main.log.info('Bring link(s) between two nodes up or down')
396 # args = utilities.parse_args(["END1","END2","OPTION"],**linkargs)
397 # end1 = args["END1"] if args["END1"] != None else ""
398 # end2 = args["END2"] if args["END2"] != None else ""
399 # option = args["OPTION"] if args["OPTION"] != None else ""
400 # command = "link "+str(end1) + " " + str(end2)+ " " + str(option)
401 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
402 # return main.TRUE
403 #
404
405 # def dpctl(self,**dpctlargs):
406 # '''
407 # Run dpctl command on all switches.
408 # '''
409 # main.log.info('Run dpctl command on all switches')
410 # args = utilities.parse_args(["CMD","ARGS"],**dpctlargs)
411 # cmd = args["CMD"] if args["CMD"] != None else ""
412 # cmdargs = args["ARGS"] if args["ARGS"] != None else ""
413 # command = "dpctl "+cmd + " " + str(cmdargs)
414 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
415 # return main.TRUE
416 #
417 #
418 # def get_version(self):
419 # file_input = path+'/lib/Mininet/INSTALL'
420 # version = super(Mininet, self).get_version()
421 # pattern = 'Mininet\s\w\.\w\.\w\w*'
422 # for line in open(file_input,'r').readlines():
423 # result = re.match(pattern, line)
424 # if result:
425 # version = result.group(0)
426 #
427 #
428 # return version
admin2a9548d2014-06-17 14:08:07 -0700429 def start_tcpdump(self, filename, intf = "eth0", port = "port 6633"):
430 '''
431 Runs tpdump on an intferface and saves the file
432 intf can be specified, or the default eth0 is used
433 '''
434 try:
435 self.handle.sendline("")
436 self.handle.sendline("sudo tcpdump -n -i "+ intf + " " + port + " -w " + filename.strip() + " &")
437 self.handle.sendline("")
438 self.handle.sendline("")
439 i=self.handle.expect(['No\ssuch\device','listening\son',pexpect.TIMEOUT,"\$"],timeout=10)
440 main.log.warn(self.handle.before + self.handle.after)
441 if i == 0:
442 main.log.error(self.name + ": tcpdump - No such device exists. tcpdump attempted on: " + intf)
443 return main.FALSE
444 elif i == 1:
445 main.log.info(self.name + ": tcpdump started on " + intf)
446 return main.TRUE
447 elif i == 2:
448 main.log.error(self.name + ": tcpdump command timed out! Check interface name, given interface was: " + intf)
449 return main.FALSE
450 elif i ==3:
451 main.log.info(self.name +": " + self.handle.before)
452 return main.TRUE
453 else:
454 main.log.error(self.name + ": tcpdump - unexpected response")
455 return main.FALSE
456 except pexpect.EOF:
457 main.log.error(self.name + ": EOF exception found")
458 main.log.error(self.name + ": " + self.handle.before)
459 main.cleanup()
460 main.exit()
461 except:
462 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
463 main.log.error( traceback.print_exc() )
464 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
465 main.cleanup()
466 main.exit()
467
468 def stop_tcpdump(self):
469 "pkills tcpdump"
470 try:
471 self.handle.sendline("sudo pkill tcpdump")
472 self.handle.sendline("")
473 self.handle.sendline("")
474 self.handle.expect("\$")
475 except pexpect.EOF:
476 main.log.error(self.name + ": EOF exception found")
477 main.log.error(self.name + ": " + self.handle.before)
478 main.cleanup()
479 main.exit()
480 except:
481 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
482 main.log.error( traceback.print_exc() )
483 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
484 main.cleanup()
485 main.exit()
486
shahshreya4d79aab2014-11-07 15:20:41 -0800487 def run_optical_mn_script(self):
shahshreya28bb18e2014-11-17 10:26:23 -0800488 '''
489 This function is only meant for Packet Optical.
490 It runs the python script "optical.py" to create the packet layer(mn)
491 topology
492 '''
493 try:
494 self.handle.sendline("")
495 self.handle.expect("\$")
496 self.handle.sendline("cd ~")
497 self.handle.expect("\$")
498 self.handle.sendline("sudo python optical.py")
499 self.handle.expect(">")
500 return main.TRUE
501 except pexpect.EOF:
502 main.log.error(self.name + ": EOF exception found")
503 main.log.error(self.name + ": " + self.handle.before)
504 return main.FALSE
505
admin680b78c2014-08-08 11:46:45 -0700506 def del_switch(self,sw):
507 self.handle.sendline("")
508 self.handle.expect("\$")
509 self.handle.sendline("sudo ovs-vsctl del-br "+sw)
510 self.handle.expect("\$")
511 return main.TRUE
admin2a9548d2014-06-17 14:08:07 -0700512
admin680b78c2014-08-08 11:46:45 -0700513 def add_switch(self,sw):
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700514 #FIXME: Remove hardcoded number of ports
admin680b78c2014-08-08 11:46:45 -0700515 self.handle.sendline("")
516 self.handle.expect("\$")
517 self.handle.sendline("sudo ovs-vsctl add-br "+sw)
518 self.handle.expect("\$")
519 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth1")
520 self.handle.expect("\$")
521 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth2")
522 self.handle.expect("\$")
523 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth3")
524 self.handle.expect("\$")
525 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth4")
526 self.handle.expect("\$")
527 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth5")
528 self.handle.expect("\$")
529 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth6")
530 self.handle.expect("\$")
531 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth7")
532 self.handle.expect("\$")
533 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth8")
534 self.handle.expect("\$")
535 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth9")
536 self.handle.expect("\$")
537 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth10")
538 self.handle.expect("\$")
539 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth11")
540 self.handle.expect("\$")
541 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth12")
542 self.handle.expect("\$")
543 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth13")
544 self.handle.expect("\$")
545 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth14")
546 self.handle.expect("\$")
admin2a9548d2014-06-17 14:08:07 -0700547
adminbae64d82013-08-01 10:50:15 -0700548
549 def disconnect(self):
adminaeedddd2013-08-02 15:14:15 -0700550 '''
551 Called at the end of the test to disconnect the handle.
552 '''
adminbae64d82013-08-01 10:50:15 -0700553 response = ''
554 #print "Disconnecting Mininet"
555 if self.handle:
556 self.handle.sendline("exit")
557 self.handle.expect("exit")
558 self.handle.expect("(.*)")
559 response = self.handle.before
560
561 else :
562 main.log.error("Connection failed to the host")
563 response = main.FALSE
564 return response
565
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700566 def get_flowTable(self, protoVersion, sw):
santhosh9da93892014-07-28 14:11:19 -0700567 self.handle.sendline("cd")
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700568 #self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
569 print "cd expect status: "
570 print self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
Jon Hall6c794f32014-08-14 13:33:13 -0700571 #TODO: Write seperate versions of the function for this, possibly a string that tells it which switch is in use?
572 #For 1.0 version of OVS
573 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 }' |sort -n -k1"
574 #for 1.3 version of OVS
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700575 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $3 $7 $8}' |sort -n -k1"
576 #NOTE: Use format to force consistent flow table output across versions
577 if protoVersion==1.0:
578 command = "sudo ovs-ofctl dump-flows " + sw + " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 $7 $8}' |sort -n -k1"
579 self.handle.sendline(command)
580 self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
581 self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
582 response = self.handle.before
583 #print "response=", response
584 return response
585 elif protoVersion==1.3:
586 command = "sudo ovs-ofctl dump-flows " + sw + " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}' |sort -n -k1"
587 self.handle.sendline(command)
588 #print "ovs-vsctl Command sent status."
589 #self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
590 #print "sort return status: "
591 #print self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
592 #print self.handle.before
593 self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
594 #print "OFPST_FLOW expected status: "
595 #print self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
596 #print self.handle.before
597 response = self.handle.before
598 #print "response=", response
599 return response
santhosh19fd8032014-07-29 11:56:17 -0700600
601
602 def flow_comp(self,flow1,flow2):
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700603 #print "Inside flow compare function"
604 #print "Flow1 Table:"
605 #for flow in flow1:
606 #print flow1
607 #print "Flow2 Table"
608 #for flow in flow2:
609 #print flow2
610
santhosh19fd8032014-07-29 11:56:17 -0700611 if flow1==flow2:
612 return main.TRUE
613 else:
Jon Hall6c794f32014-08-14 13:33:13 -0700614 main.log.info("Flow tables do not match, printing tables:")
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700615 #main.log.info("Flow Table 1:")
616 #main.log.info(flow1)
617 #main.log.info("Flow Table 2:")
618 #main.log.info(flow2)
santhosh19fd8032014-07-29 11:56:17 -0700619 return main.FALSE
620
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700621 def setIpTablesOUTPUT(self, dst_ip, dst_port, action='add', packet_type='tcp',rule='DROP'):
622 '''
623 Description:
624 add or remove iptables rule to DROP (default) packets from specific IP and PORT
625 Usage:
626 * specify action ('add' or 'remove')
627 when removing, pass in the same argument as you would add. It will
628 delete that specific rule.
629 * specify the destination ip to block with dst_ip
630 * specify destination port to block to dst_port
631 * optional packet type to block (default tcp)
632 * optional iptables rule (default DROP)
633 WARNING:
634 * This function uses root privilege iptables command which may result in
635 unwanted network errors. USE WITH CAUTION
636 '''
637 import re
638 import time
639
640 #NOTE*********
641 # The strict checking methods of this driver function is intentional
642 # to discourage any misuse or error of iptables, which can cause
643 # severe network errors
644 #*************
645
646 #NOTE: Sleep needed to give some time for rule to be added and registered
647 # to the instance
648 time.sleep(5)
649
650 action_type = action.lower()
651 if action_type != 'add' and action_type !='remove':
652 main.log.error("Invalid action type. 'add' or 'remove' table rule")
653 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
654 #NOTE: Currently only supports rules DROP, ACCEPT, and LOG
655 main.log.error("Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only.")
656 return
657 return
658 else:
659
660 #If there is no existing rule in the iptables, we will see an
661 #'iptables:'... message. We expect to see this message.
662 #Otherwise, if there IS an existing rule, we will get the prompt
663 # back, hence why we expect $ for remove type. We want to remove
664 # an already existing rule
665
666 if action_type == 'add':
667 #NOTE: "iptables:" expect is a result of return from the command
668 # iptables -C ...
669 # Any changes by the iptables command return string
670 # will result in failure of the function. (deemed unlikely
671 # at the time of writing this function)
672 #Check for existing rules on current input
673 self.handle.sendline("")
674 self.handle.expect("\$")
675 self.handle.sendline("sudo iptables -C OUTPUT -p "+str(packet_type)+
676 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
677 i = self.handle.expect(["iptables:", "\$"])
678 print i
679 print self.handle.before
680 print "after: "
681 print self.handle.after
682
683 elif action_type == 'remove':
684 #Check for existing rules on current input
685 self.handle.sendline("")
686 self.handle.expect("\$")
687 self.handle.sendline("sudo iptables -C OUTPUT -p "+str(packet_type)+
688 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
689 self.handle.expect("\$")
690 print "before: "
691 print self.handle.before
692 actual_string = self.handle.after
693 expect_string = "iptables:"
694 print "Actual String:"
695 print actual_string
696
697 if re.search(expect_string, actual_string):
698 match_result = main.TRUE
699 else:
700 match_result = main.FALSE
701 #If match_result is main.TRUE, it means there is no matching rule.
702
703 #If tables does not exist and expected prompt is returned, go ahead and
704 #add iptables rule
705 if match_result == main.TRUE:
706 #Ensure action type is add
707 if action_type == 'add':
708 #-A is the 'append' action of iptables
709 action_add = '-A'
710 try:
711 self.handle.sendline("")
712 self.handle.sendline("sudo iptables "+action_add+" OUTPUT -p "+str(packet_type)+
713 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
714
715 info_string = "Rules added to "+str(self.name)
716 info_string += "iptable rule added to block IP: "+str(dst_ip)
717 info_string += "Port: "+str(dst_port)+" Rule: "+str(rule)
718
719 main.log.info(info_string)
720
721 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
722 except pexpect.TIMEOUT:
723 main.log.error(self.name + ": Timeout exception in setIpTables function")
724 except:
725 main.log.error( traceback.print_exc())
726 main.cleanup()
727 main.exit()
728 else:
729 main.log.error("Given rule already exists, but attempted to add it")
730 #If match_result is 0, it means there IS a matching rule provided
731 elif match_result == main.FALSE:
732 #Ensure action type is remove
733 if action_type == 'remove':
734 #-D is the 'delete' rule of iptables
735 action_remove = '-D'
736 try:
737 self.handle.sendline("")
738 #Delete a specific rule specified into the function
739 self.handle.sendline("sudo iptables "+action_remove+" OUTPUT -p "+str(packet_type)+
740 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
741
742 info_string = "Rules removed from "+str(self.name)
743 info_string += " iptables rule removed from blocking IP: "+str(dst_ip)
744 info_string += " Port: "+str(dst_port)+" Rule: "+str(rule)
745
746 main.log.info(info_string)
747
748 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
749 except pexpect.TIMEOUT:
750 main.log.error(self.name + ": Timeout exception in setIpTables function")
751 except:
752 main.log.error( traceback.print_exc())
753 main.cleanup()
754 main.exit()
755 else:
756 main.log.error("Given rule does not exist, but attempted to remove it")
757 else:
758 #NOTE: If a bad usage of this function occurs, exit the entire test
759 main.log.error("Bad rule given for iptables. Exiting...")
760 main.cleanup()
761 main.exit()
762
763
adminbae64d82013-08-01 10:50:15 -0700764if __name__ != "__main__":
765 import sys
766 sys.modules[__name__] = RemoteMininetDriver()