Basic HA Sanity Test
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 9191b89..d4a12cb 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -92,7 +92,7 @@
main.log.info(self.name+": mininet built")
return main.TRUE
if i==1:
- self.handle.expect(["\n",pexpect.EOF,pexpect.TIMEOUT])
+ self.handle.expect(["",pexpect.EOF,pexpect.TIMEOUT])
main.log.info(self.handle.before)
elif i==2:
main.log.error(self.name+": Launching mininet failed...")
@@ -153,26 +153,33 @@
if self.handle :
main.log.info(self.name+": Checking reachabilty to the hosts using pingall")
try:
- response = self.execute(cmd="pingall",prompt="mininet>",timeout=120)
- print "response: " + str(response)
- except pexpect.EOF:
+ response = self.execute(cmd="pingall",prompt="mininet>",timeout=3)
+ except pexpect.EOF:
main.log.error(self.name + ": EOF exception found")
main.log.error(self.name + ": " + self.handle.before)
- #main.cleanup()
- #main.exit()
- pattern = 'Results\:\s0\%\sdropped\s'
- #FIXME:Pending Mininet Pull Request #408
- #pattern = 'Results\:\s0\.00\%\sdropped\s'
- #if utilities.assert_matches(expect=pattern,actual=response,onpass="All hosts are reaching",onfail="Unable to reach all the hosts"):
+ main.cleanup()
+ main.exit()
+ except pexpect.TIMEOUT:
+ #We may not want to kill the test if pexpect times out
+ main.log.error(self.name + ": TIMEOUT exception found")
+ main.log.error(self.name + ": " + str(self.handle.before) )
+ #NOTE: mininet's pingall rounds, so we will check the number of passed and number of failed
+ pattern = "Results\:\s0\%\sdropped\s\((?P<passed>[\d]+)/(?P=passed)"
if re.search(pattern,response):
main.log.info(self.name+": All hosts are reachable")
return main.TRUE
else:
main.log.error(self.name+": Unable to reach all the hosts")
+ main.log.info("Pingall ouput: " + str(response))
+ #NOTE: Send ctrl-c to make sure pingall is done
+ self.handle.send("\x03")
+ self.handle.expect("Interrupt")
+ self.handle.expect("mininet>")
return main.FALSE
else :
main.log.error(self.name+": Connection failed to the host")
- return main.FALSE
+ main.cleanup()
+ main.exit()
def fpingHost(self,**pingParams):
'''
@@ -649,6 +656,187 @@
else:
main.log.info(response)
+ def add_switch( self, sw, **kwargs ):
+ '''
+ adds a switch to the mininet topology
+ NOTE: this uses a custom mn function
+ NOTE: cannot currently specify what type of switch
+ required params:
+ switchname = name of the new switch as a string
+ optional keyvalues:
+ dpid = "dpid"
+ returns: main.FASLE on an error, else main.TRUE
+ '''
+ dpid = kwargs.get('dpid', '')
+ command = "addswitch " + sw + " " + str(dpid)
+ try:
+ response = self.execute(cmd=command,prompt="mininet>",timeout=10)
+ if re.search("already exists!", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("Error", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("usage:", response):
+ main.log.warn(response)
+ return main.FALSE
+ else:
+ return main.TRUE
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+
+ def del_switch( self, sw ):
+ '''
+ delete a switch from the mininet topology
+ NOTE: this uses a custom mn function
+ required params:
+ switchname = name of the switch as a string
+ returns: main.FASLE on an error, else main.TRUE
+ '''
+ command = "delswitch " + sw
+ try:
+ response = self.execute(cmd=command,prompt="mininet>",timeout=10)
+ if re.search("no switch named", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("Error", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("usage:", response):
+ main.log.warn(response)
+ return main.FALSE
+ else:
+ return main.TRUE
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+
+ def add_link( self, node1, node2 ):
+ '''
+ add a link to the mininet topology
+ NOTE: this uses a custom mn function
+ NOTE: cannot currently specify what type of link
+ required params:
+ node1 = the string node name of the first endpoint of the link
+ node2 = the string node name of the second endpoint of the link
+ returns: main.FASLE on an error, else main.TRUE
+ '''
+ command = "addlink " + node1 + " " + node2
+ try:
+ response = self.execute(cmd=command,prompt="mininet>",timeout=10)
+ if re.search("doesnt exist!", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("Error", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("usage:", response):
+ main.log.warn(response)
+ return main.FALSE
+ else:
+ return main.TRUE
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+
+ def del_link( self, node1, node2 ):
+ '''
+ delete a link from the mininet topology
+ NOTE: this uses a custom mn function
+ required params:
+ node1 = the string node name of the first endpoint of the link
+ node2 = the string node name of the second endpoint of the link
+ returns: main.FASLE on an error, else main.TRUE
+ '''
+ command = "dellink " + node1 + " " + node2
+ try:
+ response = self.execute(cmd=command,prompt="mininet>",timeout=10)
+ if re.search("no node named", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("Error", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("usage:", response):
+ main.log.warn(response)
+ return main.FALSE
+ else:
+ return main.TRUE
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+
+ def add_host( self, hostname, **kwargs ):
+ '''
+ Add a host to the mininet topology
+ NOTE: this uses a custom mn function
+ NOTE: cannot currently specify what type of host
+ required params:
+ hostname = the string hostname
+ optional key-value params
+ switch = "switch name"
+ returns: main.FASLE on an error, else main.TRUE
+ '''
+ switch = kwargs.get('switch', '')
+ command = "addhost " + hostname + " " + switch
+ try:
+ response = self.execute(cmd=command,prompt="mininet>",timeout=10)
+ if re.search("already exists!", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("doesnt exists!", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("Error", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("usage:", response):
+ main.log.warn(response)
+ return main.FALSE
+ else:
+ return main.TRUE
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+
+ def del_host( self, hostname ):
+ '''
+ delete a host from the mininet topology
+ NOTE: this uses a custom mn function
+ required params:
+ hostname = the string hostname
+ returns: main.FASLE on an error, else main.TRUE
+ '''
+ command = "delhost " + hostname
+ try:
+ response = self.execute(cmd=command,prompt="mininet>",timeout=10)
+ if re.search("no host named", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("Error", response):
+ main.log.warn(response)
+ return main.FALSE
+ elif re.search("usage:", response):
+ main.log.warn(response)
+ return main.FALSE
+ else:
+ return main.TRUE
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
def disconnect(self):
main.log.info(self.name+": Disconnecting mininet...")
@@ -735,9 +923,10 @@
self.handle.expect("mininet>")
self.handle.sendline("sh sudo tcpdump -n -i "+ intf + " " + port + " -w " + filename.strip() + " &")
self.handle.sendline("")
- self.handle.sendline("")
i=self.handle.expect(['No\ssuch\device','listening\son',pexpect.TIMEOUT,"mininet>"],timeout=10)
main.log.warn(self.handle.before + self.handle.after)
+ self.handle.sendline("")
+ self.handle.expect("mininet>")
if i == 0:
main.log.error(self.name + ": tcpdump - No such device exists. tcpdump attempted on: " + intf)
return main.FALSE
@@ -769,7 +958,7 @@
"pkills tcpdump"
try:
self.handle.sendline("sh sudo pkill tcpdump")
- self.handle.sendline("")
+ self.handle.expect("mininet>")
self.handle.sendline("")
self.handle.expect("mininet>")
except pexpect.EOF:
@@ -857,7 +1046,7 @@
#FIXME: this does not look for extra ports in ONOS, only checks that ONOS has what is in MN
import json
from numpy import uint64
- port_results = main.TRUE
+ ports_results = main.TRUE
output = {"switches":[]}
for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
ports = []
@@ -882,9 +1071,12 @@
for mn_switch in output['switches']:
mn_ports = []
onos_ports = []
+ switch_result = main.TRUE
for port in mn_switch['ports']:
if port['enabled'] == True:
mn_ports.append(port['of_port'])
+ #else: #DEBUG only
+ # main.log.warn("Port %s on switch %s is down" % ( str(port['of_port']) , str(mn_switch['name'])) )
for onos_switch in ports_json:
#print "Iterating through a new switch as seen by ONOS"
#print onos_switch
@@ -894,37 +1086,55 @@
if port['isEnabled']:
#print "Iterating through available ports on the switch"
#print port
- onos_ports.append(int(port['port']))
+ if port['port'] == 'local':
+ #onos_ports.append('local')
+ onos_ports.append(long(uint64(-2)))
+ else:
+ onos_ports.append(int(port['port']))
+ '''
+ else: #This is likely a new reserved port implemented
+ main.log.error("unkown port '" + str(port['port']) )
+ '''
+ else: #DEBUG
+ main.log.warn("Port %s on switch %s is down" % ( str(port['port']) , str(onos_switch['device']['id'])) )
+ break
mn_ports.sort(key=float)
onos_ports.sort(key=float)
#print "\nPorts for Switch %s:" % (switch['name'])
#print "\tmn_ports[] = ", mn_ports
#print "\tonos_ports[] = ", onos_ports
-
- #NOTE:For OF1.3, the OFP_local port number is 0xfffffffe or 4294967294 instead of 0xfffe or 65534 in OF1.0,
- # ONOS topology sees the correct port number, however MN topology as read from line 151 of
- # https://github.com/ucb-sts/sts/blob/topology_refactoring2/sts/entities/teston_entities.py
- # is 0xfffe which doesn't work correctly with OF1.3 switches.
-
- #NOTE: ONOS is abstracting port numbers to 64bit unsigned number(long). So we will be converting the
- # OF reserved ports to these numbers
-
+ mn_ports_log = mn_ports
+ onos_ports_log = onos_ports
+ mn_ports = [x for x in mn_ports]
+ onos_ports = [x for x in onos_ports]
#TODO: handle other reserved port numbers besides LOCAL
- for mn_port,onos_port in zip(mn_ports,onos_ports):
- #print "mn == onos port?"
- #print mn_port, onos_port
- if mn_port == onos_port or (mn_port == 65534 and onos_port == long(uint64(-2))):
- continue
+ #NOTE: Reserved ports
+ # Local port: -2 in Openflow, ONOS shows 'local', we store as long(uint64(-2))
+ for mn_port in mn_ports_log:
+ if mn_port in onos_ports:
#don't set results to true here as this is just one of many checks and it might override a failure
- else: #the ports of this switch don't match
- port_results = main.FALSE
- break
- if port_results == main.FALSE:
+ mn_ports.remove(mn_port)
+ onos_ports.remove(mn_port)
+ #NOTE: OVS reports this as down since there is no link
+ # So ignoring these for now
+ #TODO: Come up with a better way of handling these
+ if 65534 in mn_ports:
+ mn_ports.remove(65534)
+ if long(uint64(-2)) in onos_ports:
+ onos_ports.remove( long(uint64(-2)) )
+ if len(mn_ports): #the ports of this switch don't match
+ switch_result = main.FALSE
+ main.log.warn("Ports in MN but not ONOS: " + str(mn_ports) )
+ if len(onos_ports): #the ports of this switch don't match
+ switch_result = main.FALSE
+ main.log.warn("Ports in ONOS but not MN: " + str(onos_ports) )
+ if switch_result == main.FALSE:
main.log.report("The list of ports for switch %s(%s) does not match:" % (mn_switch['name'], mn_switch['dpid']) )
- main.log.report("mn_ports[] = " + str(mn_ports))
- main.log.report("onos_ports[] = " + str(onos_ports))
- return port_results
+ main.log.warn("mn_ports[] = " + str(mn_ports_log))
+ main.log.warn("onos_ports[] = " + str(onos_ports_log))
+ ports_results = ports_results and switch_result
+ return ports_results
@@ -1007,7 +1217,7 @@
if int(onos_port1) == int(port1) and int(onos_port2) == int(port2):
first_dir = main.TRUE
else:
- main.log.report('The port numbers do not match for ' +str(link) +\
+ main.log.warn('The port numbers do not match for ' +str(link) +\
' between ONOS and MN. When cheking ONOS for link '+\
'%s/%s -> %s/%s' % (node1, port1, node2, port2)+\
' ONOS has the values %s/%s -> %s/%s' %\
@@ -1018,7 +1228,7 @@
if ( int(onos_port1) == int(port2) and int(onos_port2) == int(port1) ):
second_dir = main.TRUE
else:
- main.log.report('The port numbers do not match for ' +str(link) +\
+ main.log.warn('The port numbers do not match for ' +str(link) +\
' between ONOS and MN. When cheking ONOS for link '+\
'%s/%s -> %s/%s' % (node2, port2, node1, port1)+\
' ONOS has the values %s/%s -> %s/%s' %\
@@ -1065,18 +1275,48 @@
'''
#TODO: Add error checking. currently the mininet command has no output
main.log.info("Updateing MN port information")
- self.handle.sendline("")
- self.handle.expect("mininet>")
-
- self.handle.sendline("update")
- self.handle.expect("mininet>")
+ try:
+ self.handle.sendline("")
+ self.handle.expect("mininet>")
- self.handle.sendline("")
- self.handle.expect("mininet>")
+ self.handle.sendline("update")
+ self.handle.expect("update")
+ self.handle.expect("mininet>")
- return main.TRUE
+ self.handle.sendline("")
+ self.handle.expect("mininet>")
-
+ return main.TRUE
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+
+ def cli_sanity(self):
+ '''
+ Sends control c to cli and expexts the output
+ Test to make sure the session is working correctly
+ Returns main.TRUE on success
+ '''
+ import re
+ #NOTE: Send ctrl-c to make sure pingall is done
+ print '*'*10 + "Pexpect session sanity check" + '*'*10
+ self.handle.send("\x03")
+ #self.handle.sendline("l")
+ response = ''
+ while self.handle.expect([pexpect.TIMEOUT, "mininet>"],timeout=1):
+ print repr(self.handle.before)
+ if not response:
+ response = self.handle.before
+ print repr(self.handle.after)
+ if re.search("Interrupt", response):
+ print "MN pexpect session Looks good to me"
+ return main.TRUE
+ else:
+ print "Something isn't right with MN pexpect session"
+ return main.FALSE
+
if __name__ != "__main__":
import sys
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 66dbd23..45bb92e 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -647,25 +647,23 @@
try:
self.handle.sendline("")
self.handle.expect("onos>")
-
+
if json_format:
- if not grep_str:
- self.handle.sendline("roles -j")
- self.handle.expect("roles -j")
- self.handle.expect("onos>")
- else:
- self.handle.sendline("roles -j | grep '"+
- str(grep_str)+"'")
- self.handle.expect("roles -j | grep '"+str(grep_str)+"'")
- self.handle.expect("onos>")
+ self.handle.sendline("roles -j")
+ self.handle.expect("roles -j")
+ self.handle.expect("onos>")
handle = self.handle.before
'''
- handle variable here contains some ANSI escape color code sequences at the end which are invisible in the print command output
- To make that escape sequence visible, use repr() function. The repr(handle) output when printed shows the ANSI escape sequences.
- In json.loads(somestring), this somestring variable is actually repr(somestring) and json.loads would fail with the escape sequence.
- So we take off that escape sequence using the following commads:
+ handle variable here contains some ANSI escape color code sequences at the
+ end which are invisible in the print command output. To make that escape
+ sequence visible, use repr() function. The repr(handle) output when printed
+ shows the ANSI escape sequences. In json.loads(somestring), this somestring
+ variable is actually repr(somestring) and json.loads would fail with the escape
+ sequence.
+
+ So we take off that escape sequence using the following commads:
ansi_escape = re.compile(r'\r\r\n\x1b[^m]*m')
- handle1 = ansi_escape.sub('', handle)
+ handle1 = ansi_escape.sub('', handle)
'''
#print "repr(handle) =", repr(handle)
ansi_escape = re.compile(r'\r\r\n\x1b[^m]*m')
@@ -674,17 +672,10 @@
return handle1
else:
- if not grep_str:
- self.handle.sendline("roles")
- self.handle.expect("onos>")
- self.handle.sendline("")
- self.handle.expect("onos>")
- else:
- self.handle.sendline("roles | grep '"+
- str(grep_str)+"'")
- self.handle.expect("onos>")
- self.handle.sendline("")
- self.handle.expect("onos>")
+ self.handle.sendline("roles")
+ self.handle.expect("onos>")
+ self.handle.sendline("")
+ self.handle.expect("onos>")
handle = self.handle.before
#print "handle =",handle
return handle
@@ -915,12 +906,12 @@
* host_id_two: ONOS host id for host2
Description:
Adds a host-to-host intent (bidrectional) by
- specifying the two hosts.
+ specifying the two hosts.
'''
try:
self.handle.sendline("")
self.handle.expect("onos>")
-
+
self.handle.sendline("add-host-intent "+
str(host_id_one) + " " + str(host_id_two))
self.handle.expect("onos>")
@@ -932,7 +923,7 @@
str(host_id_one) + " and " + str(host_id_two))
return handle
-
+
except pexpect.EOF:
main.log.error(self.name + ": EOF exception found")
main.log.error(self.name + ": " + self.handle.before)
@@ -1160,6 +1151,8 @@
self.handle.expect("flows -j")
self.handle.expect("onos>")
handle = self.handle.before
+ ansi_escape = re.compile(r'\r\r\n\x1b[^m]*m')
+ handle = ansi_escape.sub('', handle)
else:
self.handle.sendline("")
@@ -1167,6 +1160,8 @@
self.handle.sendline("flows")
self.handle.expect("onos>")
handle = self.handle.before
+ if re.search("Error\sexecuting\scommand:", handle):
+ main.log.error(self.name + ".flows() response: " + str(handle))
return handle
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index ca9fa01..19665a4 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -410,7 +410,7 @@
#as xml specific tags that cause errors
line = line.replace("<","[")
line = line.replace(">","]")
- main.log.report(line)
+ main.log.report("\t" + line)
return lines[2]
except pexpect.EOF:
main.log.error(self.name + ": EOF exception found")