blob: d6e839dceaca751bc50caddf9ed23875b0af55b2 [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
admin98ad0092014-07-23 16:51:07 -070094 return main.TRUE
95
96
adminbae64d82013-08-01 10:50:15 -070097 def pingLong(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -070098 '''
99 Starts a continuous ping on the mininet host outputing to a file in the /tmp dir.
100 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700101 self.handle.sendline("")
102 self.handle.expect("\$")
admin98ad0092014-07-23 16:51:07 -0700103 args = utilities.parse_args(["SRC","TARGET","PINGTIME"],**pingParams)
Jon Hall6c794f32014-08-14 13:33:13 -0700104 precmd = "sudo rm /tmp/ping." + args["SRC"]
admin530b4c92013-08-14 16:54:35 -0700105 self.execute(cmd=precmd,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700106 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 -0700107 main.log.info( command )
108 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700109 self.handle.sendline("")
110 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700111 return main.TRUE
112
113 def pingstatus(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700114 '''
115 Tails the respective ping output file and check that there is a moving "64 bytes"
116 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700117 self.handle.sendline("")
118 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700119 args = utilities.parse_args(["SRC"],**pingParams)
120 self.handle.sendline("tail /tmp/ping." + args["SRC"])
121 self.handle.expect("tail")
122 self.handle.expect("\$")
123 result = self.handle.before + self.handle.after
Jon Hall6c794f32014-08-14 13:33:13 -0700124 self.handle.sendline("")
125 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700126 if re.search('Unreachable', result ):
127 main.log.info("Unreachable found in ping logs...")
128 return main.FALSE
129 elif re.search('64\sbytes', result):
130 main.log.info("Pings look good")
131 return main.TRUE
132 else:
133 main.log.info("No, or faulty ping data...")
134 return main.FALSE
135
Jon Hall6c794f32014-08-14 13:33:13 -0700136 def pingKill(self, testONUser, testONIP):
adminaeedddd2013-08-02 15:14:15 -0700137 '''
138 Kills all continuous ping processes.
139 Then copies all the ping files to the TestStation.
140 '''
141 import time
Jon Hall6c794f32014-08-14 13:33:13 -0700142 self.handle.sendline("")
143 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700144 command = "sudo kill -SIGINT `pgrep ping`"
adminbae64d82013-08-01 10:50:15 -0700145 main.log.info( command )
146 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700147 #Commenting out in case TestON and MN are on the same machine. scp overrights the file anyways
148 #main.log.info( "Removing old ping data" )
149 #command = "rm /tmp/ping.*"
150 #os.popen(command)
151 #time.sleep(2)
adminbae64d82013-08-01 10:50:15 -0700152 main.log.info( "Transferring ping files to TestStation" )
Jon Hall6c794f32014-08-14 13:33:13 -0700153 command = "scp /tmp/ping.* "+ str(testONUser) + "@" + str(testONIP) + ":/tmp/"
adminbae64d82013-08-01 10:50:15 -0700154 self.execute(cmd=command,prompt="100%",timeout=20)
Jon Hall6c794f32014-08-14 13:33:13 -0700155 self.handle.sendline("")
156 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700157 return main.TRUE
158
159 def pingLongKill(self):
160 import time
Jon Hall6c794f32014-08-14 13:33:13 -0700161 self.handle.sendline("")
162 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700163 command = "sudo kill -SIGING `pgrep ping`"
164 main.log.info(command)
165 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700166 self.handle.sendline("")
167 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700168 return main.TRUE
169
170 def pingHost(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700171 '''
172 Pings between two hosts on remote mininet
173 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700174 self.handle.sendline("")
175 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700176 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
177 command = "mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -c 4 -W 1 -i .2"
178 main.log.info ( command )
179 response = self.execute(cmd=command,prompt="rtt",timeout=10 )
Jon Hall6c794f32014-08-14 13:33:13 -0700180 self.handle.sendline("")
181 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700182 if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
183 main.log.info("NO PACKET LOSS, HOST IS REACHABLE")
184 main.last_result = main.TRUE
185 return main.TRUE
186 else :
187 main.log.error("PACKET LOST, HOST IS NOT REACHABLE")
188 main.last_result = main.FALSE
189 return main.FALSE
190
191
192 def checknum(self,num):
193 '''
adminaeedddd2013-08-02 15:14:15 -0700194 Verifies the correct number of switches are running
adminbae64d82013-08-01 10:50:15 -0700195 '''
196 if self.handle :
197 self.handle.sendline("")
198 self.handle.expect("\$")
199 self.handle.sendline('ifconfig -a | grep "sw.. " | wc -l')
200 self.handle.expect("wc")
201 self.handle.expect("\$")
202 response = self.handle.before
203 self.handle.sendline('ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l')
204 self.handle.expect("color")
205 self.handle.expect("\$")
206 response2 = self.handle.before
207
208 if re.search(num, response):
209 if re.search(num, response2):
210 return main.TRUE
211 else:
212 return main.FALSE
213 else:
214 return main.FALSE
215 else :
216 main.log.error("Connection failed to the host")
217
218 def ctrl_none(self):
adminaeedddd2013-08-02 15:14:15 -0700219 '''
220 Sets all the switches to no controllers.
221 '''
adminbae64d82013-08-01 10:50:15 -0700222 self.execute(cmd="~/ONOS/scripts/test-ctrl-none.sh", prompt="\$",timeout=10)
223
224 def ctrl_one(self, ip):
adminaeedddd2013-08-02 15:14:15 -0700225 '''
226 Sets all the switches to point to the supplied IP
227 '''
adminbae64d82013-08-01 10:50:15 -0700228 self.execute(cmd="~/ONOS/scripts/test-ctrl-one.sh "+ip, prompt="\$",timeout=10)
229
230 def ctrl_local(self):
adminaeedddd2013-08-02 15:14:15 -0700231 '''
232 Sets all the switches to point to the Controller on the same machine that they are running on.
233 '''
adminbae64d82013-08-01 10:50:15 -0700234 self.execute(cmd="~/ONOS/scripts/test-ctrl-local.sh ", prompt="\$",timeout=10)
235
236 # def verifySSH(self,**connectargs):
237 # response = self.execute(cmd="h1 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
238 # response = self.execute(cmd="h4 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
239 # for key in connectargs:
240 # vars(self)[key] = connectargs[key]
241 # response = self.execute(cmd="xterm h1 h4 ",prompt="mininet>",timeout=10)
242 # import time
243 # time.sleep(20)
244 # if self.flag == 0:
245 # self.flag = 1
246 # return main.FALSE
247 # else :
248 # return main.TRUE
249 #
250 # def getMacAddress(self,host):
251 # '''
252 # Verifies the host's ip configured or not.
253 # '''
254 # if self.handle :
255 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
256
257 # pattern = "HWaddr\s(((\d|\w)+:)+(\d|\w))"
258 # mac_address_search = re.search(pattern, response)
259 # main.log.info("Mac-Address of Host "+host +" is "+mac_address_search.group(1))
260 # return mac_address_search.group(1)
261 # else :
262 # main.log.error("Connection failed to the host")
263 # def getIPAddress(self,host):
264 # '''
265 # Verifies the host's ip configured or not.
266 # '''
267 # if self.handle :
268 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
269
270 # pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
271 # ip_address_search = re.search(pattern, response)
272 # main.log.info("IP-Address of Host "+host +" is "+ip_address_search.group(1))
273 # return ip_address_search.group(1)
274 # else :
275 # main.log.error("Connection failed to the host")
276 #
277 # def dump(self):
278 # main.log.info("Dump node info")
279 # self.execute(cmd = 'dump',prompt = 'mininet>',timeout = 10)
280 # return main.TRUE
281 #
282 # def intfs(self):
283 # main.log.info("List interfaces")
284 # self.execute(cmd = 'intfs',prompt = 'mininet>',timeout = 10)
285 # return main.TRUE
286 #
287 # def net(self):
288 # main.log.info("List network connections")
289 # self.execute(cmd = 'net',prompt = 'mininet>',timeout = 10)
290 # return main.TRUE
291 #
292 # def iperf(self):
293 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
294 # self.execute(cmd = 'iperf',prompt = 'mininet>',timeout = 10)
295 # return main.TRUE
296 #
297 # def iperfudp(self):
298 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
299 # self.execute(cmd = 'iperfudp',prompt = 'mininet>',timeout = 10)
300 # return main.TRUE
301 #
302 # def nodes(self):
303 # main.log.info("List all nodes.")
304 # self.execute(cmd = 'nodes',prompt = 'mininet>',timeout = 10)
305 # return main.TRUE
306 #
307 # def pingpair(self):
308 # main.log.infoe("Ping between first two hosts")
309 # self.execute(cmd = 'pingpair',prompt = 'mininet>',timeout = 20)
310 #
311 # if utilities.assert_matches(expect='0% packet loss',actual=response,onpass="No Packet loss",onfail="Hosts not reachable"):
312 # main.log.info("Ping between two hosts SUCCESS")
313 # main.last_result = main.TRUE
314 # return main.TRUE
315 # else :
316 # main.log.error("PACKET LOST, HOSTS NOT REACHABLE")
317 # main.last_result = main.FALSE
318 # return main.FALSE
319 #
320 # def link(self,**linkargs):
321 # '''
322 # Bring link(s) between two nodes up or down
323 # '''
324 # main.log.info('Bring link(s) between two nodes up or down')
325 # args = utilities.parse_args(["END1","END2","OPTION"],**linkargs)
326 # end1 = args["END1"] if args["END1"] != None else ""
327 # end2 = args["END2"] if args["END2"] != None else ""
328 # option = args["OPTION"] if args["OPTION"] != None else ""
329 # command = "link "+str(end1) + " " + str(end2)+ " " + str(option)
330 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
331 # return main.TRUE
332 #
333
334 # def dpctl(self,**dpctlargs):
335 # '''
336 # Run dpctl command on all switches.
337 # '''
338 # main.log.info('Run dpctl command on all switches')
339 # args = utilities.parse_args(["CMD","ARGS"],**dpctlargs)
340 # cmd = args["CMD"] if args["CMD"] != None else ""
341 # cmdargs = args["ARGS"] if args["ARGS"] != None else ""
342 # command = "dpctl "+cmd + " " + str(cmdargs)
343 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
344 # return main.TRUE
345 #
346 #
347 # def get_version(self):
348 # file_input = path+'/lib/Mininet/INSTALL'
349 # version = super(Mininet, self).get_version()
350 # pattern = 'Mininet\s\w\.\w\.\w\w*'
351 # for line in open(file_input,'r').readlines():
352 # result = re.match(pattern, line)
353 # if result:
354 # version = result.group(0)
355 #
356 #
357 # return version
admin2a9548d2014-06-17 14:08:07 -0700358 def start_tcpdump(self, filename, intf = "eth0", port = "port 6633"):
359 '''
360 Runs tpdump on an intferface and saves the file
361 intf can be specified, or the default eth0 is used
362 '''
363 try:
364 self.handle.sendline("")
365 self.handle.sendline("sudo tcpdump -n -i "+ intf + " " + port + " -w " + filename.strip() + " &")
366 self.handle.sendline("")
367 self.handle.sendline("")
368 i=self.handle.expect(['No\ssuch\device','listening\son',pexpect.TIMEOUT,"\$"],timeout=10)
369 main.log.warn(self.handle.before + self.handle.after)
370 if i == 0:
371 main.log.error(self.name + ": tcpdump - No such device exists. tcpdump attempted on: " + intf)
372 return main.FALSE
373 elif i == 1:
374 main.log.info(self.name + ": tcpdump started on " + intf)
375 return main.TRUE
376 elif i == 2:
377 main.log.error(self.name + ": tcpdump command timed out! Check interface name, given interface was: " + intf)
378 return main.FALSE
379 elif i ==3:
380 main.log.info(self.name +": " + self.handle.before)
381 return main.TRUE
382 else:
383 main.log.error(self.name + ": tcpdump - unexpected response")
384 return main.FALSE
385 except pexpect.EOF:
386 main.log.error(self.name + ": EOF exception found")
387 main.log.error(self.name + ": " + self.handle.before)
388 main.cleanup()
389 main.exit()
390 except:
391 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
392 main.log.error( traceback.print_exc() )
393 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
394 main.cleanup()
395 main.exit()
396
397 def stop_tcpdump(self):
398 "pkills tcpdump"
399 try:
400 self.handle.sendline("sudo pkill tcpdump")
401 self.handle.sendline("")
402 self.handle.sendline("")
403 self.handle.expect("\$")
404 except pexpect.EOF:
405 main.log.error(self.name + ": EOF exception found")
406 main.log.error(self.name + ": " + self.handle.before)
407 main.cleanup()
408 main.exit()
409 except:
410 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
411 main.log.error( traceback.print_exc() )
412 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
413 main.cleanup()
414 main.exit()
415
admin680b78c2014-08-08 11:46:45 -0700416 def del_switch(self,sw):
417 self.handle.sendline("")
418 self.handle.expect("\$")
419 self.handle.sendline("sudo ovs-vsctl del-br "+sw)
420 self.handle.expect("\$")
421 return main.TRUE
admin2a9548d2014-06-17 14:08:07 -0700422
admin680b78c2014-08-08 11:46:45 -0700423 def add_switch(self,sw):
424 self.handle.sendline("")
425 self.handle.expect("\$")
426 self.handle.sendline("sudo ovs-vsctl add-br "+sw)
427 self.handle.expect("\$")
428 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth1")
429 self.handle.expect("\$")
430 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth2")
431 self.handle.expect("\$")
432 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth3")
433 self.handle.expect("\$")
434 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth4")
435 self.handle.expect("\$")
436 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth5")
437 self.handle.expect("\$")
438 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth6")
439 self.handle.expect("\$")
440 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth7")
441 self.handle.expect("\$")
442 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth8")
443 self.handle.expect("\$")
444 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth9")
445 self.handle.expect("\$")
446 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth10")
447 self.handle.expect("\$")
448 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth11")
449 self.handle.expect("\$")
450 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth12")
451 self.handle.expect("\$")
452 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth13")
453 self.handle.expect("\$")
454 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth14")
455 self.handle.expect("\$")
admin2a9548d2014-06-17 14:08:07 -0700456
adminbae64d82013-08-01 10:50:15 -0700457
458 def disconnect(self):
adminaeedddd2013-08-02 15:14:15 -0700459 '''
460 Called at the end of the test to disconnect the handle.
461 '''
adminbae64d82013-08-01 10:50:15 -0700462 response = ''
463 #print "Disconnecting Mininet"
464 if self.handle:
465 self.handle.sendline("exit")
466 self.handle.expect("exit")
467 self.handle.expect("(.*)")
468 response = self.handle.before
469
470 else :
471 main.log.error("Connection failed to the host")
472 response = main.FALSE
473 return response
474
santhosh19fd8032014-07-29 11:56:17 -0700475 def get_flowTable(self,sw):
santhosh9da93892014-07-28 14:11:19 -0700476 self.handle.sendline("cd")
477 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
Jon Hall6c794f32014-08-14 13:33:13 -0700478 #TODO: Write seperate versions of the function for this, possibly a string that tells it which switch is in use?
479 #For 1.0 version of OVS
480 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 }' |sort -n -k1"
481 #for 1.3 version of OVS
Jon Hall41bcb7b2014-08-15 10:10:53 -0700482 command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $3 $7 $8}' |sort -n -k1"
santhosh9da93892014-07-28 14:11:19 -0700483 self.handle.sendline(command)
484 self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
485 self.handle.expect(["NXST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
santhosh9da93892014-07-28 14:11:19 -0700486 response = self.handle.before
santhosh19fd8032014-07-29 11:56:17 -0700487 return response
488
489
490 def flow_comp(self,flow1,flow2):
491 if flow1==flow2:
492 return main.TRUE
493 else:
Jon Hall6c794f32014-08-14 13:33:13 -0700494 main.log.info("Flow tables do not match, printing tables:")
495 main.log.info("Flow Table 1:")
496 main.log.info(flow1)
497 main.log.info("Flow Table 2:")
498 main.log.info(flow2)
santhosh19fd8032014-07-29 11:56:17 -0700499 return main.FALSE
500
adminbae64d82013-08-01 10:50:15 -0700501if __name__ != "__main__":
502 import sys
503 sys.modules[__name__] = RemoteMininetDriver()