Merge pull request #83 from opennetworkinglab/devl/driver_changes
Devl/driver changes
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index fbd863e..8399546 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -83,7 +83,7 @@
self.user_name +
"@" +
self.ip_address )
- msin.log.error( "Failed to connect to the Mininet CLI" )
+ main.log.error( "Failed to connect to the Mininet CLI" )
return main.FALSE
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
@@ -957,6 +957,8 @@
return main.TRUE
def getVersion( self ):
+ #FIXME: What uses this? This should be refactored to get
+ # version from MN and not some other file
fileInput = path + '/lib/Mininet/INSTALL'
version = super( Mininet, self ).getVersion()
pattern = 'Mininet\s\w\.\w\.\w\w*'
@@ -1499,12 +1501,12 @@
# print "mn"
# print json.dumps( output,
- # sortKeys=True,
+ # sort_keys=True,
# indent=4,
# separators=( ',', ': ' ) )
# print "onos"
# print json.dumps( switchesJson,
- # sortKeys=True,
+ # sort_keys=True,
# indent=4,
# separators=( ',', ': ' ) )
@@ -1798,6 +1800,71 @@
linkResults = linkResults and firstDir and secondDir
return linkResults
+ def compareHosts( self, topo, hostsJson ):
+ """
+ Compare mn and onos Hosts.
+ Since Mininet hosts are quiet, ONOS will only know of them when they
+ speak. For this reason, we will only check that the hosts in ONOS
+ stores are in Mininet, and not vice versa.
+ topo: sts TestONTopology object
+ hostsJson: parsed json object from the onos hosts api
+
+ This uses the sts TestONTopology object"""
+ import json
+ hostResults = main.TRUE
+ hosts = []
+ # iterate through the MN topology and pull out hosts
+ for mnHost in topo.graph.hosts:
+ interfaces = []
+ for intf in mnHost.interfaces:
+ interfaces.append( {
+ "name": intf.name, # str
+ "ips": [ str( ip ) for ip in intf.ips ], # list of IPAddrs
+ # hw_addr is of type EthAddr, Not JSON serializable
+ "hw_addr": str( intf.hw_addr ) } )
+ hosts.append( {
+ "name": mnHost.name, # str
+ "interfaces": interfaces } ) # list
+ for onosHost in hostsJson:
+ onosMAC = onosHost[ 'mac' ].lower()
+ match = False
+ for mnHost in hosts:
+ for mnIntf in mnHost[ 'interfaces' ]:
+ if onosMAC == mnIntf[ 'hw_addr' ].lower() :
+ match = True
+ for ip in mnIntf[ 'ips' ]:
+ if ip in onosHost[ 'ips' ]:
+ pass # all is well
+ else:
+ # misssing ip
+ main.log.error( "ONOS host " + onosHost[ 'id' ]
+ + " has a different IP than " +
+ "the Mininet host." )
+ output = json.dumps(
+ onosHost,
+ sort_keys=True,
+ indent=4,
+ separators=( ',', ': ' ) )
+ main.log.info( output )
+ hostResults = main.FALSE
+ if not match:
+ hostResults = main.FALSE
+ main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " +
+ "corresponding Mininet host." )
+ output = json.dumps( onosHost,
+ sort_keys=True,
+ indent=4,
+ separators=( ',', ': ' ) )
+ main.log.info( output )
+ # DEBUG
+ main.log.debug( "mn hosts" )
+ for h in hosts:
+ main.log.debug( h )
+ main.log.debug( "onos hosts" )
+ main.log.debug( hostsJson )
+ # /DEBUG
+ return hostResults
+
def getHosts( self ):
"""
Returns a list of all hosts
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index e88aab2..3103772 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -43,9 +43,9 @@
if key == "home":
self.home = self.options[ 'home' ]
break
- if self.home == None or self.home == "":
+ if self.home is None or self.home == "":
self.home = "~/ONOS"
-
+
self.name = self.options[ 'name' ]
self.handle = super( OnosCliDriver, self ).connect(
user_name=self.user_name,
@@ -269,7 +269,7 @@
self.handle.expect( "onos>" )
self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
self.handle.expect( "onos>" )
-
+
response = self.handle.before
if re.search( "Error", response ):
return main.FALSE
@@ -281,9 +281,7 @@
main.cleanup()
main.exit()
except:
- main.log.info( self.name + " ::::::" )
- main.log.error( traceback.print_exc() )
- main.log.info( self.name + " ::::::" )
+ main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -297,25 +295,21 @@
sent using this method.
"""
try:
-
logStr = "\"Sending CLI command: '" + cmdStr + "'\""
self.log( logStr )
self.handle.sendline( cmdStr )
self.handle.expect( "onos>" )
main.log.info( "Command '" + str( cmdStr ) + "' sent to "
+ self.name + "." )
-
handle = self.handle.before
# Remove control strings from output
ansiEscape = re.compile( r'\x1b[^m]*m' )
handle = ansiEscape.sub( '', handle )
- #Remove extra return chars that get added
+ # Remove extra return chars that get added
handle = re.sub( r"\s\r", "", handle )
handle = handle.strip()
# parse for just the output, remove the cmd from handle
output = handle.split( cmdStr, 1 )[1]
-
-
return output
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
@@ -922,6 +916,8 @@
Description:
Adds a host-to-host intent ( bidrectional ) by
specifying the two hosts.
+ Returns:
+ A string of the intent id or None on Error
"""
try:
cmdStr = "add-host-intent " + str( hostIdOne ) +\
@@ -929,16 +925,19 @@
handle = self.sendline( cmdStr )
if re.search( "Error", handle ):
main.log.error( "Error in adding Host intent" )
- return handle
+ return None
else:
main.log.info( "Host intent installed between " +
- str( hostIdOne ) + " and " + str( hostIdTwo ) )
- return main.TRUE
-
+ str( hostIdOne ) + " and " + str( hostIdTwo ) )
+ match = re.search('id=0x([\da-f]+),', handle)
+ if match:
+ return match.group()[3:-1]
+ else:
+ main.log.error( "Error, intent ID not found" )
+ return None
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
-
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
main.log.error( self.name + ": " + self.handle.before )
@@ -956,6 +955,10 @@
* egressDevice: device id of egress device
Optional:
TODO: Still needs to be implemented via dev side
+ Description:
+ Adds an optical intent by specifying an ingress and egress device
+ Returns:
+ A string of the intent id or None on error
"""
try:
cmdStr = "add-optical-intent " + str( ingressDevice ) +\
@@ -963,9 +966,18 @@
handle = self.sendline( cmdStr )
# If error, return error message
if re.search( "Error", handle ):
- return handle
+ main.log.error( "Error in adding Optical intent" )
+ return None
else:
- return main.TRUE
+ main.log.info( "Optical intent installed between " +
+ str( ingressDevice ) + " and " +
+ str( egressDevice ) )
+ match = re.search('id=0x([\da-f]+),', handle)
+ if match:
+ return match.group()[3:-1]
+ else:
+ main.log.error( "Error, intent ID not found" )
+ return None
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -1014,6 +1026,8 @@
Description:
Adds a point-to-point intent ( uni-directional ) by
specifying device id's and optional fields
+ Returns:
+ A string of the intent id or None on error
NOTE: This function may change depending on the
options developers provide for point-to-point
@@ -1059,10 +1073,11 @@
cmd += " " + str( ingressDevice )
else:
if not portIngress:
- main.log.error( "You must specify " +
- "the ingress port" )
+ main.log.error( "You must specify the ingress port" )
# TODO: perhaps more meaningful return
- return main.FALSE
+ # Would it make sense to throw an exception and exit
+ # the test?
+ return None
cmd += " " + \
str( ingressDevice ) + "/" +\
@@ -1072,20 +1087,29 @@
cmd += " " + str( egressDevice )
else:
if not portEgress:
- main.log.error( "You must specify " +
- "the egress port" )
- return main.FALSE
+ main.log.error( "You must specify the egress port" )
+ return None
cmd += " " +\
str( egressDevice ) + "/" +\
str( portEgress )
handle = self.sendline( cmd )
+ # If error, return error message
if re.search( "Error", handle ):
main.log.error( "Error in adding point-to-point intent" )
- return main.FALSE
+ return None
else:
- return main.TRUE
+ # TODO: print out all the options in this message?
+ main.log.info( "Point-to-point intent installed between " +
+ str( ingressDevice ) + " and " +
+ str( egressDevice ) )
+ match = re.search('id=0x([\da-f]+),', handle)
+ if match:
+ return match.group()[3:-1]
+ else:
+ main.log.error( "Error, intent ID not found" )
+ return None
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -1104,7 +1128,8 @@
ingressDevice1,
ingressDevice2,
egressDevice,
- portIngress="",
+ portIngress1="",
+ portIngress2="",
portEgress="",
ethType="",
ethSrc="",
@@ -1144,6 +1169,8 @@
Description:
Adds a multipoint-to-singlepoint intent ( uni-directional ) by
specifying device id's and optional fields
+ Returns:
+ A string of the intent id or None on error
NOTE: This function may change depending on the
options developers provide for multipointpoint-to-singlepoint
@@ -1197,7 +1224,7 @@
main.log.error( "You must specify " +
"the ingress port1" )
# TODO: perhaps more meaningful return
- return main.FALSE
+ return None
cmd += " " + \
str( ingressDevice1 ) + "/" +\
@@ -1210,7 +1237,7 @@
main.log.error( "You must specify " +
"the ingress port2" )
# TODO: perhaps more meaningful return
- return main.FALSE
+ return None
cmd += " " + \
str( ingressDevice2 ) + "/" +\
@@ -1229,11 +1256,23 @@
str( portEgress )
print "cmd= ", cmd
handle = self.sendline( cmd )
+ # If error, return error message
if re.search( "Error", handle ):
- main.log.error( "Error in adding point-to-point intent" )
- return self.handle
+ main.log.error( "Error in adding multipoint-to-singlepoint " +
+ "intent" )
+ return None
else:
- return main.TRUE
+ # TODO: print out all the options in this message?
+ main.log.info( "Multipoint-to-singlepoint intent installed" +
+ " between " + str( ingressDevice1 ) + ", " +
+ str( ingressDevice2 ) + " and " +
+ str( egressDevice ) )
+ match = re.search('id=0x([\da-f]+),', handle)
+ if match:
+ return match.group()[3:-1]
+ else:
+ main.log.error( "Error, intent ID not found" )
+ return None
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -1505,29 +1544,16 @@
"""
try:
# Obtain output of intents function
- intentsStr = self.intents()
- allIntentList = []
+ intentsStr = self.intents(jsonFormat=False)
intentIdList = []
# Parse the intents output for ID's
intentsList = [ s.strip() for s in intentsStr.splitlines() ]
for intents in intentsList:
- if "onos>" in intents:
- continue
- elif "intents" in intents:
- continue
- else:
- lineList = intents.split( " " )
- allIntentList.append( lineList[ 0 ] )
-
- allIntentList = allIntentList[ 1:-2 ]
-
- for intents in allIntentList:
- if not intents:
- continue
- else:
- intentIdList.append( intents )
-
+ match = re.search('id=0x([\da-f]+),', intents)
+ if match:
+ tmpId = match.group()[3:-1]
+ intentIdList.append( tmpId )
return intentIdList
except TypeError:
@@ -1688,7 +1714,7 @@
# 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:
+ if devices is False or links is False:
return main.ERROR
switchCheck = ( int( devices ) == int( numoswitch ) )
# Is the number of links is what we expected
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 328ac0e..f45ad08 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -645,8 +645,10 @@
handleAfter + handleMore )
return main.TRUE
- except pexpect.EOF:
- main.log.error( self.name + ": EOF exception found" )
+ except pexpect.ExceptionPexpect as e:
+ main.log.error( self.name + ": Pexpect exception found of type " +
+ str( type( e ) ) )
+ main.log.error ( e.get_trace() )
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()