blob: b8242c82b3e53cafc2d5b6314d2fcf4b222d7daf [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 print("finished pingKill")
156 self.handle.sendline("")
157 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700158 return main.TRUE
159
160 def pingLongKill(self):
161 import time
Jon Hall6c794f32014-08-14 13:33:13 -0700162 self.handle.sendline("")
163 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700164 command = "sudo kill -SIGING `pgrep ping`"
165 main.log.info(command)
166 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700167 self.handle.sendline("")
168 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700169 return main.TRUE
170
171 def pingHost(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700172 '''
173 Pings between two hosts on remote mininet
174 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700175 self.handle.sendline("")
176 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700177 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
178 command = "mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -c 4 -W 1 -i .2"
179 main.log.info ( command )
180 response = self.execute(cmd=command,prompt="rtt",timeout=10 )
Jon Hall6c794f32014-08-14 13:33:13 -0700181 self.handle.sendline("")
182 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700183 if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
184 main.log.info("NO PACKET LOSS, HOST IS REACHABLE")
185 main.last_result = main.TRUE
186 return main.TRUE
187 else :
188 main.log.error("PACKET LOST, HOST IS NOT REACHABLE")
189 main.last_result = main.FALSE
190 return main.FALSE
191
192
193 def checknum(self,num):
194 '''
adminaeedddd2013-08-02 15:14:15 -0700195 Verifies the correct number of switches are running
adminbae64d82013-08-01 10:50:15 -0700196 '''
197 if self.handle :
198 self.handle.sendline("")
199 self.handle.expect("\$")
200 self.handle.sendline('ifconfig -a | grep "sw.. " | wc -l')
201 self.handle.expect("wc")
202 self.handle.expect("\$")
203 response = self.handle.before
204 self.handle.sendline('ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l')
205 self.handle.expect("color")
206 self.handle.expect("\$")
207 response2 = self.handle.before
208
209 if re.search(num, response):
210 if re.search(num, response2):
211 return main.TRUE
212 else:
213 return main.FALSE
214 else:
215 return main.FALSE
216 else :
217 main.log.error("Connection failed to the host")
218
219 def ctrl_none(self):
adminaeedddd2013-08-02 15:14:15 -0700220 '''
221 Sets all the switches to no controllers.
222 '''
adminbae64d82013-08-01 10:50:15 -0700223 self.execute(cmd="~/ONOS/scripts/test-ctrl-none.sh", prompt="\$",timeout=10)
224
225 def ctrl_one(self, ip):
adminaeedddd2013-08-02 15:14:15 -0700226 '''
227 Sets all the switches to point to the supplied IP
228 '''
adminbae64d82013-08-01 10:50:15 -0700229 self.execute(cmd="~/ONOS/scripts/test-ctrl-one.sh "+ip, prompt="\$",timeout=10)
230
231 def ctrl_local(self):
adminaeedddd2013-08-02 15:14:15 -0700232 '''
233 Sets all the switches to point to the Controller on the same machine that they are running on.
234 '''
adminbae64d82013-08-01 10:50:15 -0700235 self.execute(cmd="~/ONOS/scripts/test-ctrl-local.sh ", prompt="\$",timeout=10)
236
237 # def verifySSH(self,**connectargs):
238 # response = self.execute(cmd="h1 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
239 # response = self.execute(cmd="h4 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
240 # for key in connectargs:
241 # vars(self)[key] = connectargs[key]
242 # response = self.execute(cmd="xterm h1 h4 ",prompt="mininet>",timeout=10)
243 # import time
244 # time.sleep(20)
245 # if self.flag == 0:
246 # self.flag = 1
247 # return main.FALSE
248 # else :
249 # return main.TRUE
250 #
251 # def getMacAddress(self,host):
252 # '''
253 # Verifies the host's ip configured or not.
254 # '''
255 # if self.handle :
256 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
257
258 # pattern = "HWaddr\s(((\d|\w)+:)+(\d|\w))"
259 # mac_address_search = re.search(pattern, response)
260 # main.log.info("Mac-Address of Host "+host +" is "+mac_address_search.group(1))
261 # return mac_address_search.group(1)
262 # else :
263 # main.log.error("Connection failed to the host")
264 # def getIPAddress(self,host):
265 # '''
266 # Verifies the host's ip configured or not.
267 # '''
268 # if self.handle :
269 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
270
271 # pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
272 # ip_address_search = re.search(pattern, response)
273 # main.log.info("IP-Address of Host "+host +" is "+ip_address_search.group(1))
274 # return ip_address_search.group(1)
275 # else :
276 # main.log.error("Connection failed to the host")
277 #
278 # def dump(self):
279 # main.log.info("Dump node info")
280 # self.execute(cmd = 'dump',prompt = 'mininet>',timeout = 10)
281 # return main.TRUE
282 #
283 # def intfs(self):
284 # main.log.info("List interfaces")
285 # self.execute(cmd = 'intfs',prompt = 'mininet>',timeout = 10)
286 # return main.TRUE
287 #
288 # def net(self):
289 # main.log.info("List network connections")
290 # self.execute(cmd = 'net',prompt = 'mininet>',timeout = 10)
291 # return main.TRUE
292 #
293 # def iperf(self):
294 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
295 # self.execute(cmd = 'iperf',prompt = 'mininet>',timeout = 10)
296 # return main.TRUE
297 #
298 # def iperfudp(self):
299 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
300 # self.execute(cmd = 'iperfudp',prompt = 'mininet>',timeout = 10)
301 # return main.TRUE
302 #
303 # def nodes(self):
304 # main.log.info("List all nodes.")
305 # self.execute(cmd = 'nodes',prompt = 'mininet>',timeout = 10)
306 # return main.TRUE
307 #
308 # def pingpair(self):
309 # main.log.infoe("Ping between first two hosts")
310 # self.execute(cmd = 'pingpair',prompt = 'mininet>',timeout = 20)
311 #
312 # if utilities.assert_matches(expect='0% packet loss',actual=response,onpass="No Packet loss",onfail="Hosts not reachable"):
313 # main.log.info("Ping between two hosts SUCCESS")
314 # main.last_result = main.TRUE
315 # return main.TRUE
316 # else :
317 # main.log.error("PACKET LOST, HOSTS NOT REACHABLE")
318 # main.last_result = main.FALSE
319 # return main.FALSE
320 #
321 # def link(self,**linkargs):
322 # '''
323 # Bring link(s) between two nodes up or down
324 # '''
325 # main.log.info('Bring link(s) between two nodes up or down')
326 # args = utilities.parse_args(["END1","END2","OPTION"],**linkargs)
327 # end1 = args["END1"] if args["END1"] != None else ""
328 # end2 = args["END2"] if args["END2"] != None else ""
329 # option = args["OPTION"] if args["OPTION"] != None else ""
330 # command = "link "+str(end1) + " " + str(end2)+ " " + str(option)
331 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
332 # return main.TRUE
333 #
334
335 # def dpctl(self,**dpctlargs):
336 # '''
337 # Run dpctl command on all switches.
338 # '''
339 # main.log.info('Run dpctl command on all switches')
340 # args = utilities.parse_args(["CMD","ARGS"],**dpctlargs)
341 # cmd = args["CMD"] if args["CMD"] != None else ""
342 # cmdargs = args["ARGS"] if args["ARGS"] != None else ""
343 # command = "dpctl "+cmd + " " + str(cmdargs)
344 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
345 # return main.TRUE
346 #
347 #
348 # def get_version(self):
349 # file_input = path+'/lib/Mininet/INSTALL'
350 # version = super(Mininet, self).get_version()
351 # pattern = 'Mininet\s\w\.\w\.\w\w*'
352 # for line in open(file_input,'r').readlines():
353 # result = re.match(pattern, line)
354 # if result:
355 # version = result.group(0)
356 #
357 #
358 # return version
admin2a9548d2014-06-17 14:08:07 -0700359 def start_tcpdump(self, filename, intf = "eth0", port = "port 6633"):
360 '''
361 Runs tpdump on an intferface and saves the file
362 intf can be specified, or the default eth0 is used
363 '''
364 try:
365 self.handle.sendline("")
366 self.handle.sendline("sudo tcpdump -n -i "+ intf + " " + port + " -w " + filename.strip() + " &")
367 self.handle.sendline("")
368 self.handle.sendline("")
369 i=self.handle.expect(['No\ssuch\device','listening\son',pexpect.TIMEOUT,"\$"],timeout=10)
370 main.log.warn(self.handle.before + self.handle.after)
371 if i == 0:
372 main.log.error(self.name + ": tcpdump - No such device exists. tcpdump attempted on: " + intf)
373 return main.FALSE
374 elif i == 1:
375 main.log.info(self.name + ": tcpdump started on " + intf)
376 return main.TRUE
377 elif i == 2:
378 main.log.error(self.name + ": tcpdump command timed out! Check interface name, given interface was: " + intf)
379 return main.FALSE
380 elif i ==3:
381 main.log.info(self.name +": " + self.handle.before)
382 return main.TRUE
383 else:
384 main.log.error(self.name + ": tcpdump - unexpected response")
385 return main.FALSE
386 except pexpect.EOF:
387 main.log.error(self.name + ": EOF exception found")
388 main.log.error(self.name + ": " + self.handle.before)
389 main.cleanup()
390 main.exit()
391 except:
392 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
393 main.log.error( traceback.print_exc() )
394 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
395 main.cleanup()
396 main.exit()
397
398 def stop_tcpdump(self):
399 "pkills tcpdump"
400 try:
401 self.handle.sendline("sudo pkill tcpdump")
402 self.handle.sendline("")
403 self.handle.sendline("")
404 self.handle.expect("\$")
405 except pexpect.EOF:
406 main.log.error(self.name + ": EOF exception found")
407 main.log.error(self.name + ": " + self.handle.before)
408 main.cleanup()
409 main.exit()
410 except:
411 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
412 main.log.error( traceback.print_exc() )
413 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
414 main.cleanup()
415 main.exit()
416
admin680b78c2014-08-08 11:46:45 -0700417 def del_switch(self,sw):
418 self.handle.sendline("")
419 self.handle.expect("\$")
420 self.handle.sendline("sudo ovs-vsctl del-br "+sw)
421 self.handle.expect("\$")
422 return main.TRUE
admin2a9548d2014-06-17 14:08:07 -0700423
admin680b78c2014-08-08 11:46:45 -0700424 def add_switch(self,sw):
425 self.handle.sendline("")
426 self.handle.expect("\$")
427 self.handle.sendline("sudo ovs-vsctl add-br "+sw)
428 self.handle.expect("\$")
429 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth1")
430 self.handle.expect("\$")
431 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth2")
432 self.handle.expect("\$")
433 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth3")
434 self.handle.expect("\$")
435 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth4")
436 self.handle.expect("\$")
437 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth5")
438 self.handle.expect("\$")
439 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth6")
440 self.handle.expect("\$")
441 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth7")
442 self.handle.expect("\$")
443 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth8")
444 self.handle.expect("\$")
445 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth9")
446 self.handle.expect("\$")
447 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth10")
448 self.handle.expect("\$")
449 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth11")
450 self.handle.expect("\$")
451 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth12")
452 self.handle.expect("\$")
453 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth13")
454 self.handle.expect("\$")
455 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth14")
456 self.handle.expect("\$")
admin2a9548d2014-06-17 14:08:07 -0700457
adminbae64d82013-08-01 10:50:15 -0700458
459 def disconnect(self):
adminaeedddd2013-08-02 15:14:15 -0700460 '''
461 Called at the end of the test to disconnect the handle.
462 '''
adminbae64d82013-08-01 10:50:15 -0700463 response = ''
464 #print "Disconnecting Mininet"
465 if self.handle:
466 self.handle.sendline("exit")
467 self.handle.expect("exit")
468 self.handle.expect("(.*)")
469 response = self.handle.before
470
471 else :
472 main.log.error("Connection failed to the host")
473 response = main.FALSE
474 return response
475
santhosh19fd8032014-07-29 11:56:17 -0700476 def get_flowTable(self,sw):
santhosh9da93892014-07-28 14:11:19 -0700477 self.handle.sendline("cd")
478 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
Jon Hall6c794f32014-08-14 13:33:13 -0700479 #TODO: Write seperate versions of the function for this, possibly a string that tells it which switch is in use?
480 #For 1.0 version of OVS
481 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 }' |sort -n -k1"
482 #for 1.3 version of OVS
483 command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 $8}' |sort -n -k1"
santhosh9da93892014-07-28 14:11:19 -0700484 self.handle.sendline(command)
485 self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
486 self.handle.expect(["NXST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
santhosh9da93892014-07-28 14:11:19 -0700487 response = self.handle.before
santhosh19fd8032014-07-29 11:56:17 -0700488 return response
489
490
491 def flow_comp(self,flow1,flow2):
492 if flow1==flow2:
493 return main.TRUE
494 else:
Jon Hall6c794f32014-08-14 13:33:13 -0700495 main.log.info("Flow tables do not match, printing tables:")
496 main.log.info("Flow Table 1:")
497 main.log.info(flow1)
498 main.log.info("Flow Table 2:")
499 main.log.info(flow2)
santhosh19fd8032014-07-29 11:56:17 -0700500 return main.FALSE
501
adminbae64d82013-08-01 10:50:15 -0700502if __name__ != "__main__":
503 import sys
504 sys.modules[__name__] = RemoteMininetDriver()