blob: d4a12cb16e5c844a22790140ea9b2d041b4fa5fd [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("../")
Jon Hall1ccf82c2014-10-15 14:55:16 -040034from math import pow
adminbae64d82013-08-01 10:50:15 -070035from drivers.common.cli.emulatordriver import Emulator
36from drivers.common.clidriver import CLI
37
38class MininetCliDriver(Emulator):
39 '''
Jon Hall41f40e82014-04-08 16:43:17 -070040 MininetCliDriver is the basic driver which will handle the Mininet functions
adminbae64d82013-08-01 10:50:15 -070041 '''
42 def __init__(self):
43 super(Emulator, self).__init__()
44 self.handle = self
45 self.wrapped = sys.modules[__name__]
46 self.flag = 0
47
48 def connect(self, **connectargs):
Jon Hall41f40e82014-04-08 16:43:17 -070049 '''
50 Here the main is the TestON instance after creating all the log handles.
51 '''
adminbae64d82013-08-01 10:50:15 -070052 for key in connectargs:
53 vars(self)[key] = connectargs[key]
54
55 self.name = self.options['name']
56 self.handle = super(MininetCliDriver, self).connect(user_name = self.user_name, ip_address = self.ip_address,port = None, pwd = self.pwd)
57
58 self.ssh_handle = self.handle
59
adminbae64d82013-08-01 10:50:15 -070060 if self.handle :
Jon Hallf2942ce2014-04-10 16:00:16 -070061 main.log.info(self.name+": Clearing any residual state or processes")
adminbae64d82013-08-01 10:50:15 -070062 self.handle.sendline("sudo mn -c")
adminf939f8b2014-04-03 17:22:56 -070063 i=self.handle.expect(['password\sfor\s','Cleanup\scomplete',pexpect.EOF,pexpect.TIMEOUT],120)
adminbae64d82013-08-01 10:50:15 -070064 if i==0:
Jon Hallf2942ce2014-04-10 16:00:16 -070065 main.log.info(self.name+": Sending sudo password")
adminf939f8b2014-04-03 17:22:56 -070066 self.handle.sendline(self.pwd)
67 i=self.handle.expect(['%s:'%(self.user),'\$',pexpect.EOF,pexpect.TIMEOUT],120)
adminbae64d82013-08-01 10:50:15 -070068 if i==1:
Jon Hallf2942ce2014-04-10 16:00:16 -070069 main.log.info(self.name+": Clean")
adminbae64d82013-08-01 10:50:15 -070070 elif i==2:
Jon Hallf2942ce2014-04-10 16:00:16 -070071 main.log.error(self.name+": Connection terminated")
adminbae64d82013-08-01 10:50:15 -070072 elif i==3: #timeout
Jon Hallf2942ce2014-04-10 16:00:16 -070073 main.log.error(self.name+": Something while cleaning MN took too long... " )
adminbae64d82013-08-01 10:50:15 -070074
Jon Hallf2942ce2014-04-10 16:00:16 -070075 main.log.info(self.name+": building fresh mininet")
adminbeea0032014-01-23 14:54:13 -080076 #### for reactive/PARP enabled tests
shahshreyaf4d4d0c2014-10-10 12:11:10 -070077 cmdString = "sudo mn " + self.options['arg1'] + " " + self.options['arg2'] + " --mac --controller " + self.options['controller'] + " " + self.options['arg3']
Jon Hall1ccf82c2014-10-15 14:55:16 -040078
79 argList = self.options['arg1'].split(",")
80 global topoArgList
81 topoArgList = argList[0].split(" ")
82 argList = map(int, argList[1:])
83 topoArgList = topoArgList[1:] + argList
84
85 #### for proactive flow with static ARP entries
shahshreyaf4d4d0c2014-10-10 12:11:10 -070086 #cmdString = "sudo mn " + self.options['arg1'] + " " + self.options['arg2'] + " --mac --arp --controller " + self.options['controller'] + " " + self.options['arg3']
adminbae64d82013-08-01 10:50:15 -070087 self.handle.sendline(cmdString)
Jon Hall333fa8c2014-04-11 11:24:58 -070088 self.handle.expect(["sudo mn",pexpect.EOF,pexpect.TIMEOUT])
adminbae64d82013-08-01 10:50:15 -070089 while 1:
90 i=self.handle.expect(['mininet>','\*\*\*','Exception',pexpect.EOF,pexpect.TIMEOUT],300)
91 if i==0:
Jon Hallf2942ce2014-04-10 16:00:16 -070092 main.log.info(self.name+": mininet built")
adminbae64d82013-08-01 10:50:15 -070093 return main.TRUE
94 if i==1:
Jon Hallb1290e82014-11-18 16:17:48 -050095 self.handle.expect(["",pexpect.EOF,pexpect.TIMEOUT])
adminbae64d82013-08-01 10:50:15 -070096 main.log.info(self.handle.before)
97 elif i==2:
Jon Hallf2942ce2014-04-10 16:00:16 -070098 main.log.error(self.name+": Launching mininet failed...")
adminbae64d82013-08-01 10:50:15 -070099 return main.FALSE
100 elif i==3:
Jon Hallf2942ce2014-04-10 16:00:16 -0700101 main.log.error(self.name+": Connection timeout")
adminbae64d82013-08-01 10:50:15 -0700102 return main.FALSE
103 elif i==4: #timeout
Jon Hallf2942ce2014-04-10 16:00:16 -0700104 main.log.error(self.name+": Something took too long... " )
adminbae64d82013-08-01 10:50:15 -0700105 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700106 #if utilities.assert_matches(expect=patterns,actual=resultCommand,onpass="Network is being launched",onfail="Network launching is being failed "):
107 return main.TRUE
Jon Hallf2942ce2014-04-10 16:00:16 -0700108 else:#if no handle
109 main.log.error(self.name+": Connection failed to the host "+self.user_name+"@"+self.ip_address)
110 main.log.error(self.name+": Failed to connect to the Mininet")
adminbae64d82013-08-01 10:50:15 -0700111 return main.FALSE
Jon Hall1ccf82c2014-10-15 14:55:16 -0400112
113 def num_switches_n_links(self,topoType,depth,fanout):
114 if topoType == 'tree':
115 if fanout is None: #In tree topology, if fanout arg is not given, by default it is 2
116 fanout = 2
117 k = 0
Jon Hall38481722014-11-04 16:50:05 -0500118 count = 0
Jon Hall1ccf82c2014-10-15 14:55:16 -0400119 while(k <= depth-1):
Jon Hall38481722014-11-04 16:50:05 -0500120 count = count + pow(fanout,k)
Jon Hall1ccf82c2014-10-15 14:55:16 -0400121 k = k+1
Jon Hall38481722014-11-04 16:50:05 -0500122 num_switches = count
Jon Hall1ccf82c2014-10-15 14:55:16 -0400123 while(k <= depth-2):
124 '''depth-2 gives you only core links and not considering edge links as seen by ONOS
125 If all the links including edge links are required, do depth-1
126 '''
Jon Hall38481722014-11-04 16:50:05 -0500127 count = count + pow(fanout,k)
Jon Hall1ccf82c2014-10-15 14:55:16 -0400128 k = k+1
Jon Hall38481722014-11-04 16:50:05 -0500129 num_links = count * fanout
Jon Hall1ccf82c2014-10-15 14:55:16 -0400130 #print "num_switches for %s(%d,%d) = %d and links=%d" %(topoType,depth,fanout,num_switches,num_links)
131
132 elif topoType =='linear':
133 if fanout is None: #In linear topology, if fanout or num_hosts_per_sw is not given, by default it is 1
134 fanout = 1
135 num_switches = depth
136 num_hosts_per_sw = fanout
137 total_num_hosts = num_switches * num_hosts_per_sw
138 num_links = total_num_hosts + (num_switches - 1)
139 print "num_switches for %s(%d,%d) = %d and links=%d" %(topoType,depth,fanout,num_switches,num_links)
140 topoDict = {}
141 topoDict = {"num_switches":int(num_switches), "num_corelinks":int(num_links)}
142 return topoDict
143
144
145 def calculate_sw_and_links(self):
146 topoDict = self.num_switches_n_links(*topoArgList)
147 return topoDict
148
adminbae64d82013-08-01 10:50:15 -0700149 def pingall(self):
150 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700151 Verifies the reachability of the hosts using pingall command.
adminbae64d82013-08-01 10:50:15 -0700152 '''
153 if self.handle :
Jon Hallf2942ce2014-04-10 16:00:16 -0700154 main.log.info(self.name+": Checking reachabilty to the hosts using pingall")
Jon Hall6094a362014-04-11 14:46:56 -0700155 try:
Jon Hallb1290e82014-11-18 16:17:48 -0500156 response = self.execute(cmd="pingall",prompt="mininet>",timeout=3)
157 except pexpect.EOF:
Jon Hall6094a362014-04-11 14:46:56 -0700158 main.log.error(self.name + ": EOF exception found")
159 main.log.error(self.name + ": " + self.handle.before)
Jon Hallb1290e82014-11-18 16:17:48 -0500160 main.cleanup()
161 main.exit()
162 except pexpect.TIMEOUT:
163 #We may not want to kill the test if pexpect times out
164 main.log.error(self.name + ": TIMEOUT exception found")
165 main.log.error(self.name + ": " + str(self.handle.before) )
166 #NOTE: mininet's pingall rounds, so we will check the number of passed and number of failed
167 pattern = "Results\:\s0\%\sdropped\s\((?P<passed>[\d]+)/(?P=passed)"
Jon Hallf2942ce2014-04-10 16:00:16 -0700168 if re.search(pattern,response):
169 main.log.info(self.name+": All hosts are reachable")
adminbae64d82013-08-01 10:50:15 -0700170 return main.TRUE
171 else:
Jon Hallf2942ce2014-04-10 16:00:16 -0700172 main.log.error(self.name+": Unable to reach all the hosts")
Jon Hallb1290e82014-11-18 16:17:48 -0500173 main.log.info("Pingall ouput: " + str(response))
174 #NOTE: Send ctrl-c to make sure pingall is done
175 self.handle.send("\x03")
176 self.handle.expect("Interrupt")
177 self.handle.expect("mininet>")
adminbae64d82013-08-01 10:50:15 -0700178 return main.FALSE
179 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700180 main.log.error(self.name+": Connection failed to the host")
Jon Hallb1290e82014-11-18 16:17:48 -0500181 main.cleanup()
182 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700183
184 def fpingHost(self,**pingParams):
185 '''
186 Uses the fping package for faster pinging...
187 *requires fping to be installed on machine running mininet
188 '''
189 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
admin530b4c92013-08-14 16:54:35 -0700190 command = args["SRC"] + " fping -i 100 -t 20 -C 1 -q "+args["TARGET"]
adminaeedddd2013-08-02 15:14:15 -0700191 self.handle.sendline(command)
Jon Hall333fa8c2014-04-11 11:24:58 -0700192 self.handle.expect([args["TARGET"],pexpect.EOF,pexpect.TIMEOUT])
193 self.handle.expect(["mininet",pexpect.EOF,pexpect.TIMEOUT])
adminaeedddd2013-08-02 15:14:15 -0700194 response = self.handle.before
195 if re.search(":\s-" ,response):
Jon Hallf2942ce2014-04-10 16:00:16 -0700196 main.log.info(self.name+": Ping fail")
adminaeedddd2013-08-02 15:14:15 -0700197 return main.FALSE
admin530b4c92013-08-14 16:54:35 -0700198 elif re.search(":\s\d{1,2}\.\d\d", response):
Jon Hallf2942ce2014-04-10 16:00:16 -0700199 main.log.info(self.name+": Ping good!")
adminaeedddd2013-08-02 15:14:15 -0700200 return main.TRUE
Jon Hallf2942ce2014-04-10 16:00:16 -0700201 main.log.info(self.name+": Install fping on mininet machine... ")
202 main.log.info(self.name+": \n---\n"+response)
adminaeedddd2013-08-02 15:14:15 -0700203 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700204
205 def pingHost(self,**pingParams):
Jon Hallf2942ce2014-04-10 16:00:16 -0700206 '''
207 Ping from one mininet host to another
208 Currently the only supported Params: SRC and TARGET
209 '''
adminbae64d82013-08-01 10:50:15 -0700210 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
211 #command = args["SRC"] + " ping -" + args["CONTROLLER"] + " " +args ["TARGET"]
Jon Hall0819fd92014-05-23 12:08:13 -0700212 command = args["SRC"] + " ping "+args ["TARGET"]+" -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700213 try:
Jon Hall6e18c7b2014-04-23 16:26:33 -0700214 main.log.warn("Sending: " + command)
215 #response = self.execute(cmd=command,prompt="mininet",timeout=10 )
216 self.handle.sendline(command)
217 i = self.handle.expect([command,pexpect.TIMEOUT])
218 if i == 1:
219 main.log.error(self.name + ": timeout when waiting for response from mininet")
220 main.log.error("response: " + str(self.handle.before))
221 i = self.handle.expect(["mininet>",pexpect.TIMEOUT])
222 if i == 1:
223 main.log.error(self.name + ": timeout when waiting for response from mininet")
224 main.log.error("response: " + str(self.handle.before))
225 response = self.handle.before
Jon Hall6094a362014-04-11 14:46:56 -0700226 except pexpect.EOF:
227 main.log.error(self.name + ": EOF exception found")
228 main.log.error(self.name + ": " + self.handle.before)
229 main.cleanup()
230 main.exit()
Jon Hallf2942ce2014-04-10 16:00:16 -0700231 main.log.info(self.name+": Ping Response: "+ response )
232 #if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
233 if re.search(',\s0\%\spacket\sloss',response):
Jon Hall6e18c7b2014-04-23 16:26:33 -0700234 main.log.info(self.name+": no packets lost, host is reachable")
adminbae64d82013-08-01 10:50:15 -0700235 main.last_result = main.TRUE
236 return main.TRUE
237 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700238 main.log.error(self.name+": PACKET LOST, HOST IS NOT REACHABLE")
adminbae64d82013-08-01 10:50:15 -0700239 main.last_result = main.FALSE
240 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700241
242 def checkIP(self,host):
243 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700244 Verifies the host's ip configured or not.
adminbae64d82013-08-01 10:50:15 -0700245 '''
246 if self.handle :
Jon Hall6094a362014-04-11 14:46:56 -0700247 try:
248 response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
249 except pexpect.EOF:
250 main.log.error(self.name + ": EOF exception found")
251 main.log.error(self.name + ": " + self.handle.before)
252 main.cleanup()
253 main.exit()
adminbae64d82013-08-01 10:50:15 -0700254
255 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})"
admin2a9548d2014-06-17 14:08:07 -0700256 #pattern = "inet addr:10.0.0.6"
Jon Hallf2942ce2014-04-10 16:00:16 -0700257 #if utilities.assert_matches(expect=pattern,actual=response,onpass="Host Ip configured properly",onfail="Host IP not found") :
258 if re.search(pattern,response):
259 main.log.info(self.name+": Host Ip configured properly")
adminbae64d82013-08-01 10:50:15 -0700260 return main.TRUE
261 else:
Jon Hallf2942ce2014-04-10 16:00:16 -0700262 main.log.error(self.name+": Host IP not found")
adminbae64d82013-08-01 10:50:15 -0700263 return main.FALSE
264 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700265 main.log.error(self.name+": Connection failed to the host")
adminbae64d82013-08-01 10:50:15 -0700266
267 def verifySSH(self,**connectargs):
Jon Hall6094a362014-04-11 14:46:56 -0700268 try:
269 response = self.execute(cmd="h1 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
270 response = self.execute(cmd="h4 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
271 for key in connectargs:
272 vars(self)[key] = connectargs[key]
273 response = self.execute(cmd="xterm h1 h4 ",prompt="mininet>",timeout=10)
274 except pexpect.EOF:
275 main.log.error(self.name + ": EOF exception found")
276 main.log.error(self.name + ": " + self.handle.before)
277 main.cleanup()
278 main.exit()
adminbae64d82013-08-01 10:50:15 -0700279 import time
280 time.sleep(20)
281 if self.flag == 0:
282 self.flag = 1
283 return main.FALSE
284 else :
285 return main.TRUE
286
287 def getMacAddress(self,host):
288 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700289 Verifies the host's ip configured or not.
adminbae64d82013-08-01 10:50:15 -0700290 '''
291 if self.handle :
Jon Hall6094a362014-04-11 14:46:56 -0700292 try:
293 response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
294 except pexpect.EOF:
295 main.log.error(self.name + ": EOF exception found")
296 main.log.error(self.name + ": " + self.handle.before)
297 main.cleanup()
298 main.exit()
adminbae64d82013-08-01 10:50:15 -0700299
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700300 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
301 mac_address_search = re.search(pattern, response, re.I)
302 mac_address = mac_address_search.group().split(" ")[1]
Jon Hallf2942ce2014-04-10 16:00:16 -0700303 main.log.info(self.name+": Mac-Address of Host "+ host + " is " + mac_address)
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700304 return mac_address
adminbae64d82013-08-01 10:50:15 -0700305 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700306 main.log.error(self.name+": Connection failed to the host")
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700307
308 def getInterfaceMACAddress(self,host, interface):
309 '''
310 Return the IP address of the interface on the given host
311 '''
312 if self.handle :
Jon Hall6094a362014-04-11 14:46:56 -0700313 try:
314 response = self.execute(cmd=host+" ifconfig " + interface,
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700315 prompt="mininet>",timeout=10)
Jon Hall6094a362014-04-11 14:46:56 -0700316 except pexpect.EOF:
317 main.log.error(self.name + ": EOF exception found")
318 main.log.error(self.name + ": " + self.handle.before)
319 main.cleanup()
320 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700321
322 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
323 mac_address_search = re.search(pattern, response, re.I)
324 if mac_address_search is None:
325 main.log.info("No mac address found in %s" % response)
326 return main.FALSE
327 mac_address = mac_address_search.group().split(" ")[1]
328 main.log.info("Mac-Address of "+ host + ":"+ interface + " is " + mac_address)
329 return mac_address
330 else:
331 main.log.error("Connection failed to the host")
332
adminbae64d82013-08-01 10:50:15 -0700333 def getIPAddress(self,host):
334 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700335 Verifies the host's ip configured or not.
adminbae64d82013-08-01 10:50:15 -0700336 '''
337 if self.handle :
Jon Hall6094a362014-04-11 14:46:56 -0700338 try:
339 response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
340 except pexpect.EOF:
341 main.log.error(self.name + ": EOF exception found")
342 main.log.error(self.name + ": " + self.handle.before)
343 main.cleanup()
344 main.exit()
adminbae64d82013-08-01 10:50:15 -0700345
346 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
347 ip_address_search = re.search(pattern, response)
Jon Hallf2942ce2014-04-10 16:00:16 -0700348 main.log.info(self.name+": IP-Address of Host "+host +" is "+ip_address_search.group(1))
adminbae64d82013-08-01 10:50:15 -0700349 return ip_address_search.group(1)
350 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700351 main.log.error(self.name+": Connection failed to the host")
adminbae64d82013-08-01 10:50:15 -0700352
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700353 def getSwitchDPID(self,switch):
354 '''
355 return the datapath ID of the switch
356 '''
357 if self.handle :
358 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700359 try:
360 response = self.execute(cmd=cmd,prompt="mininet>",timeout=10)
361 except pexpect.EOF:
362 main.log.error(self.name + ": EOF exception found")
363 main.log.error(self.name + ": " + self.handle.before)
364 main.cleanup()
365 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700366 pattern = r'^(?P<dpid>\d)+'
367 result = re.search(pattern, response, re.MULTILINE)
368 if result is None:
369 main.log.info("Couldn't find DPID for switch '', found: %s" % (switch, response))
370 return main.FALSE
Jon Hallc1a1d242014-07-21 16:03:33 -0700371 return str(result.group(0))
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700372 else:
373 main.log.error("Connection failed to the host")
374
admin2580a0e2014-07-29 11:24:34 -0700375 def getDPID(self, switch):
376 if self.handle:
377 self.handle.sendline("")
378 self.expect("mininet>")
379 cmd = "py %s.dpid" %switch
380 try:
381 response = self.execute(cmd=cmd,prompt="mininet>",timeout=10)
382 self.handle.expect("mininet>")
383 response = self.handle.before
384 return response
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
391
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700392 def getInterfaces(self, node):
393 '''
394 return information dict about interfaces connected to the node
395 '''
396 if self.handle :
Jon Hall38481722014-11-04 16:50:05 -0500397 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s" % (i.name, i.MAC(), i.IP(), i.isUp())'
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700398 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700399 try:
400 response = self.execute(cmd=cmd,prompt="mininet>",timeout=10)
401 except pexpect.EOF:
402 main.log.error(self.name + ": EOF exception found")
403 main.log.error(self.name + ": " + self.handle.before)
404 main.cleanup()
405 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700406 return response
407 else:
408 main.log.error("Connection failed to the node")
409
adminbae64d82013-08-01 10:50:15 -0700410 def dump(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700411 main.log.info(self.name+": Dump node info")
Jon Hall6094a362014-04-11 14:46:56 -0700412 try:
413 response = self.execute(cmd = 'dump',prompt = 'mininet>',timeout = 10)
414 except pexpect.EOF:
415 main.log.error(self.name + ": EOF exception found")
416 main.log.error(self.name + ": " + self.handle.before)
417 main.cleanup()
418 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700419 return response
adminbae64d82013-08-01 10:50:15 -0700420
421 def intfs(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700422 main.log.info(self.name+": List interfaces")
Jon Hall6094a362014-04-11 14:46:56 -0700423 try:
424 response = self.execute(cmd = 'intfs',prompt = 'mininet>',timeout = 10)
425 except pexpect.EOF:
426 main.log.error(self.name + ": EOF exception found")
427 main.log.error(self.name + ": " + self.handle.before)
428 main.cleanup()
429 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700430 return response
adminbae64d82013-08-01 10:50:15 -0700431
432 def net(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700433 main.log.info(self.name+": List network connections")
Jon Hall6094a362014-04-11 14:46:56 -0700434 try:
435 response = self.execute(cmd = 'net',prompt = 'mininet>',timeout = 10)
436 except pexpect.EOF:
437 main.log.error(self.name + ": EOF exception found")
438 main.log.error(self.name + ": " + self.handle.before)
439 main.cleanup()
440 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700441 return response
adminbae64d82013-08-01 10:50:15 -0700442
443 def iperf(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700444 main.log.info(self.name+": Simple iperf TCP test between two (optionally specified) hosts")
Jon Hall6094a362014-04-11 14:46:56 -0700445 try:
446 response = self.execute(cmd = 'iperf',prompt = 'mininet>',timeout = 10)
447 except pexpect.EOF:
448 main.log.error(self.name + ": EOF exception found")
449 main.log.error(self.name + ": " + self.handle.before)
450 main.cleanup()
451 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700452 return response
adminbae64d82013-08-01 10:50:15 -0700453
454 def iperfudp(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700455 main.log.info(self.name+": Simple iperf TCP test between two (optionally specified) hosts")
Jon Hall6094a362014-04-11 14:46:56 -0700456 try:
457 response = self.execute(cmd = 'iperfudp',prompt = 'mininet>',timeout = 10)
458 except pexpect.EOF:
459 main.log.error(self.name + ": EOF exception found")
460 main.log.error(self.name + ": " + self.handle.before)
461 main.cleanup()
462 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700463 return response
adminbae64d82013-08-01 10:50:15 -0700464
465 def nodes(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700466 main.log.info(self.name+": List all nodes.")
Jon Hall6094a362014-04-11 14:46:56 -0700467 try:
468 response = self.execute(cmd = 'nodes',prompt = 'mininet>',timeout = 10)
469 except pexpect.EOF:
470 main.log.error(self.name + ": EOF exception found")
471 main.log.error(self.name + ": " + self.handle.before)
472 main.cleanup()
473 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700474 return response
adminbae64d82013-08-01 10:50:15 -0700475
476 def pingpair(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700477 main.log.info(self.name+": Ping between first two hosts")
Jon Hall6094a362014-04-11 14:46:56 -0700478 try:
479 response = self.execute(cmd = 'pingpair',prompt = 'mininet>',timeout = 20)
480 except pexpect.EOF:
481 main.log.error(self.name + ": EOF exception found")
482 main.log.error(self.name + ": " + self.handle.before)
483 main.cleanup()
484 main.exit()
adminbae64d82013-08-01 10:50:15 -0700485
Jon Hallf2942ce2014-04-10 16:00:16 -0700486 #if utilities.assert_matches(expect='0% packet loss',actual=response,onpass="No Packet loss",onfail="Hosts not reachable"):
487 if re.search(',\s0\%\spacket\sloss',response):
488 main.log.info(self.name+": Ping between two hosts SUCCESSFUL")
adminbae64d82013-08-01 10:50:15 -0700489 main.last_result = main.TRUE
490 return main.TRUE
491 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700492 main.log.error(self.name+": PACKET LOST, HOSTS NOT REACHABLE")
adminbae64d82013-08-01 10:50:15 -0700493 main.last_result = main.FALSE
494 return main.FALSE
495
496 def link(self,**linkargs):
497 '''
498 Bring link(s) between two nodes up or down
499 '''
adminbae64d82013-08-01 10:50:15 -0700500 args = utilities.parse_args(["END1","END2","OPTION"],**linkargs)
501 end1 = args["END1"] if args["END1"] != None else ""
502 end2 = args["END2"] if args["END2"] != None else ""
503 option = args["OPTION"] if args["OPTION"] != None else ""
Jon Hall38481722014-11-04 16:50:05 -0500504 main.log.info("Bring link between '"+ end1 +"' and '" + end2 + "' '" + option + "'")
adminbae64d82013-08-01 10:50:15 -0700505 command = "link "+str(end1) + " " + str(end2)+ " " + str(option)
Jon Hall6094a362014-04-11 14:46:56 -0700506 try:
Jon Halle80ef8c2014-04-29 15:29:13 -0700507 #response = self.execute(cmd=command,prompt="mininet>",timeout=10)
508 self.handle.sendline(command)
509 self.handle.expect("mininet>")
Jon Hall6094a362014-04-11 14:46:56 -0700510 except pexpect.EOF:
511 main.log.error(self.name + ": EOF exception found")
512 main.log.error(self.name + ": " + self.handle.before)
513 main.cleanup()
514 main.exit()
adminbae64d82013-08-01 10:50:15 -0700515 return main.TRUE
516
517
admin530b4c92013-08-14 16:54:35 -0700518 def yank(self,**yankargs):
adminaeedddd2013-08-02 15:14:15 -0700519 '''
admin530b4c92013-08-14 16:54:35 -0700520 yank a mininet switch interface to a host
adminaeedddd2013-08-02 15:14:15 -0700521 '''
admin530b4c92013-08-14 16:54:35 -0700522 main.log.info('Yank the switch interface attached to a host')
523 args = utilities.parse_args(["SW","INTF"],**yankargs)
adminaeedddd2013-08-02 15:14:15 -0700524 sw = args["SW"] if args["SW"] !=None else ""
525 intf = args["INTF"] if args["INTF"] != None else ""
526 command = "py "+ str(sw) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700527 try:
528 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
529 except pexpect.EOF:
530 main.log.error(self.name + ": EOF exception found")
531 main.log.error(self.name + ": " + self.handle.before)
532 main.cleanup()
533 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700534 return main.TRUE
535
536 def plug(self, **plugargs):
537 '''
538 plug the yanked mininet switch interface to a switch
539 '''
540 main.log.info('Plug the switch interface attached to a switch')
admin530b4c92013-08-14 16:54:35 -0700541 args = utilities.parse_args(["SW","INTF"],**plugargs)
adminaeedddd2013-08-02 15:14:15 -0700542 sw = args["SW"] if args["SW"] !=None else ""
543 intf = args["INTF"] if args["INTF"] != None else ""
544 command = "py "+ str(sw) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700545 try:
546 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
547 except pexpect.EOF:
548 main.log.error(self.name + ": EOF exception found")
549 main.log.error(self.name + ": " + self.handle.before)
550 main.cleanup()
551 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700552 return main.TRUE
553
554
555
adminbae64d82013-08-01 10:50:15 -0700556 def dpctl(self,**dpctlargs):
557 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700558 Run dpctl command on all switches.
adminbae64d82013-08-01 10:50:15 -0700559 '''
560 main.log.info('Run dpctl command on all switches')
561 args = utilities.parse_args(["CMD","ARGS"],**dpctlargs)
562 cmd = args["CMD"] if args["CMD"] != None else ""
563 cmdargs = args["ARGS"] if args["ARGS"] != None else ""
564 command = "dpctl "+cmd + " " + str(cmdargs)
Jon Hall6094a362014-04-11 14:46:56 -0700565 try:
566 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
567 except pexpect.EOF:
568 main.log.error(self.name + ": EOF exception found")
569 main.log.error(self.name + ": " + self.handle.before)
570 main.cleanup()
571 main.exit()
adminbae64d82013-08-01 10:50:15 -0700572 return main.TRUE
573
574
575 def get_version(self):
576 file_input = path+'/lib/Mininet/INSTALL'
577 version = super(Mininet, self).get_version()
578 pattern = 'Mininet\s\w\.\w\.\w\w*'
579 for line in open(file_input,'r').readlines():
580 result = re.match(pattern, line)
581 if result:
582 version = result.group(0)
Jon Hallec3c21e2014-11-10 22:22:37 -0500583 return version
adminbae64d82013-08-01 10:50:15 -0700584
Jon Hallec3c21e2014-11-10 22:22:37 -0500585 def get_sw_controller(self, sw):
586 '''
587 Parameters:
588 sw: The name of an OVS switch. Example "s1"
589 Return:
590 The output of the command from the mininet cli or main.FALSE on timeout
591 '''
admin2a9548d2014-06-17 14:08:07 -0700592 command = "sh ovs-vsctl get-controller "+str(sw)
593 try:
Jon Hallec3c21e2014-11-10 22:22:37 -0500594 response = self.execute(cmd=command, prompt="mininet>", timeout=10)
admin2a9548d2014-06-17 14:08:07 -0700595 if response:
Jon Hallec3c21e2014-11-10 22:22:37 -0500596 return response
admin2a9548d2014-06-17 14:08:07 -0700597 else:
598 return main.FALSE
599 except pexpect.EOF:
600 main.log.error(self.name + ": EOF exception found")
601 main.log.error(self.name + ": " + self.handle.before)
602 main.cleanup()
603 main.exit()
adminbae64d82013-08-01 10:50:15 -0700604
605 def assign_sw_controller(self,**kwargs):
Jon Hallf89c8552014-04-02 13:14:06 -0700606 '''
607 count is only needed if there is more than 1 controller
608 '''
609 args = utilities.parse_args(["COUNT"],**kwargs)
610 count = args["COUNT"] if args!={} else 1
611
612 argstring = "SW"
613 for j in range(count):
614 argstring = argstring + ",IP" + str(j+1) + ",PORT" + str(j+1)
615 args = utilities.parse_args(argstring.split(","),**kwargs)
616
adminbae64d82013-08-01 10:50:15 -0700617 sw = args["SW"] if args["SW"] != None else ""
admin530b4c92013-08-14 16:54:35 -0700618 ptcpA = int(args["PORT1"])+int(sw) if args["PORT1"] != None else ""
Jon Hallf89c8552014-04-02 13:14:06 -0700619 ptcpB = "ptcp:"+str(ptcpA) if ptcpA != "" else ""
620
621 command = "sh ovs-vsctl set-controller s" + str(sw) + " " + ptcpB + " "
622 for j in range(count):
623 i=j+1
624 args = utilities.parse_args(["IP"+str(i),"PORT"+str(i)],**kwargs)
625 ip = args["IP"+str(i)] if args["IP"+str(i)] != None else ""
626 port = args["PORT" + str(i)] if args["PORT" + str(i)] != None else ""
627 tcp = "tcp:" + str(ip) + ":" + str(port) + " " if ip != "" else ""
628 command = command + tcp
Jon Hall6094a362014-04-11 14:46:56 -0700629 try:
630 self.execute(cmd=command,prompt="mininet>",timeout=5)
631 except pexpect.EOF:
632 main.log.error(self.name + ": EOF exception found")
633 main.log.error(self.name + ": " + self.handle.before)
634 main.cleanup()
635 main.exit()
636 except:
637 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
638 main.log.error( traceback.print_exc() )
639 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
640 main.cleanup()
641 main.exit()
adminbae64d82013-08-01 10:50:15 -0700642
Jon Hall0819fd92014-05-23 12:08:13 -0700643 def delete_sw_controller(self,sw):
644 '''
645 Removes the controller target from sw
646 '''
647
648 command = "sh ovs-vsctl del-controller "+str(sw)
649 try:
650 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
651 except pexpect.EOF:
652 main.log.error(self.name + ": EOF exception found")
653 main.log.error(self.name + ": " + self.handle.before)
654 main.cleanup()
655 main.exit()
656 else:
657 main.log.info(response)
658
Jon Hallb1290e82014-11-18 16:17:48 -0500659 def add_switch( self, sw, **kwargs ):
660 '''
661 adds a switch to the mininet topology
662 NOTE: this uses a custom mn function
663 NOTE: cannot currently specify what type of switch
664 required params:
665 switchname = name of the new switch as a string
666 optional keyvalues:
667 dpid = "dpid"
668 returns: main.FASLE on an error, else main.TRUE
669 '''
670 dpid = kwargs.get('dpid', '')
671 command = "addswitch " + sw + " " + str(dpid)
672 try:
673 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
674 if re.search("already exists!", response):
675 main.log.warn(response)
676 return main.FALSE
677 elif re.search("Error", response):
678 main.log.warn(response)
679 return main.FALSE
680 elif re.search("usage:", response):
681 main.log.warn(response)
682 return main.FALSE
683 else:
684 return main.TRUE
685 except pexpect.EOF:
686 main.log.error(self.name + ": EOF exception found")
687 main.log.error(self.name + ": " + self.handle.before)
688 main.cleanup()
689 main.exit()
690
691 def del_switch( self, sw ):
692 '''
693 delete a switch from the mininet topology
694 NOTE: this uses a custom mn function
695 required params:
696 switchname = name of the switch as a string
697 returns: main.FASLE on an error, else main.TRUE
698 '''
699 command = "delswitch " + sw
700 try:
701 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
702 if re.search("no switch named", response):
703 main.log.warn(response)
704 return main.FALSE
705 elif re.search("Error", response):
706 main.log.warn(response)
707 return main.FALSE
708 elif re.search("usage:", response):
709 main.log.warn(response)
710 return main.FALSE
711 else:
712 return main.TRUE
713 except pexpect.EOF:
714 main.log.error(self.name + ": EOF exception found")
715 main.log.error(self.name + ": " + self.handle.before)
716 main.cleanup()
717 main.exit()
718
719 def add_link( self, node1, node2 ):
720 '''
721 add a link to the mininet topology
722 NOTE: this uses a custom mn function
723 NOTE: cannot currently specify what type of link
724 required params:
725 node1 = the string node name of the first endpoint of the link
726 node2 = the string node name of the second endpoint of the link
727 returns: main.FASLE on an error, else main.TRUE
728 '''
729 command = "addlink " + node1 + " " + node2
730 try:
731 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
732 if re.search("doesnt exist!", response):
733 main.log.warn(response)
734 return main.FALSE
735 elif re.search("Error", response):
736 main.log.warn(response)
737 return main.FALSE
738 elif re.search("usage:", response):
739 main.log.warn(response)
740 return main.FALSE
741 else:
742 return main.TRUE
743 except pexpect.EOF:
744 main.log.error(self.name + ": EOF exception found")
745 main.log.error(self.name + ": " + self.handle.before)
746 main.cleanup()
747 main.exit()
748
749 def del_link( self, node1, node2 ):
750 '''
751 delete a link from the mininet topology
752 NOTE: this uses a custom mn function
753 required params:
754 node1 = the string node name of the first endpoint of the link
755 node2 = the string node name of the second endpoint of the link
756 returns: main.FASLE on an error, else main.TRUE
757 '''
758 command = "dellink " + node1 + " " + node2
759 try:
760 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
761 if re.search("no node named", response):
762 main.log.warn(response)
763 return main.FALSE
764 elif re.search("Error", response):
765 main.log.warn(response)
766 return main.FALSE
767 elif re.search("usage:", response):
768 main.log.warn(response)
769 return main.FALSE
770 else:
771 return main.TRUE
772 except pexpect.EOF:
773 main.log.error(self.name + ": EOF exception found")
774 main.log.error(self.name + ": " + self.handle.before)
775 main.cleanup()
776 main.exit()
777
778 def add_host( self, hostname, **kwargs ):
779 '''
780 Add a host to the mininet topology
781 NOTE: this uses a custom mn function
782 NOTE: cannot currently specify what type of host
783 required params:
784 hostname = the string hostname
785 optional key-value params
786 switch = "switch name"
787 returns: main.FASLE on an error, else main.TRUE
788 '''
789 switch = kwargs.get('switch', '')
790 command = "addhost " + hostname + " " + switch
791 try:
792 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
793 if re.search("already exists!", response):
794 main.log.warn(response)
795 return main.FALSE
796 elif re.search("doesnt exists!", response):
797 main.log.warn(response)
798 return main.FALSE
799 elif re.search("Error", response):
800 main.log.warn(response)
801 return main.FALSE
802 elif re.search("usage:", response):
803 main.log.warn(response)
804 return main.FALSE
805 else:
806 return main.TRUE
807 except pexpect.EOF:
808 main.log.error(self.name + ": EOF exception found")
809 main.log.error(self.name + ": " + self.handle.before)
810 main.cleanup()
811 main.exit()
812
813 def del_host( self, hostname ):
814 '''
815 delete a host from the mininet topology
816 NOTE: this uses a custom mn function
817 required params:
818 hostname = the string hostname
819 returns: main.FASLE on an error, else main.TRUE
820 '''
821 command = "delhost " + hostname
822 try:
823 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
824 if re.search("no host named", response):
825 main.log.warn(response)
826 return main.FALSE
827 elif re.search("Error", response):
828 main.log.warn(response)
829 return main.FALSE
830 elif re.search("usage:", response):
831 main.log.warn(response)
832 return main.FALSE
833 else:
834 return main.TRUE
835 except pexpect.EOF:
836 main.log.error(self.name + ": EOF exception found")
837 main.log.error(self.name + ": " + self.handle.before)
838 main.cleanup()
839 main.exit()
Jon Hall0819fd92014-05-23 12:08:13 -0700840
adminbae64d82013-08-01 10:50:15 -0700841 def disconnect(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700842 main.log.info(self.name+": Disconnecting mininet...")
adminbae64d82013-08-01 10:50:15 -0700843 response = ''
844 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700845 try:
846 response = self.execute(cmd="exit",prompt="(.*)",timeout=120)
847 response = self.execute(cmd="exit",prompt="(.*)",timeout=120)
Jon Halle80ef8c2014-04-29 15:29:13 -0700848 self.handle.sendline("sudo mn -c")
shahshreya328c2a72014-11-17 10:19:50 -0800849 response = main.TRUE
Jon Hall6094a362014-04-11 14:46:56 -0700850 except pexpect.EOF:
851 main.log.error(self.name + ": EOF exception found")
852 main.log.error(self.name + ": " + self.handle.before)
853 main.cleanup()
854 main.exit()
adminbae64d82013-08-01 10:50:15 -0700855 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700856 main.log.error(self.name+": Connection failed to the host")
adminbae64d82013-08-01 10:50:15 -0700857 response = main.FALSE
858 return response
admin07529932013-11-22 14:58:28 -0800859
860 def arping(self, src, dest, destmac):
861 self.handle.sendline('')
Jon Hall333fa8c2014-04-11 11:24:58 -0700862 self.handle.expect(["mininet",pexpect.EOF,pexpect.TIMEOUT])
admin07529932013-11-22 14:58:28 -0800863
864 self.handle.sendline(src + ' arping ' + dest)
865 try:
Jon Hall333fa8c2014-04-11 11:24:58 -0700866 self.handle.expect([destmac,pexpect.EOF,pexpect.TIMEOUT])
Jon Hallf2942ce2014-04-10 16:00:16 -0700867 main.log.info(self.name+": ARP successful")
Jon Hall333fa8c2014-04-11 11:24:58 -0700868 self.handle.expect(["mininet",pexpect.EOF,pexpect.TIMEOUT])
admin07529932013-11-22 14:58:28 -0800869 return main.TRUE
870 except:
Jon Hallf2942ce2014-04-10 16:00:16 -0700871 main.log.warn(self.name+": ARP FAILURE")
Jon Hall333fa8c2014-04-11 11:24:58 -0700872 self.handle.expect(["mininet",pexpect.EOF,pexpect.TIMEOUT])
admin07529932013-11-22 14:58:28 -0800873 return main.FALSE
874
875 def decToHex(num):
876 return hex(num).split('x')[1]
admin2a9548d2014-06-17 14:08:07 -0700877
878 def getSwitchFlowCount(self, switch):
879 '''
880 return the Flow Count of the switch
881 '''
882 if self.handle:
883 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
884 try:
885 response = self.execute(cmd=cmd, prompt="mininet>", timeout=10)
886 except pexpect.EOF:
887 main.log.error(self.name + ": EOF exception found")
888 main.log.error(self.name + " " + self.handle.before)
889 main.cleanup()
890 main.exit()
891 pattern = "flow_count=(\d+)"
892 result = re.search(pattern, response, re.MULTILINE)
893 if result is None:
admin2a9548d2014-06-17 14:08:07 -0700894 main.log.info("Couldn't find flows on switch '', found: %s" % (switch, response))
895 return main.FALSE
896 return result.group(1)
897 else:
898 main.log.error("Connection failed to the Mininet host")
899
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -0700900 def check_flows(self, sw, dump_format=None):
901 if dump_format:
902 command = "sh ovs-ofctl -F " + dump_format + " dump-flows " + str(sw)
903 else:
904 command = "sh ovs-ofctl dump-flows "+str(sw)
admin2a9548d2014-06-17 14:08:07 -0700905 try:
906 response=self.execute(cmd=command,prompt="mininet>",timeout=10)
907 return response
908 except pexpect.EOF:
909 main.log.error(self.name + ": EOF exception found")
910 main.log.error(self.name + ": " + self.handle.before)
911 main.cleanup()
912 main.exit()
913 else:
914 main.log.info(response)
915
916 def start_tcpdump(self, filename, intf = "eth0", port = "port 6633"):
917 '''
918 Runs tpdump on an intferface and saves the file
919 intf can be specified, or the default eth0 is used
920 '''
921 try:
922 self.handle.sendline("")
923 self.handle.expect("mininet>")
924 self.handle.sendline("sh sudo tcpdump -n -i "+ intf + " " + port + " -w " + filename.strip() + " &")
925 self.handle.sendline("")
admin2a9548d2014-06-17 14:08:07 -0700926 i=self.handle.expect(['No\ssuch\device','listening\son',pexpect.TIMEOUT,"mininet>"],timeout=10)
927 main.log.warn(self.handle.before + self.handle.after)
Jon Hallb1290e82014-11-18 16:17:48 -0500928 self.handle.sendline("")
929 self.handle.expect("mininet>")
admin2a9548d2014-06-17 14:08:07 -0700930 if i == 0:
931 main.log.error(self.name + ": tcpdump - No such device exists. tcpdump attempted on: " + intf)
932 return main.FALSE
933 elif i == 1:
934 main.log.info(self.name + ": tcpdump started on " + intf)
935 return main.TRUE
936 elif i == 2:
937 main.log.error(self.name + ": tcpdump command timed out! Check interface name, given interface was: " + intf)
938 return main.FALSE
939 elif i ==3:
940 main.log.info(self.name +": " + self.handle.before)
941 return main.TRUE
942 else:
943 main.log.error(self.name + ": tcpdump - unexpected response")
944 return main.FALSE
945 except pexpect.EOF:
946 main.log.error(self.name + ": EOF exception found")
947 main.log.error(self.name + ": " + self.handle.before)
948 main.cleanup()
949 main.exit()
950 except:
951 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
952 main.log.error( traceback.print_exc() )
953 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
954 main.cleanup()
955 main.exit()
956
957 def stop_tcpdump(self):
958 "pkills tcpdump"
959 try:
960 self.handle.sendline("sh sudo pkill tcpdump")
Jon Hallb1290e82014-11-18 16:17:48 -0500961 self.handle.expect("mininet>")
admin2a9548d2014-06-17 14:08:07 -0700962 self.handle.sendline("")
963 self.handle.expect("mininet>")
964 except pexpect.EOF:
965 main.log.error(self.name + ": EOF exception found")
966 main.log.error(self.name + ": " + self.handle.before)
967 main.cleanup()
968 main.exit()
969 except:
970 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
971 main.log.error( traceback.print_exc() )
972 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
973 main.cleanup()
974 main.exit()
975
Jon Hall3d87d502014-10-17 18:37:42 -0400976 def compare_switches(self, topo, switches_json):
977 '''
978 Compare mn and onos switches
979 topo: sts TestONTopology object
980 switches_json: parsed json object from the onos devices api
981
982 This uses the sts TestONTopology object
983
984 '''
985 import json
Jon Hall42db6dc2014-10-24 19:03:48 -0400986 #main.log.debug("Switches_json string: ", switches_json)
Jon Hall3d87d502014-10-17 18:37:42 -0400987 output = {"switches":[]}
988 for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
Jon Hall3d87d502014-10-17 18:37:42 -0400989 ports = []
990 for port in switch.ports.values():
Jon Hall3d87d502014-10-17 18:37:42 -0400991 ports.append({'of_port': port.port_no, 'mac': str(port.hw_addr).replace('\'',''), 'name': port.name})
992 output['switches'].append({"name": switch.name, "dpid": str(switch.dpid).zfill(16), "ports": ports })
Jon Hall3d87d502014-10-17 18:37:42 -0400993
Jon Hall42db6dc2014-10-24 19:03:48 -0400994 #print "mn"
Jon Hall3d87d502014-10-17 18:37:42 -0400995 #print json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))
Jon Hall42db6dc2014-10-24 19:03:48 -0400996 #print "onos"
997 #print json.dumps(switches_json, sort_keys=True,indent=4,separators=(',', ': '))
Jon Hall3d87d502014-10-17 18:37:42 -0400998
999
1000 # created sorted list of dpid's in MN and ONOS for comparison
1001 mnDPIDs=[]
1002 for switch in output['switches']:
1003 mnDPIDs.append(switch['dpid'])
1004 mnDPIDs.sort()
Jon Hall38481722014-11-04 16:50:05 -05001005 #print "List of Mininet switch DPID's"
Jon Hall3d87d502014-10-17 18:37:42 -04001006 #print mnDPIDs
1007 if switches_json == "":#if rest call fails
Jon Hall42db6dc2014-10-24 19:03:48 -04001008 main.log.error(self.name + ".compare_switches(): Empty JSON object given from ONOS")
Jon Hall3d87d502014-10-17 18:37:42 -04001009 return main.FALSE
1010 onos=switches_json
1011 onosDPIDs=[]
1012 for switch in onos:
Jon Hall38481722014-11-04 16:50:05 -05001013 if switch['available'] == True:
1014 onosDPIDs.append(switch['id'].replace(":",'').replace("of",''))
1015 #else:
1016 #print "Switch is unavailable:"
1017 #print switch
Jon Hall3d87d502014-10-17 18:37:42 -04001018 onosDPIDs.sort()
Jon Hall38481722014-11-04 16:50:05 -05001019 #print "List of ONOS switch DPID's"
Jon Hall3d87d502014-10-17 18:37:42 -04001020 #print onosDPIDs
1021
1022 if mnDPIDs!=onosDPIDs:
1023 switch_results = main.FALSE
1024 main.log.report( "Switches in MN but not in ONOS:")
1025 main.log.report( str([switch for switch in mnDPIDs if switch not in onosDPIDs]))
1026 main.log.report( "Switches in ONOS but not in MN:")
1027 main.log.report( str([switch for switch in onosDPIDs if switch not in mnDPIDs]))
1028 else:#list of dpid's match in onos and mn
1029 #main.log.report("DEBUG: The dpid's of the switches in Mininet and ONOS match")
1030 switch_results = main.TRUE
1031 return switch_results
1032
1033
1034
Jon Hall72cf1dc2014-10-20 21:04:50 -04001035 def compare_ports(self, topo, ports_json):
1036 '''
1037 Compare mn and onos ports
1038 topo: sts TestONTopology object
1039 ports_json: parsed json object from the onos ports api
1040
1041 Dependencies:
1042 1. This uses the sts TestONTopology object
1043 2. numpy - "sudo pip install numpy"
1044
1045 '''
Jon Hall1c9e8732014-10-27 19:29:27 -04001046 #FIXME: this does not look for extra ports in ONOS, only checks that ONOS has what is in MN
Jon Hall72cf1dc2014-10-20 21:04:50 -04001047 import json
1048 from numpy import uint64
Jon Hallb1290e82014-11-18 16:17:48 -05001049 ports_results = main.TRUE
Jon Hall72cf1dc2014-10-20 21:04:50 -04001050 output = {"switches":[]}
1051 for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
Jon Hall72cf1dc2014-10-20 21:04:50 -04001052 ports = []
1053 for port in switch.ports.values():
1054 #print port.hw_addr.toStr(separator = '')
Jon Hall39f29df2014-11-04 19:30:21 -05001055 tmp_port = {}
1056 tmp_port['of_port'] = port.port_no
1057 tmp_port['mac'] = str(port.hw_addr).replace('\'','')
1058 tmp_port['name'] = port.name
1059 tmp_port['enabled'] = port.enabled
1060
1061 ports.append(tmp_port)
1062 tmp_switch = {}
1063 tmp_switch['name'] = switch.name
1064 tmp_switch['dpid'] = str(switch.dpid).zfill(16)
1065 tmp_switch['ports'] = ports
1066
1067 output['switches'].append(tmp_switch)
Jon Hall72cf1dc2014-10-20 21:04:50 -04001068
1069
1070 ################ports#############
Jon Hall39f29df2014-11-04 19:30:21 -05001071 for mn_switch in output['switches']:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001072 mn_ports = []
1073 onos_ports = []
Jon Hallb1290e82014-11-18 16:17:48 -05001074 switch_result = main.TRUE
Jon Hall39f29df2014-11-04 19:30:21 -05001075 for port in mn_switch['ports']:
Jon Hall38481722014-11-04 16:50:05 -05001076 if port['enabled'] == True:
1077 mn_ports.append(port['of_port'])
Jon Hallb1290e82014-11-18 16:17:48 -05001078 #else: #DEBUG only
1079 # main.log.warn("Port %s on switch %s is down" % ( str(port['of_port']) , str(mn_switch['name'])) )
Jon Hall72cf1dc2014-10-20 21:04:50 -04001080 for onos_switch in ports_json:
Jon Hall38481722014-11-04 16:50:05 -05001081 #print "Iterating through a new switch as seen by ONOS"
1082 #print onos_switch
1083 if onos_switch['device']['available'] == True:
Jon Hall39f29df2014-11-04 19:30:21 -05001084 if onos_switch['device']['id'].replace(':','').replace("of", '') == mn_switch['dpid']:
Jon Hall38481722014-11-04 16:50:05 -05001085 for port in onos_switch['ports']:
1086 if port['isEnabled']:
1087 #print "Iterating through available ports on the switch"
1088 #print port
Jon Hallb1290e82014-11-18 16:17:48 -05001089 if port['port'] == 'local':
1090 #onos_ports.append('local')
1091 onos_ports.append(long(uint64(-2)))
1092 else:
1093 onos_ports.append(int(port['port']))
1094 '''
1095 else: #This is likely a new reserved port implemented
1096 main.log.error("unkown port '" + str(port['port']) )
1097 '''
1098 else: #DEBUG
1099 main.log.warn("Port %s on switch %s is down" % ( str(port['port']) , str(onos_switch['device']['id'])) )
1100 break
Jon Hall72cf1dc2014-10-20 21:04:50 -04001101 mn_ports.sort(key=float)
1102 onos_ports.sort(key=float)
1103 #print "\nPorts for Switch %s:" % (switch['name'])
1104 #print "\tmn_ports[] = ", mn_ports
1105 #print "\tonos_ports[] = ", onos_ports
Jon Hallb1290e82014-11-18 16:17:48 -05001106 mn_ports_log = mn_ports
1107 onos_ports_log = onos_ports
1108 mn_ports = [x for x in mn_ports]
1109 onos_ports = [x for x in onos_ports]
Jon Hall38481722014-11-04 16:50:05 -05001110
Jon Hall72cf1dc2014-10-20 21:04:50 -04001111 #TODO: handle other reserved port numbers besides LOCAL
Jon Hallb1290e82014-11-18 16:17:48 -05001112 #NOTE: Reserved ports
1113 # Local port: -2 in Openflow, ONOS shows 'local', we store as long(uint64(-2))
1114 for mn_port in mn_ports_log:
1115 if mn_port in onos_ports:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001116 #don't set results to true here as this is just one of many checks and it might override a failure
Jon Hallb1290e82014-11-18 16:17:48 -05001117 mn_ports.remove(mn_port)
1118 onos_ports.remove(mn_port)
1119 #NOTE: OVS reports this as down since there is no link
1120 # So ignoring these for now
1121 #TODO: Come up with a better way of handling these
1122 if 65534 in mn_ports:
1123 mn_ports.remove(65534)
1124 if long(uint64(-2)) in onos_ports:
1125 onos_ports.remove( long(uint64(-2)) )
1126 if len(mn_ports): #the ports of this switch don't match
1127 switch_result = main.FALSE
1128 main.log.warn("Ports in MN but not ONOS: " + str(mn_ports) )
1129 if len(onos_ports): #the ports of this switch don't match
1130 switch_result = main.FALSE
1131 main.log.warn("Ports in ONOS but not MN: " + str(onos_ports) )
1132 if switch_result == main.FALSE:
Jon Hall39f29df2014-11-04 19:30:21 -05001133 main.log.report("The list of ports for switch %s(%s) does not match:" % (mn_switch['name'], mn_switch['dpid']) )
Jon Hallb1290e82014-11-18 16:17:48 -05001134 main.log.warn("mn_ports[] = " + str(mn_ports_log))
1135 main.log.warn("onos_ports[] = " + str(onos_ports_log))
1136 ports_results = ports_results and switch_result
1137 return ports_results
Jon Hall72cf1dc2014-10-20 21:04:50 -04001138
1139
1140
1141
1142 def compare_links(self, topo, links_json):
1143 '''
1144 Compare mn and onos links
1145 topo: sts TestONTopology object
1146 links_json: parsed json object from the onos links api
1147
1148 This uses the sts TestONTopology object
1149
1150 '''
Jon Hall1c9e8732014-10-27 19:29:27 -04001151 #FIXME: this does not look for extra links in ONOS, only checks that ONOS has what is in MN
Jon Hall72cf1dc2014-10-20 21:04:50 -04001152 import json
1153 link_results = main.TRUE
1154 output = {"switches":[]}
1155 onos = links_json
1156 for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
Jon Hall38481722014-11-04 16:50:05 -05001157 # print "Iterating though switches as seen by Mininet"
1158 # print switch
Jon Hall72cf1dc2014-10-20 21:04:50 -04001159 ports = []
1160 for port in switch.ports.values():
1161 #print port.hw_addr.toStr(separator = '')
1162 ports.append({'of_port': port.port_no, 'mac': str(port.hw_addr).replace('\'',''), 'name': port.name})
1163 output['switches'].append({"name": switch.name, "dpid": str(switch.dpid).zfill(16), "ports": ports })
1164 #######Links########
1165
Jon Hall38481722014-11-04 16:50:05 -05001166 mn_links = [link for link in topo.patch_panel.network_links if (link.port1.enabled and link.port2.enabled)]
1167 #print "mn_links:"
1168 #print mn_links
1169 if 2*len(mn_links) == len(onos):
Jon Hall72cf1dc2014-10-20 21:04:50 -04001170 link_results = main.TRUE
1171 else:
1172 link_results = main.FALSE
Jon Hall38481722014-11-04 16:50:05 -05001173 main.log.report("Mininet has %i bidirectional links and ONOS has %i unidirectional links" % (len(mn_links), len(onos) ))
Jon Hall72cf1dc2014-10-20 21:04:50 -04001174
1175
1176 # iterate through MN links and check if an ONOS link exists in both directions
1177 # NOTE: Will currently only show mn links as down if they are cut through STS.
1178 # We can either do everything through STS or wait for up_network_links
1179 # and down_network_links to be fully implemented.
Jon Hall38481722014-11-04 16:50:05 -05001180 for link in mn_links:
Jon Hall72cf1dc2014-10-20 21:04:50 -04001181 #print "Link: %s" % link
1182 #TODO: Find a more efficient search method
1183 node1 = None
1184 port1 = None
1185 node2 = None
1186 port2 = None
1187 first_dir = main.FALSE
1188 second_dir = main.FALSE
1189 for switch in output['switches']:
1190 #print "Switch: %s" % switch['name']
1191 if switch['name'] == link.node1.name:
1192 node1 = switch['dpid']
1193 for port in switch['ports']:
1194 if str(port['name']) == str(link.port1):
1195 port1 = port['of_port']
1196 if node1 is not None and node2 is not None:
1197 break
1198 if switch['name'] == link.node2.name:
1199 node2 = switch['dpid']
1200 for port in switch['ports']:
1201 if str(port['name']) == str(link.port2):
1202 port2 = port['of_port']
1203 if node1 is not None and node2 is not None:
1204 break
1205
1206
1207 for onos_link in onos:
1208 onos_node1 = onos_link['src']['device'].replace(":",'').replace("of", '')
1209 onos_node2 = onos_link['dst']['device'].replace(":",'').replace("of", '')
1210 onos_port1 = onos_link['src']['port']
1211 onos_port2 = onos_link['dst']['port']
1212
1213 #print "Checking ONOS for link %s/%s -> %s/%s and" % (node1, port1, node2, port2)
1214 #print "Checking ONOS for link %s/%s -> %s/%s" % (node2, port2, node1, port1)
1215 # check onos link from node1 to node2
1216 if str(onos_node1) == str(node1) and str(onos_node2) == str(node2):
1217 if int(onos_port1) == int(port1) and int(onos_port2) == int(port2):
1218 first_dir = main.TRUE
1219 else:
Jon Hallb1290e82014-11-18 16:17:48 -05001220 main.log.warn('The port numbers do not match for ' +str(link) +\
Jon Hall72cf1dc2014-10-20 21:04:50 -04001221 ' between ONOS and MN. When cheking ONOS for link '+\
1222 '%s/%s -> %s/%s' % (node1, port1, node2, port2)+\
1223 ' ONOS has the values %s/%s -> %s/%s' %\
1224 (onos_node1, onos_port1, onos_node2, onos_port2))
1225
1226 # check onos link from node2 to node1
1227 elif ( str(onos_node1) == str(node2) and str(onos_node2) == str(node1) ):
1228 if ( int(onos_port1) == int(port2) and int(onos_port2) == int(port1) ):
1229 second_dir = main.TRUE
1230 else:
Jon Hallb1290e82014-11-18 16:17:48 -05001231 main.log.warn('The port numbers do not match for ' +str(link) +\
Jon Hall72cf1dc2014-10-20 21:04:50 -04001232 ' between ONOS and MN. When cheking ONOS for link '+\
1233 '%s/%s -> %s/%s' % (node2, port2, node1, port1)+\
1234 ' ONOS has the values %s/%s -> %s/%s' %\
1235 (onos_node2, onos_port2, onos_node1, onos_port1))
1236 else:#this is not the link you're looking for
1237 pass
1238 if not first_dir:
1239 main.log.report('ONOS does not have the link %s/%s -> %s/%s' % (node1, port1, node2, port2))
1240 if not second_dir:
1241 main.log.report('ONOS does not have the link %s/%s -> %s/%s' % (node2, port2, node1, port1))
1242 link_results = link_results and first_dir and second_dir
Jon Hall62df9242014-10-22 12:20:17 -04001243 return link_results
Jon Hall72cf1dc2014-10-20 21:04:50 -04001244
1245
andrewonlab3f0a4af2014-10-17 12:25:14 -04001246 def get_hosts(self):
1247 '''
1248 Returns a list of all hosts
1249 Don't ask questions just use it
1250 '''
1251 self.handle.sendline("")
1252 self.handle.expect("mininet>")
1253
1254 self.handle.sendline("py [ host.name for host in net.hosts ]")
1255 self.handle.expect("mininet>")
admin2a9548d2014-06-17 14:08:07 -07001256
andrewonlab3f0a4af2014-10-17 12:25:14 -04001257 handle_py = self.handle.before
1258 handle_py = handle_py.split("]\r\n",1)[1]
1259 handle_py = handle_py.rstrip()
admin2a9548d2014-06-17 14:08:07 -07001260
andrewonlab3f0a4af2014-10-17 12:25:14 -04001261 self.handle.sendline("")
1262 self.handle.expect("mininet>")
admin2a9548d2014-06-17 14:08:07 -07001263
andrewonlab3f0a4af2014-10-17 12:25:14 -04001264 host_str = handle_py.replace("]", "")
1265 host_str = host_str.replace("'", "")
1266 host_str = host_str.replace("[", "")
1267 host_list = host_str.split(",")
1268
1269 return host_list
adminbae64d82013-08-01 10:50:15 -07001270
Jon Hall38481722014-11-04 16:50:05 -05001271
1272 def update(self):
1273 '''
1274 updates the port address and status information for each port in mn
1275 '''
1276 #TODO: Add error checking. currently the mininet command has no output
1277 main.log.info("Updateing MN port information")
Jon Hallb1290e82014-11-18 16:17:48 -05001278 try:
1279 self.handle.sendline("")
1280 self.handle.expect("mininet>")
Jon Hall38481722014-11-04 16:50:05 -05001281
Jon Hallb1290e82014-11-18 16:17:48 -05001282 self.handle.sendline("update")
1283 self.handle.expect("update")
1284 self.handle.expect("mininet>")
Jon Hall38481722014-11-04 16:50:05 -05001285
Jon Hallb1290e82014-11-18 16:17:48 -05001286 self.handle.sendline("")
1287 self.handle.expect("mininet>")
Jon Hall38481722014-11-04 16:50:05 -05001288
Jon Hallb1290e82014-11-18 16:17:48 -05001289 return main.TRUE
1290 except pexpect.EOF:
1291 main.log.error(self.name + ": EOF exception found")
1292 main.log.error(self.name + ": " + self.handle.before)
1293 main.cleanup()
1294 main.exit()
1295
1296 def cli_sanity(self):
1297 '''
1298 Sends control c to cli and expexts the output
1299 Test to make sure the session is working correctly
1300 Returns main.TRUE on success
1301 '''
1302 import re
1303 #NOTE: Send ctrl-c to make sure pingall is done
1304 print '*'*10 + "Pexpect session sanity check" + '*'*10
1305 self.handle.send("\x03")
1306 #self.handle.sendline("l")
1307 response = ''
1308 while self.handle.expect([pexpect.TIMEOUT, "mininet>"],timeout=1):
1309 print repr(self.handle.before)
1310 if not response:
1311 response = self.handle.before
1312 print repr(self.handle.after)
1313 if re.search("Interrupt", response):
1314 print "MN pexpect session Looks good to me"
1315 return main.TRUE
1316 else:
1317 print "Something isn't right with MN pexpect session"
1318 return main.FALSE
1319
Jon Hall38481722014-11-04 16:50:05 -05001320
adminbae64d82013-08-01 10:50:15 -07001321if __name__ != "__main__":
1322 import sys
1323 sys.modules[__name__] = MininetCliDriver()
admin2a9548d2014-06-17 14:08:07 -07001324