Add hosts and get_host command
Initial commit of multinode Test
minor text changes
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index ccf3baf..419ee06 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -808,6 +808,7 @@
'''
import json
+ #main.log.debug("Switches_json string: ", switches_json)
output = {"switches":[]}
for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
#print vars(switch)
@@ -818,7 +819,10 @@
output['switches'].append({"name": switch.name, "dpid": str(switch.dpid).zfill(16), "ports": ports })
#print output
+ #print "mn"
#print json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))
+ #print "onos"
+ #print json.dumps(switches_json, sort_keys=True,indent=4,separators=(',', ': '))
# created sorted list of dpid's in MN and ONOS for comparison
@@ -828,7 +832,7 @@
mnDPIDs.sort()
#print mnDPIDs
if switches_json == "":#if rest call fails
- main.log.error(self.name + ".compare_topo(): Empty JSON object given from ONOS")
+ main.log.error(self.name + ".compare_switches(): Empty JSON object given from ONOS")
return main.FALSE
onos=switches_json
onosDPIDs=[]
@@ -1019,184 +1023,6 @@
return link_results
-
-
- def compare_topo(self, topo, onos_json):
- '''
- compares mn topology with ONOS topology
- onos_list is a list of ONOS controllers, each element of the list should be (handle, name, ip, port)
- onos_json is the output of the onos get_json function calling the /wm/onos/topology REST API
- Returns: True if MN and ONOS topology match and False if the differ.
- Differences between ONOS and MN topology will be printed to the log.
-
- Dependency: Requires STS to be installed on the TestON machine. STS can be pulled
- from https://github.com/ucb-sts/sts.git . Currently the required functions from STS are located in the
- topology_refactoring2 branch, but may be merged into the master branch soon. You may need to install some
- python modules such as networkx to use the STS functions.
-
- To install sts:
- $ git clone git://github.com/ucb-sts/sts.git
- $ cd sts
- $ git clone -b debugger git://github.com/ucb-sts/pox.git
- $ sudo apt-get install python-dev
- $ ./tools/install_hassel_python.sh
- $ sudo pip install networkx
-
- Include sts in your PYTHONPATH. it should looks comething like:
- PYTHONPATH=/home/admin/TestON:/home/admin/sts
-
- '''
- import sys
- sys.path.append("~/sts")
- #NOTE: Create this once per Test and pass the TestONTopology object around. It takes too long to create this object.
- # This will make it easier to use the sts methods for severing links and solve that issue
- import json
-
- link_results = main.TRUE
- switch_results = main.TRUE
- port_results = main.TRUE
-
- ########Switches#######
- output = {"switches":[]}
- for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
- ports = []
- for port in switch.ports.values():
- #print port.hw_addr.toStr(separator = '')
- ports.append({'of_port': port.port_no, 'mac': str(port.hw_addr).replace('\'',''), 'name': port.name})
- output['switches'].append({"name": switch.name, "dpid": str(switch.dpid).zfill(16), "ports": ports })
- #print output
-
- #print json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))
-
-
- # created sorted list of dpid's in MN and ONOS for comparison
- mnDPIDs=[]
- for switch in output['switches']:
- mnDPIDs.append(switch['dpid'])
- mnDPIDs.sort()
- #print mnDPIDs
- if onos_json == "":#if rest call fails
- main.log.error(self.name + ".compare_topo(): Empty JSON object given from ONOS rest call")
- return main.FALSE
- onos=onos_json
- onosDPIDs=[]
- for switch in onos['switches']:
- onosDPIDs.append(switch['dpid'].replace(":",''))
- onosDPIDs.sort()
- #print onosDPIDs
-
- if mnDPIDs!=onosDPIDs:
- switch_results = main.FALSE
- main.log.report( "Switches in MN but not in ONOS:")
- main.log.report( str([switch for switch in mnDPIDs if switch not in onosDPIDs]))
- main.log.report( "Switches in ONOS but not in MN:")
- main.log.report( str([switch for switch in onosDPIDs if switch not in mnDPIDs]))
- else:#list of dpid's match in onos and mn
- switch_results = main.TRUE
-
- ################ports#############
- for switch in output['switches']:
- mn_ports = []
- onos_ports = []
- for port in switch['ports']:
- mn_ports.append(port['of_port'])
- for onos_switch in onos['switches']:
- if onos_switch['dpid'].replace(':','') == switch['dpid']:
- for port in onos_switch['ports']:
- onos_ports.append(port['portNumber'])
- mn_ports.sort()
- onos_ports.sort()
- #print "mn_ports[] = ", mn_ports
- #print "onos_ports90 = ", onos_ports
-
- #if mn_ports == onos_ports:
- #pass #don't set results to true here as this is just one of many checks and it might override a failure
-
- #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.
- #So a short term fix is to ignore the case when mn_port == 65534 and onos_port ==4294967294.
- for mn_port,onos_port in zip(mn_ports,onos_ports):
- if mn_port == onos_port or (mn_port == 65534 and onos_port ==4294967294):
- continue
- else:
- port_results = main.FALSE
- break
- '''
- else: #the ports of this switch don't match
- port_results = main.FALSE
- main.log.report("ports in MN switch %s(%s) but not in ONOS:" % (switch['name'],switch['dpid']))
- main.log.report( str([port for port in mn_ports if port not in onos_ports]))
- main.log.report("ports in ONOS switch %s(%s) but not in MN:" % (switch['name'],switch['dpid']))
- main.log.report( str([port for port in onos_ports if port not in mn_ports]))
- '''
- if port_results == main.FALSE:
- main.log.report("ports in MN switch %s(%s) but not in ONOS:" % (switch['name'],switch['dpid']))
- main.log.report( str([port for port in mn_ports if port not in onos_ports]))
- main.log.report("ports in ONOS switch %s(%s) but not in MN:" % (switch['name'],switch['dpid']))
- main.log.report( str([port for port in onos_ports if port not in mn_ports]))
-
- #######Links########
- # iterate through MN links and check if and ONOS link exists in both directions
- # NOTE: Will currently only show mn links as down if they are cut through STS.
- # We can either do everything through STS or wait for up_network_links
- # and down_network_links to be fully implemented.
- for link in topo.patch_panel.network_links:
- #print "Link: %s" % link
- #TODO: Find a more efficient search method
- node1 = None
- port1 = None
- node2 = None
- port2 = None
- first_dir = main.FALSE
- second_dir = main.FALSE
- for switch in output['switches']:
- if switch['name'] == link.node1.name:
- node1 = switch['dpid']
- for port in switch['ports']:
- if str(port['name']) == str(link.port1):
- port1 = port['of_port']
- if node1 is not None and node2 is not None:
- break
- if switch['name'] == link.node2.name:
- node2 = switch['dpid']
- for port in switch['ports']:
- if str(port['name']) == str(link.port2):
- port2 = port['of_port']
- if node1 is not None and node2 is not None:
- break
- # check onos link from node1 to node2
- for onos_link in onos['links']:
- if onos_link['src']['dpid'].replace(":",'') == node1 and onos_link['dst']['dpid'].replace(":",'') == node2:
- if onos_link['src']['portNumber'] == port1 and onos_link['dst']['portNumber'] == port2:
- first_dir = main.TRUE
- else:
- main.log.report('the port numbers do not match for ' +str(link) + ' between ONOS and MN')
- #print node1, ' to ', node2
- elif onos_link['src']['dpid'].replace(":",'') == node2 and onos_link['dst']['dpid'].replace(":",'') == node1:
- if onos_link['src']['portNumber'] == port2 and onos_link['dst']['portNumber'] == port1:
- second_dir = main.TRUE
- else:
- main.log.report('the port numbers do not match for ' +str(link) + ' between ONOS and MN')
- #print node2, ' to ', node1
- else:#this is not the link you're looking for
- pass
- if not first_dir:
- main.log.report('ONOS has issues with the link from '+str(link.node1.name) +"(dpid: "+ str(node1)+"):"+str(link.port1)+"(portNumber: "+str(port1)+")"+ ' to ' + str(link.node2.name) +"(dpid: "+ str(node2)+"):"+str(link.port2)+"(portNumber: "+str(port2)+")")
- if not second_dir:
- main.log.report('ONOS has issues with the link from '+str(link.node2.name) +"(dpid: "+ str(node2)+"):"+str(link.port2)+"(portNumber: "+str(port2)+")"+ ' to ' + str(link.node1.name) +"(dpid: "+ str(node1)+"):"+str(link.port1)+"(portNumber: "+str(port1)+")")
- link_results = link_results and first_dir and second_dir
-
-
- results = switch_results and port_results and link_results
-# if not results: #To print out both topologies
-# main.log.error("Topology comparison failed, printing json objects, MN then ONOS")
-# main.log.error(str(json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))))
-# main.log.error('MN Links:')
-# for link in topo.patch_panel.network_links: main.log.error(str("\tLink: %s" % link))
-# main.log.error(str(json.dumps(onos, sort_keys=True,indent=4,separators=(',', ': '))))
- return results
-
def get_hosts(self):
'''
Returns a list of all hosts
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 6b7a02e..1caf0ec 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -208,6 +208,8 @@
handle += self.handle.after
main.log.info("Command sent.")
+ ansi_escape = re.compile(r'\x1b[^m]*m')
+ handle = ansi_escape.sub('', handle)
return handle
except pexpect.EOF:
@@ -688,8 +690,95 @@
main.cleanup()
main.exit()
- #TODO:
- #def hosts(self):
+ def hosts(self, json_format=True, grep_str=""):
+ '''
+ Lists all discovered hosts
+ Optional argument:
+ * grep_str - pass in a string to grep
+ '''
+ try:
+ self.handle.sendline("")
+ self.handle.expect("onos>")
+
+ if json_format:
+ if not grep_str:
+ self.handle.sendline("hosts -j")
+ self.handle.expect("hosts -j")
+ self.handle.expect("onos>")
+ else:
+ self.handle.sendline("hosts -j | grep '"+
+ str(grep_str)+"'")
+ self.handle.expect("hosts -j | grep '"+str(grep_str)+"'")
+ 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
+ ansi_escape = re.compile(r'\r\r\n\x1b[^m]*m')
+ handle1 = ansi_escape.sub('', handle)
+ '''
+ #print "repr(handle) =", repr(handle)
+ ansi_escape = re.compile(r'\r\r\n\x1b[^m]*m')
+ handle1 = ansi_escape.sub('', handle)
+ #print "repr(handle1) = ", repr(handle1)
+ return handle1
+ else:
+ if not grep_str:
+ self.handle.sendline("hosts")
+ self.handle.expect("onos>")
+ else:
+ self.handle.sendline("hosts | grep '"+
+ str(grep_str)+"'")
+ self.handle.expect("onos>")
+ handle = self.handle.before
+ print "handle =",handle
+ return handle
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name+" ::::::")
+ main.log.error( traceback.print_exc())
+ main.log.info(self.name+" ::::::")
+ main.cleanup()
+ main.exit()
+
+ def get_host(self, mac):
+ '''
+ Return the first host from the hosts api whose 'id' contains 'mac'
+ Note: mac must be a colon seperated mac address, but could be a partial mac address
+ Return None if there is no match
+ '''
+ import json
+ try:
+ if mac == None:
+ return None
+ else:
+ mac = mac
+ raw_hosts = self.hosts()
+ hosts_json = json.loads(raw_hosts)
+ #search json for the host with mac then return the device
+ for host in hosts_json:
+ print "%s in %s?" % (mac, host['id'])
+ if mac in host['id']:
+ return host
+ return None
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name+" ::::::")
+ main.log.error( traceback.print_exc())
+ main.log.info(self.name+" ::::::")
+ main.cleanup()
+ main.exit()
+
def get_hosts_id(self, host_list):
'''
@@ -1162,4 +1251,65 @@
main.cleanup()
main.exit()
+ def check_status(self, ip, numoswitch, numolink, log_level="info"):
+ '''
+ Checks the number of swithes & links that ONOS sees against the
+ supplied values. By default this will report to main.log, but the
+ log level can be specifid.
+
+ Params: ip = ip used for the onos cli
+ numoswitch = expected number of switches
+ numlink = expected number of links
+ log_level = level to log to. Currently accepts 'info', 'warn' and 'report'
+
+
+ log_level can
+
+ Returns: main.TRUE if the number of switchs and links are correct,
+ main.FALSE if the numer of switches and links is incorrect,
+ and main.ERROR otherwise
+ '''
+
+ try:
+ topology = self.get_topology(ip)
+ if topology == {}:
+ return main.ERROR
+ output = ""
+ #Is the number of switches is what we expected
+ devices = topology.get('devices',False)
+ links = topology.get('links',False)
+ if devices == False or links == False:
+ return main.ERROR
+ switch_check = ( int(devices) == int(numoswitch) )
+ #Is the number of links is what we expected
+ link_check = ( int(links) == int(numolink) )
+ if (switch_check and link_check):
+ #We expected the correct numbers
+ output = output + "The number of links and switches match "\
+ + "what was expected"
+ result = main.TRUE
+ else:
+ output = output + \
+ "The number of links and switches does not match what was expected"
+ result = main.FALSE
+ output = output + "\n ONOS sees %i devices (%i expected) and %i links (%i expected)"\
+ % ( int(devices), int(numoswitch), int(links), int(numolink) )
+ if log_level == "report":
+ main.log.report(output)
+ elif log_level == "warn":
+ main.log.warn(output)
+ else:
+ main.log.info(output)
+ return result
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name+" ::::::")
+ main.log.error( traceback.print_exc())
+ main.log.info(self.name+" ::::::")
+ main.cleanup()
+ main.exit()
#***********************************
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 17b74ec..e924c29 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -366,10 +366,14 @@
self.handle.sendline("export TERM=xterm-256color")
self.handle.expect("xterm-256color")
self.handle.expect("\$")
- self.handle.sendline("cd " + self.home + "; git log -1 --pretty=fuller --decorate=short | grep -A 5 \"commit\" --color=never; cd \.\.")
- self.handle.expect("cd ..")
+ self.handle.sendline("\n")
+ self.handle.expect("\$")
+ self.handle.sendline("cd " + self.home + "; git log -1 --pretty=fuller --decorate=short | grep -A 6 \"commit\" --color=never")
+ self.handle.expect("--color=never")
self.handle.expect("\$")
response=(self.name +": \n"+ str(self.handle.before + self.handle.after))
+ self.handle.sendline("cd " + self.home)
+ self.handle.expect("\$")
lines=response.splitlines()
for line in lines:
print line
@@ -631,10 +635,10 @@
main.log.warn("Network is unreachable")
return main.FALSE
elif i == 1:
- main.log.info("ONOS was installed on the VM and started")
+ main.log.info("ONOS was installed on " + node + " and started")
return main.TRUE
elif i == 2:
- main.log.info("Installation of ONOS on the VM timed out")
+ main.log.info("Installation of ONOS on " + node + " timed out")
return main.FALSE
except pexpect.EOF: