blob: 5d2a7a3df04278416da65ba56f23f63a8b64a1f0 [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:
Jon Hall2ef1e9e2014-11-18 14:27:05 -050095 main.log.error("Error, unexpected output in the ping file")
96 main.log.warn( outputs )
shahshreyaf4d4d0c2014-10-10 12:11:10 -070097 return main.TRUE
98
admin98ad0092014-07-23 16:51:07 -070099
100
adminbae64d82013-08-01 10:50:15 -0700101 def pingLong(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700102 '''
103 Starts a continuous ping on the mininet host outputing to a file in the /tmp dir.
104 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700105 self.handle.sendline("")
106 self.handle.expect("\$")
admin98ad0092014-07-23 16:51:07 -0700107 args = utilities.parse_args(["SRC","TARGET","PINGTIME"],**pingParams)
Jon Hall6c794f32014-08-14 13:33:13 -0700108 precmd = "sudo rm /tmp/ping." + args["SRC"]
admin530b4c92013-08-14 16:54:35 -0700109 self.execute(cmd=precmd,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700110 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 -0700111 main.log.info( command )
112 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700113 self.handle.sendline("")
114 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700115 return main.TRUE
116
117 def pingstatus(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700118 '''
119 Tails the respective ping output file and check that there is a moving "64 bytes"
120 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700121 self.handle.sendline("")
122 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700123 args = utilities.parse_args(["SRC"],**pingParams)
124 self.handle.sendline("tail /tmp/ping." + args["SRC"])
125 self.handle.expect("tail")
126 self.handle.expect("\$")
127 result = self.handle.before + self.handle.after
Jon Hall6c794f32014-08-14 13:33:13 -0700128 self.handle.sendline("")
129 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700130 if re.search('Unreachable', result ):
131 main.log.info("Unreachable found in ping logs...")
132 return main.FALSE
133 elif re.search('64\sbytes', result):
134 main.log.info("Pings look good")
135 return main.TRUE
136 else:
137 main.log.info("No, or faulty ping data...")
138 return main.FALSE
139
Jon Hall6c794f32014-08-14 13:33:13 -0700140 def pingKill(self, testONUser, testONIP):
adminaeedddd2013-08-02 15:14:15 -0700141 '''
142 Kills all continuous ping processes.
143 Then copies all the ping files to the TestStation.
144 '''
145 import time
Jon Hall6c794f32014-08-14 13:33:13 -0700146 self.handle.sendline("")
147 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700148 command = "sudo kill -SIGINT `pgrep ping`"
adminbae64d82013-08-01 10:50:15 -0700149 main.log.info( command )
150 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700151 #Commenting out in case TestON and MN are on the same machine. scp overrights the file anyways
152 #main.log.info( "Removing old ping data" )
153 #command = "rm /tmp/ping.*"
154 #os.popen(command)
155 #time.sleep(2)
adminbae64d82013-08-01 10:50:15 -0700156 main.log.info( "Transferring ping files to TestStation" )
Jon Hall6c794f32014-08-14 13:33:13 -0700157 command = "scp /tmp/ping.* "+ str(testONUser) + "@" + str(testONIP) + ":/tmp/"
adminbae64d82013-08-01 10:50:15 -0700158 self.execute(cmd=command,prompt="100%",timeout=20)
Jon Hall2ef1e9e2014-11-18 14:27:05 -0500159 #Make sure the output is cleared
160 self.handle.sendline("")
161 self.handle.expect("\$")
162 self.handle.sendline("")
163 self.handle.expect("\$")
Jon Hall6c794f32014-08-14 13:33:13 -0700164 self.handle.sendline("")
165 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700166 return main.TRUE
167
168 def pingLongKill(self):
169 import time
Jon Hall6c794f32014-08-14 13:33:13 -0700170 self.handle.sendline("")
171 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700172 command = "sudo kill -SIGING `pgrep ping`"
173 main.log.info(command)
174 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700175 self.handle.sendline("")
176 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700177 return main.TRUE
shahshreya28bb18e2014-11-17 10:26:23 -0800178
179 def pingHostOptical(self,**pingParams):
180 '''
181 This function is only for Packey Optical related ping
182 Use the next pingHost() function for all normal scenarios)
183 Ping from one mininet host to another
184 Currently the only supported Params: SRC and TARGET
185 '''
186 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
187 #command = args["SRC"] + " ping -" + args["CONTROLLER"] + " " +args ["TARGET"]
188 command = args["SRC"] + " ping "+args ["TARGET"]+" -c 1 -i 1 -W 8"
189 try:
190 main.log.warn("Sending: " + command)
191 #response = self.execute(cmd=command,prompt="mininet",timeout=10 )
192 self.handle.sendline(command)
193 i = self.handle.expect([command,pexpect.TIMEOUT])
194 if i == 1:
195 main.log.error(self.name + ": timeout when waiting for response from mininet")
196 main.log.error("response: " + str(self.handle.before))
197 i = self.handle.expect(["mininet>",pexpect.TIMEOUT])
198 if i == 1:
199 main.log.error(self.name + ": timeout when waiting for response from mininet")
200 main.log.error("response: " + str(self.handle.before))
201 response = self.handle.before
202 except pexpect.EOF:
203 main.log.error(self.name + ": EOF exception found")
204 main.log.error(self.name + ": " + self.handle.before)
205 main.cleanup()
206 main.exit()
207 main.log.info(self.name+": Ping Response: "+ response )
208 #if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
209 if re.search(',\s0\%\spacket\sloss',response):
210 main.log.info(self.name+": no packets lost, host is reachable")
211 main.last_result = main.TRUE
212 return main.TRUE
213 else :
214 main.log.error(self.name+": PACKET LOST, HOST IS NOT REACHABLE")
215 main.last_result = main.FALSE
216 return main.FALSE
217
218
219 def pingall(self):
220 '''
221 Verifies the reachability of the hosts using pingall command.
222 This function is required by Packey Optical test
223 '''
224 if self.handle :
225 main.log.info(self.name+": Checking reachabilty to the hosts using pingall")
226 try:
227 response = self.execute(cmd="pingall",prompt="mininet>",timeout=120)
228 print "response: " + str(response)
229 except pexpect.EOF:
230 main.log.error(self.name + ": EOF exception found")
231 main.log.error(self.name + ": " + self.handle.before)
232 pattern = 'Results\:\s0\%\sdropped\s'
233 if re.search(pattern,response):
234 main.log.info(self.name+": All hosts are reachable")
235 return main.TRUE
236 else:
237 main.log.error(self.name+": Unable to reach all the hosts")
238 return main.FALSE
239 else :
240 main.log.error(self.name+": Connection failed to the host")
241 return main.FALSE
242
243
244
245
adminbae64d82013-08-01 10:50:15 -0700246 def pingHost(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700247 '''
248 Pings between two hosts on remote mininet
249 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700250 self.handle.sendline("")
251 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700252 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
shahshreya28bb18e2014-11-17 10:26:23 -0800253 #command = "mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -c 4 -W 1 -i .2"
adminbae64d82013-08-01 10:50:15 -0700254 command = "mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -c 4 -W 1 -i .2"
255 main.log.info ( command )
256 response = self.execute(cmd=command,prompt="rtt",timeout=10 )
shahshreya28bb18e2014-11-17 10:26:23 -0800257 #self.handle.sendline("")
258 #self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700259 if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
260 main.log.info("NO PACKET LOSS, HOST IS REACHABLE")
261 main.last_result = main.TRUE
262 return main.TRUE
263 else :
264 main.log.error("PACKET LOST, HOST IS NOT REACHABLE")
265 main.last_result = main.FALSE
266 return main.FALSE
267
268
269 def checknum(self,num):
270 '''
adminaeedddd2013-08-02 15:14:15 -0700271 Verifies the correct number of switches are running
adminbae64d82013-08-01 10:50:15 -0700272 '''
273 if self.handle :
274 self.handle.sendline("")
275 self.handle.expect("\$")
276 self.handle.sendline('ifconfig -a | grep "sw.. " | wc -l')
277 self.handle.expect("wc")
278 self.handle.expect("\$")
279 response = self.handle.before
280 self.handle.sendline('ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l')
281 self.handle.expect("color")
282 self.handle.expect("\$")
283 response2 = self.handle.before
284
285 if re.search(num, response):
286 if re.search(num, response2):
287 return main.TRUE
288 else:
289 return main.FALSE
290 else:
291 return main.FALSE
292 else :
293 main.log.error("Connection failed to the host")
294
295 def ctrl_none(self):
adminaeedddd2013-08-02 15:14:15 -0700296 '''
297 Sets all the switches to no controllers.
298 '''
adminbae64d82013-08-01 10:50:15 -0700299 self.execute(cmd="~/ONOS/scripts/test-ctrl-none.sh", prompt="\$",timeout=10)
300
301 def ctrl_one(self, ip):
adminaeedddd2013-08-02 15:14:15 -0700302 '''
303 Sets all the switches to point to the supplied IP
304 '''
adminbae64d82013-08-01 10:50:15 -0700305 self.execute(cmd="~/ONOS/scripts/test-ctrl-one.sh "+ip, prompt="\$",timeout=10)
306
307 def ctrl_local(self):
adminaeedddd2013-08-02 15:14:15 -0700308 '''
309 Sets all the switches to point to the Controller on the same machine that they are running on.
310 '''
adminbae64d82013-08-01 10:50:15 -0700311 self.execute(cmd="~/ONOS/scripts/test-ctrl-local.sh ", prompt="\$",timeout=10)
312
313 # def verifySSH(self,**connectargs):
314 # response = self.execute(cmd="h1 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
315 # response = self.execute(cmd="h4 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
316 # for key in connectargs:
317 # vars(self)[key] = connectargs[key]
318 # response = self.execute(cmd="xterm h1 h4 ",prompt="mininet>",timeout=10)
319 # import time
320 # time.sleep(20)
321 # if self.flag == 0:
322 # self.flag = 1
323 # return main.FALSE
324 # else :
325 # return main.TRUE
326 #
327 # def getMacAddress(self,host):
328 # '''
329 # Verifies the host's ip configured or not.
330 # '''
331 # if self.handle :
332 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
333
334 # pattern = "HWaddr\s(((\d|\w)+:)+(\d|\w))"
335 # mac_address_search = re.search(pattern, response)
336 # main.log.info("Mac-Address of Host "+host +" is "+mac_address_search.group(1))
337 # return mac_address_search.group(1)
338 # else :
339 # main.log.error("Connection failed to the host")
340 # def getIPAddress(self,host):
341 # '''
342 # Verifies the host's ip configured or not.
343 # '''
344 # if self.handle :
345 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
346
347 # pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
348 # ip_address_search = re.search(pattern, response)
349 # main.log.info("IP-Address of Host "+host +" is "+ip_address_search.group(1))
350 # return ip_address_search.group(1)
351 # else :
352 # main.log.error("Connection failed to the host")
353 #
354 # def dump(self):
355 # main.log.info("Dump node info")
356 # self.execute(cmd = 'dump',prompt = 'mininet>',timeout = 10)
357 # return main.TRUE
358 #
359 # def intfs(self):
360 # main.log.info("List interfaces")
361 # self.execute(cmd = 'intfs',prompt = 'mininet>',timeout = 10)
362 # return main.TRUE
363 #
364 # def net(self):
365 # main.log.info("List network connections")
366 # self.execute(cmd = 'net',prompt = 'mininet>',timeout = 10)
367 # return main.TRUE
368 #
369 # def iperf(self):
370 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
371 # self.execute(cmd = 'iperf',prompt = 'mininet>',timeout = 10)
372 # return main.TRUE
373 #
374 # def iperfudp(self):
375 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
376 # self.execute(cmd = 'iperfudp',prompt = 'mininet>',timeout = 10)
377 # return main.TRUE
378 #
379 # def nodes(self):
380 # main.log.info("List all nodes.")
381 # self.execute(cmd = 'nodes',prompt = 'mininet>',timeout = 10)
382 # return main.TRUE
383 #
384 # def pingpair(self):
385 # main.log.infoe("Ping between first two hosts")
386 # self.execute(cmd = 'pingpair',prompt = 'mininet>',timeout = 20)
387 #
388 # if utilities.assert_matches(expect='0% packet loss',actual=response,onpass="No Packet loss",onfail="Hosts not reachable"):
389 # main.log.info("Ping between two hosts SUCCESS")
390 # main.last_result = main.TRUE
391 # return main.TRUE
392 # else :
393 # main.log.error("PACKET LOST, HOSTS NOT REACHABLE")
394 # main.last_result = main.FALSE
395 # return main.FALSE
396 #
397 # def link(self,**linkargs):
398 # '''
399 # Bring link(s) between two nodes up or down
400 # '''
401 # main.log.info('Bring link(s) between two nodes up or down')
402 # args = utilities.parse_args(["END1","END2","OPTION"],**linkargs)
403 # end1 = args["END1"] if args["END1"] != None else ""
404 # end2 = args["END2"] if args["END2"] != None else ""
405 # option = args["OPTION"] if args["OPTION"] != None else ""
406 # command = "link "+str(end1) + " " + str(end2)+ " " + str(option)
407 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
408 # return main.TRUE
409 #
410
411 # def dpctl(self,**dpctlargs):
412 # '''
413 # Run dpctl command on all switches.
414 # '''
415 # main.log.info('Run dpctl command on all switches')
416 # args = utilities.parse_args(["CMD","ARGS"],**dpctlargs)
417 # cmd = args["CMD"] if args["CMD"] != None else ""
418 # cmdargs = args["ARGS"] if args["ARGS"] != None else ""
419 # command = "dpctl "+cmd + " " + str(cmdargs)
420 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
421 # return main.TRUE
422 #
423 #
424 # def get_version(self):
425 # file_input = path+'/lib/Mininet/INSTALL'
426 # version = super(Mininet, self).get_version()
427 # pattern = 'Mininet\s\w\.\w\.\w\w*'
428 # for line in open(file_input,'r').readlines():
429 # result = re.match(pattern, line)
430 # if result:
431 # version = result.group(0)
432 #
433 #
434 # return version
admin2a9548d2014-06-17 14:08:07 -0700435 def start_tcpdump(self, filename, intf = "eth0", port = "port 6633"):
436 '''
437 Runs tpdump on an intferface and saves the file
438 intf can be specified, or the default eth0 is used
439 '''
440 try:
441 self.handle.sendline("")
442 self.handle.sendline("sudo tcpdump -n -i "+ intf + " " + port + " -w " + filename.strip() + " &")
443 self.handle.sendline("")
444 self.handle.sendline("")
445 i=self.handle.expect(['No\ssuch\device','listening\son',pexpect.TIMEOUT,"\$"],timeout=10)
446 main.log.warn(self.handle.before + self.handle.after)
447 if i == 0:
448 main.log.error(self.name + ": tcpdump - No such device exists. tcpdump attempted on: " + intf)
449 return main.FALSE
450 elif i == 1:
451 main.log.info(self.name + ": tcpdump started on " + intf)
452 return main.TRUE
453 elif i == 2:
454 main.log.error(self.name + ": tcpdump command timed out! Check interface name, given interface was: " + intf)
455 return main.FALSE
456 elif i ==3:
457 main.log.info(self.name +": " + self.handle.before)
458 return main.TRUE
459 else:
460 main.log.error(self.name + ": tcpdump - unexpected response")
461 return main.FALSE
462 except pexpect.EOF:
463 main.log.error(self.name + ": EOF exception found")
464 main.log.error(self.name + ": " + self.handle.before)
465 main.cleanup()
466 main.exit()
467 except:
468 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
469 main.log.error( traceback.print_exc() )
470 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
471 main.cleanup()
472 main.exit()
473
474 def stop_tcpdump(self):
475 "pkills tcpdump"
476 try:
477 self.handle.sendline("sudo pkill tcpdump")
478 self.handle.sendline("")
479 self.handle.sendline("")
480 self.handle.expect("\$")
481 except pexpect.EOF:
482 main.log.error(self.name + ": EOF exception found")
483 main.log.error(self.name + ": " + self.handle.before)
484 main.cleanup()
485 main.exit()
486 except:
487 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
488 main.log.error( traceback.print_exc() )
489 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
490 main.cleanup()
491 main.exit()
492
shahshreya4d79aab2014-11-07 15:20:41 -0800493 def run_optical_mn_script(self):
shahshreya28bb18e2014-11-17 10:26:23 -0800494 '''
495 This function is only meant for Packet Optical.
496 It runs the python script "optical.py" to create the packet layer(mn)
497 topology
498 '''
499 try:
500 self.handle.sendline("")
501 self.handle.expect("\$")
502 self.handle.sendline("cd ~")
503 self.handle.expect("\$")
504 self.handle.sendline("sudo python optical.py")
505 self.handle.expect(">")
506 return main.TRUE
507 except pexpect.EOF:
508 main.log.error(self.name + ": EOF exception found")
509 main.log.error(self.name + ": " + self.handle.before)
510 return main.FALSE
511
admin680b78c2014-08-08 11:46:45 -0700512 def del_switch(self,sw):
513 self.handle.sendline("")
514 self.handle.expect("\$")
515 self.handle.sendline("sudo ovs-vsctl del-br "+sw)
516 self.handle.expect("\$")
517 return main.TRUE
admin2a9548d2014-06-17 14:08:07 -0700518
admin680b78c2014-08-08 11:46:45 -0700519 def add_switch(self,sw):
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700520 #FIXME: Remove hardcoded number of ports
admin680b78c2014-08-08 11:46:45 -0700521 self.handle.sendline("")
522 self.handle.expect("\$")
523 self.handle.sendline("sudo ovs-vsctl add-br "+sw)
524 self.handle.expect("\$")
525 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth1")
526 self.handle.expect("\$")
527 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth2")
528 self.handle.expect("\$")
529 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth3")
530 self.handle.expect("\$")
531 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth4")
532 self.handle.expect("\$")
533 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth5")
534 self.handle.expect("\$")
535 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth6")
536 self.handle.expect("\$")
537 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth7")
538 self.handle.expect("\$")
539 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth8")
540 self.handle.expect("\$")
541 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth9")
542 self.handle.expect("\$")
543 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth10")
544 self.handle.expect("\$")
545 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth11")
546 self.handle.expect("\$")
547 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth12")
548 self.handle.expect("\$")
549 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth13")
550 self.handle.expect("\$")
551 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth14")
552 self.handle.expect("\$")
admin2a9548d2014-06-17 14:08:07 -0700553
adminbae64d82013-08-01 10:50:15 -0700554
555 def disconnect(self):
adminaeedddd2013-08-02 15:14:15 -0700556 '''
557 Called at the end of the test to disconnect the handle.
558 '''
adminbae64d82013-08-01 10:50:15 -0700559 response = ''
560 #print "Disconnecting Mininet"
561 if self.handle:
Jon Hall2ef1e9e2014-11-18 14:27:05 -0500562 self.handle.sendline("exit")
adminbae64d82013-08-01 10:50:15 -0700563 self.handle.expect("exit")
564 self.handle.expect("(.*)")
565 response = self.handle.before
566
567 else :
568 main.log.error("Connection failed to the host")
569 response = main.FALSE
Jon Hall2ef1e9e2014-11-18 14:27:05 -0500570 return response
adminbae64d82013-08-01 10:50:15 -0700571
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700572 def get_flowTable(self, protoVersion, sw):
Jon Hall2ef1e9e2014-11-18 14:27:05 -0500573 #TODO document usage
574 #FIXME: clean up print statements and such
santhosh9da93892014-07-28 14:11:19 -0700575 self.handle.sendline("cd")
Jon Hall2ef1e9e2014-11-18 14:27:05 -0500576 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
577 #print "cd expect status: "
578 #print self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
Jon Hall6c794f32014-08-14 13:33:13 -0700579 #TODO: Write seperate versions of the function for this, possibly a string that tells it which switch is in use?
580 #For 1.0 version of OVS
581 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 }' |sort -n -k1"
582 #for 1.3 version of OVS
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700583 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $3 $7 $8}' |sort -n -k1"
584 #NOTE: Use format to force consistent flow table output across versions
585 if protoVersion==1.0:
586 command = "sudo ovs-ofctl dump-flows " + sw + " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 $7 $8}' |sort -n -k1"
587 self.handle.sendline(command)
588 self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
589 self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
590 response = self.handle.before
591 #print "response=", response
592 return response
593 elif protoVersion==1.3:
594 command = "sudo ovs-ofctl dump-flows " + sw + " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}' |sort -n -k1"
595 self.handle.sendline(command)
596 #print "ovs-vsctl Command sent status."
597 #self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
598 #print "sort return status: "
599 #print self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
600 #print self.handle.before
601 self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
602 #print "OFPST_FLOW expected status: "
603 #print self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
604 #print self.handle.before
605 response = self.handle.before
606 #print "response=", response
607 return response
santhosh19fd8032014-07-29 11:56:17 -0700608
609
610 def flow_comp(self,flow1,flow2):
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700611 #print "Inside flow compare function"
612 #print "Flow1 Table:"
613 #for flow in flow1:
614 #print flow1
615 #print "Flow2 Table"
616 #for flow in flow2:
617 #print flow2
618
santhosh19fd8032014-07-29 11:56:17 -0700619 if flow1==flow2:
620 return main.TRUE
621 else:
Jon Hall6c794f32014-08-14 13:33:13 -0700622 main.log.info("Flow tables do not match, printing tables:")
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700623 #main.log.info("Flow Table 1:")
624 #main.log.info(flow1)
625 #main.log.info("Flow Table 2:")
626 #main.log.info(flow2)
santhosh19fd8032014-07-29 11:56:17 -0700627 return main.FALSE
628
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700629 def setIpTablesOUTPUT(self, dst_ip, dst_port, action='add', packet_type='tcp',rule='DROP'):
630 '''
631 Description:
632 add or remove iptables rule to DROP (default) packets from specific IP and PORT
633 Usage:
634 * specify action ('add' or 'remove')
635 when removing, pass in the same argument as you would add. It will
636 delete that specific rule.
637 * specify the destination ip to block with dst_ip
638 * specify destination port to block to dst_port
639 * optional packet type to block (default tcp)
640 * optional iptables rule (default DROP)
641 WARNING:
642 * This function uses root privilege iptables command which may result in
643 unwanted network errors. USE WITH CAUTION
644 '''
645 import re
646 import time
647
648 #NOTE*********
649 # The strict checking methods of this driver function is intentional
650 # to discourage any misuse or error of iptables, which can cause
651 # severe network errors
652 #*************
653
654 #NOTE: Sleep needed to give some time for rule to be added and registered
655 # to the instance
656 time.sleep(5)
657
658 action_type = action.lower()
659 if action_type != 'add' and action_type !='remove':
660 main.log.error("Invalid action type. 'add' or 'remove' table rule")
661 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
662 #NOTE: Currently only supports rules DROP, ACCEPT, and LOG
663 main.log.error("Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only.")
664 return
665 return
666 else:
667
668 #If there is no existing rule in the iptables, we will see an
669 #'iptables:'... message. We expect to see this message.
670 #Otherwise, if there IS an existing rule, we will get the prompt
671 # back, hence why we expect $ for remove type. We want to remove
672 # an already existing rule
673
674 if action_type == 'add':
675 #NOTE: "iptables:" expect is a result of return from the command
676 # iptables -C ...
677 # Any changes by the iptables command return string
678 # will result in failure of the function. (deemed unlikely
679 # at the time of writing this function)
680 #Check for existing rules on current input
681 self.handle.sendline("")
682 self.handle.expect("\$")
683 self.handle.sendline("sudo iptables -C OUTPUT -p "+str(packet_type)+
684 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
685 i = self.handle.expect(["iptables:", "\$"])
686 print i
687 print self.handle.before
688 print "after: "
689 print self.handle.after
690
691 elif action_type == 'remove':
692 #Check for existing rules on current input
693 self.handle.sendline("")
694 self.handle.expect("\$")
695 self.handle.sendline("sudo iptables -C OUTPUT -p "+str(packet_type)+
696 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
697 self.handle.expect("\$")
698 print "before: "
699 print self.handle.before
700 actual_string = self.handle.after
701 expect_string = "iptables:"
702 print "Actual String:"
703 print actual_string
704
705 if re.search(expect_string, actual_string):
706 match_result = main.TRUE
707 else:
708 match_result = main.FALSE
709 #If match_result is main.TRUE, it means there is no matching rule.
710
711 #If tables does not exist and expected prompt is returned, go ahead and
712 #add iptables rule
713 if match_result == main.TRUE:
714 #Ensure action type is add
715 if action_type == 'add':
716 #-A is the 'append' action of iptables
717 action_add = '-A'
718 try:
719 self.handle.sendline("")
720 self.handle.sendline("sudo iptables "+action_add+" OUTPUT -p "+str(packet_type)+
721 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
722
723 info_string = "Rules added to "+str(self.name)
724 info_string += "iptable rule added to block IP: "+str(dst_ip)
725 info_string += "Port: "+str(dst_port)+" Rule: "+str(rule)
726
727 main.log.info(info_string)
728
729 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
730 except pexpect.TIMEOUT:
731 main.log.error(self.name + ": Timeout exception in setIpTables function")
732 except:
733 main.log.error( traceback.print_exc())
734 main.cleanup()
735 main.exit()
736 else:
737 main.log.error("Given rule already exists, but attempted to add it")
738 #If match_result is 0, it means there IS a matching rule provided
739 elif match_result == main.FALSE:
740 #Ensure action type is remove
741 if action_type == 'remove':
742 #-D is the 'delete' rule of iptables
743 action_remove = '-D'
744 try:
745 self.handle.sendline("")
746 #Delete a specific rule specified into the function
747 self.handle.sendline("sudo iptables "+action_remove+" OUTPUT -p "+str(packet_type)+
748 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
749
750 info_string = "Rules removed from "+str(self.name)
751 info_string += " iptables rule removed from blocking IP: "+str(dst_ip)
752 info_string += " Port: "+str(dst_port)+" Rule: "+str(rule)
753
754 main.log.info(info_string)
755
756 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
757 except pexpect.TIMEOUT:
758 main.log.error(self.name + ": Timeout exception in setIpTables function")
759 except:
760 main.log.error( traceback.print_exc())
761 main.cleanup()
762 main.exit()
763 else:
764 main.log.error("Given rule does not exist, but attempted to remove it")
765 else:
766 #NOTE: If a bad usage of this function occurs, exit the entire test
767 main.log.error("Bad rule given for iptables. Exiting...")
768 main.cleanup()
769 main.exit()
770
771
adminbae64d82013-08-01 10:50:15 -0700772if __name__ != "__main__":
773 import sys
774 sys.modules[__name__] = RemoteMininetDriver()