Update: commiting the latest onosclidriver
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 5deb911..baed719 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -19,6 +19,8 @@
import sys
import pexpect
import re
+import json
+import types
sys.path.append( "../" )
from drivers.common.clidriver import CLI
@@ -29,6 +31,9 @@
"""
Initialize client
"""
+ self.name = None
+ self.home = None
+ self.handle = None
super( CLI, self ).__init__()
def connect( self, **connectargs ):
@@ -38,11 +43,13 @@
try:
for key in connectargs:
vars( self )[ key ] = connectargs[ key ]
- self.home = "~/ONOS"
+ self.home = "~/onos"
for key in self.options:
if key == "home":
self.home = self.options[ 'home' ]
break
+ if self.home is None or self.home == "":
+ self.home = "~/onos"
self.name = self.options[ 'name' ]
self.handle = super( OnosCliDriver, self ).connect(
@@ -67,7 +74,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -76,27 +83,25 @@
"""
Called when Test is complete to disconnect the ONOS handle.
"""
- response = ''
+ response = main.TRUE
try:
- self.handle.sendline( "" )
- i = self.handle.expect( [ "onos>", "\$" ] )
- if i == 0:
- self.handle.sendline( "system:shutdown" )
- self.handle.expect( "Confirm" )
- self.handle.sendline( "yes" )
- self.handle.expect( "\$" )
- self.handle.sendline( "" )
- self.handle.expect( "\$" )
- self.handle.sendline( "exit" )
- self.handle.expect( "closed" )
-
+ if self.handle:
+ i = self.logout()
+ if i == main.TRUE:
+ self.handle.sendline( "" )
+ self.handle.expect( "\$" )
+ self.handle.sendline( "exit" )
+ self.handle.expect( "closed" )
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
- return None
+ response = main.FALSE
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
main.log.error( self.name + ": " + self.handle.before )
- except:
+ except ValueError:
+ main.log.exception( "Exception in discconect of " + self.name )
+ response = main.TRUE
+ except Exception:
main.log.exception( self.name + ": Connection failed to the host" )
response = main.FALSE
return response
@@ -104,28 +109,38 @@
def logout( self ):
"""
Sends 'logout' command to ONOS cli
+ Returns main.TRUE if exited CLI and
+ main.FALSE on timeout (not guranteed you are disconnected)
+ None on TypeError
+ Exits test on unknown error or pexpect exits unexpectedly
"""
try:
- self.handle.sendline( "" )
- i = self.handle.expect( [
- "onos>",
- "\$" ], timeout=10 )
- if i == 0:
- self.handle.sendline( "logout" )
- self.handle.expect( "\$" )
- elif i == 1:
+ if self.handle:
+ self.handle.sendline( "" )
+ i = self.handle.expect( [ "onos>", "\$", pexpect.TIMEOUT ],
+ timeout=10 )
+ if i == 0: # In ONOS CLI
+ self.handle.sendline( "logout" )
+ self.handle.expect( "\$" )
+ return main.TRUE
+ elif i == 1: # not in CLI
+ return main.TRUE
+ elif i == 3: # Timeout
+ return main.FALSE
+ else:
return main.TRUE
-
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 )
+ main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except ValueError:
+ main.log.error( self.name +
+ "ValueError exception in logout method" )
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -146,12 +161,12 @@
# Expect the cellname in the ONOSCELL variable.
# Note that this variable name is subject to change
# and that this driver will have to change accordingly
- self.handle.expect( "ONOS_CELL=" + str( cellname ) )
+ self.handle.expect(str(cellname))
handleBefore = self.handle.before
handleAfter = self.handle.after
# Get the rest of the handle
- self.handle.sendline( "" )
- self.handle.expect( "\$" )
+ self.handle.sendline("")
+ self.handle.expect("\$")
handleMore = self.handle.before
main.log.info( "Cell call returned: " + handleBefore +
@@ -167,14 +182,14 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
def startOnosCli( self, ONOSIp, karafTimeout="" ):
"""
- karafTimeout is an optional arugument. karafTimeout value passed
+ karafTimeout is an optional argument. karafTimeout value passed
by user would be used to set the current karaf shell idle timeout.
Note that when ever this property is modified the shell will exit and
the subsequent login would reflect new idle timeout.
@@ -245,7 +260,40 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+
+ def log( self, cmdStr, level="" ):
+ """
+ log the commands in the onos CLI.
+ returns main.TRUE on success
+ returns main.FALSE if Error occurred
+ Available level: DEBUG, TRACE, INFO, WARN, ERROR
+ Level defaults to INFO
+ """
+ try:
+ lvlStr = ""
+ if level:
+ lvlStr = "--level=" + level
+
+ self.handle.sendline( "" )
+ 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
+ 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()
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -260,28 +308,31 @@
sent using this method.
"""
try:
- self.handle.sendline( "" )
- self.handle.expect( "onos>" )
-
- self.handle.sendline( "log:log \"Sending CLI command: '"
- + cmdStr + "'\"" )
- self.handle.expect( "onos>" )
+ logStr = "\"Sending CLI command: '" + cmdStr + "'\""
+ self.log( logStr )
self.handle.sendline( cmdStr )
- self.handle.expect( "onos>" )
+ i = self.handle.expect( ["onos>", "\$", pexpect.TIMEOUT] )
+ response = self.handle.before
+ if i == 2:
+ self.handle.sendline()
+ self.handle.expect( "\$" )
+ response += self.handle.before
+ print response
+ try:
+ print self.handle.after
+ except:
+ pass
+ # TODO: do something with i
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
- 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]
-
-
+ response = ansiEscape.sub( '', response )
+ # Remove extra return chars that get added
+ response = re.sub( r"\s\r", "", response )
+ response = response.strip()
+ # parse for just the output, remove the cmd from response
+ output = response.split( cmdStr, 1 )[1]
return output
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
@@ -291,7 +342,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -331,7 +382,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -359,21 +410,29 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
- def nodes( self ):
+ def nodes( self, jsonFormat=True):
"""
List the nodes currently visible
Issues command: 'nodes'
- Returns: entire handle of list of nodes
+ Optional argument:
+ * jsonFormat - boolean indicating if you want output in json
"""
try:
- cmdStr = "nodes"
- handle = self.sendline( cmdStr )
- return handle
+ if jsonFormat:
+ cmdStr = "nodes -j"
+ output = self.sendline( cmdStr )
+ ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
+ parsedOutput = ansiEscape.sub( '', output )
+ return parsedOutput
+ else:
+ cmdStr = "nodes"
+ output = self.sendline( cmdStr )
+ return output
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -382,21 +441,24 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
def topology( self ):
"""
- Shows the current state of the topology
- by issusing command: 'onos> onos:topology'
+ Definition:
+ Returns the ouput of topology command.
+ Return:
+ topology = current ONOS topology
"""
+ import json
try:
# either onos:topology or 'topology' will work in CLI
- cmdStr = "onos:topology"
+ cmdStr = "topology -j"
handle = self.sendline( cmdStr )
- main.log.info( "onos:topology returned: " + str( handle ) )
+ main.log.info( "topology -j returned: " + str( handle ) )
return handle
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
@@ -406,7 +468,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -431,7 +493,7 @@
main.log.report( "Exiting test" )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.log.report( "Failed to install feature" )
main.log.report( "Exiting test" )
@@ -444,9 +506,15 @@
by issuing command: 'onos> feature:uninstall <feature_str>'
"""
try:
- cmdStr = "feature:uninstall " + str( featureStr )
- self.sendline( cmdStr )
- # TODO: Check for possible error responses from karaf
+ cmdStr = 'feature:list -i | grep "' + featureStr + '"'
+ handle = self.sendline( cmdStr )
+ if handle != '':
+ cmdStr = "feature:uninstall " + str( featureStr )
+ self.sendline( cmdStr )
+ # TODO: Check for possible error responses from karaf
+ else:
+ main.log.info( "Feature needs to be installed before " +
+ "uninstalling it" )
return main.TRUE
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
@@ -456,11 +524,36 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
+ def deviceRemove( self, deviceId ):
+ """
+ Removes particular device from storage
+
+ TODO: refactor this function
+ """
+ try:
+ cmdStr = "device-remove "+str(deviceId)
+ handle = self.sendline( cmdStr )
+ return main.TRUE
+ 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 )
+ main.cleanup()
+ main.exit()
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+
+
+
def devices( self, jsonFormat=True ):
"""
Lists all infrastructure devices or switches
@@ -499,7 +592,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -523,7 +616,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -566,7 +659,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -589,7 +682,7 @@
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:
+ sequence using the following commands:
ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
handle1 = ansiEscape.sub( '', handle )
@@ -610,7 +703,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -656,7 +749,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -673,7 +766,6 @@
None if no match
"""
try:
- import json
if deviceId is None:
return None
else:
@@ -693,7 +785,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -705,7 +797,6 @@
main.FALSE any device has no master
"""
try:
- import json
rawRoles = self.roles()
rolesJson = json.loads( rawRoles )
# search json for the device with id then return the device
@@ -724,7 +815,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -752,7 +843,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -795,7 +886,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -804,12 +895,11 @@
"""
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
+ Note: mac must be a colon separated mac address, but could be a
partial mac address
Return None if there is no match
"""
- import json
try:
if mac is None:
return None
@@ -833,7 +923,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -875,7 +965,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -886,8 +976,10 @@
* hostIdOne: ONOS host id for host1
* hostIdTwo: ONOS host id for host2
Description:
- Adds a host-to-host intent ( bidrectional ) by
+ Adds a host-to-host intent ( bidirectional ) by
specifying the two hosts.
+ Returns:
+ A string of the intent id or None on Error
"""
try:
cmdStr = "add-host-intent " + str( hostIdOne ) +\
@@ -895,12 +987,19 @@
handle = self.sendline( cmdStr )
if re.search( "Error", handle ):
main.log.error( "Error in adding Host intent" )
- return handle
+ main.log.debug( "Response from ONOS was: " + repr( 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" )
+ main.log.debug( "Response from ONOS was: " +
+ repr( handle ) )
+ return None
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -909,7 +1008,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -921,6 +1020,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 ) +\
@@ -928,9 +1031,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
@@ -939,7 +1051,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -979,14 +1091,14 @@
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
intent via cli
"""
try:
- cmd = ""
-
# If there are no optional arguments
if not ethType and not ethSrc and not ethDst\
and not bandwidth and not lambdaAlloc \
@@ -1024,10 +1136,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 ) + "/" +\
@@ -1037,20 +1150,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
@@ -1059,17 +1181,16 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
def addMultipointToSinglepointIntent(
self,
- ingressDevice1,
- ingressDevice2,
+ ingressDeviceList,
egressDevice,
- portIngress="",
+ portIngressList=None,
portEgress="",
ethType="",
ethSrc="",
@@ -1085,12 +1206,13 @@
setEthDst="" ):
"""
Note:
- This function assumes that there would be 2 ingress devices and
- one egress device. For more number of ingress devices, this
- function needs to be modified
+ This function assumes the format of all ingress devices
+ is same. That is, all ingress devices include port nos
+ with a "/" or all ingress devices could specify device
+ ids and port nos seperately.
Required:
- * ingressDevice1: device id of ingress device1
- * ingressDevice2: device id of ingress device2
+ * ingressDeviceList: List of device ids of ingress device
+ ( Atleast 2 ingress devices required in the list )
* egressDevice: device id of egress device
Optional:
* ethType: specify ethType
@@ -1109,14 +1231,14 @@
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
+ options developers provide for multipoint-to-singlepoint
intent via cli
"""
try:
- cmd = ""
-
# If there are no optional arguments
if not ethType and not ethSrc and not ethDst\
and not bandwidth and not lambdaAlloc\
@@ -1155,31 +1277,22 @@
# Check whether the user appended the port
# or provided it as an input
- if "/" in ingressDevice1:
- cmd += " " + str( ingressDevice1 )
+
+ if portIngressList is None:
+ for ingressDevice in ingressDeviceList:
+ if "/" in ingressDevice:
+ cmd += " " + str( ingressDevice )
+ else:
+ main.log.error( "You must specify " +
+ "the ingress port" )
+ # TODO: perhaps more meaningful return
+ return main.FALSE
else:
- if not portIngress1:
- main.log.error( "You must specify " +
- "the ingress port1" )
- # TODO: perhaps more meaningful return
- return main.FALSE
-
- cmd += " " + \
- str( ingressDevice1 ) + "/" +\
- str( portIngress1 ) + " "
-
- if "/" in ingressDevice2:
- cmd += " " + str( ingressDevice2 )
- else:
- if not portIngress2:
- main.log.error( "You must specify " +
- "the ingress port2" )
- # TODO: perhaps more meaningful return
- return main.FALSE
-
- cmd += " " + \
- str( ingressDevice2 ) + "/" +\
- str( portIngress2 ) + " "
+ if len( ingressDeviceList ) == len( portIngressList ):
+ for ingressDevice,portIngress in zip( ingressDeviceList,portIngressList ):
+ cmd += " " + \
+ str( ingressDevice ) + "/" +\
+ str( portIngress ) + " "
if "/" in egressDevice:
cmd += " " + str( egressDevice )
@@ -1192,13 +1305,25 @@
cmd += " " +\
str( egressDevice ) + "/" +\
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" +
+ " failed " )
+ return None
+ #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
@@ -1207,21 +1332,31 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
- def removeIntent( self, intentId ):
+ def removeIntent( self, intentId, app='org.onosproject.cli',
+ purge=False, sync=False ):
"""
- Remove intent for specified intent id
+ Remove intent for specified application id and intent id
+ Optional args:-
+ -s or --sync: Waits for the removal before returning
+ -p or --purge: Purge the intent from the store after removal
Returns:
main.False on error and
cli output otherwise
"""
try:
- cmdStr = "remove-intent " + str( intentId )
+ cmdStr = "remove-intent "
+ if purge:
+ cmdStr += " -p"
+ if sync:
+ cmdStr += " -s"
+
+ cmdStr += " " + app + " " + str( intentId )
handle = self.sendline( cmdStr )
if re.search( "Error", handle ):
main.log.error( "Error in removing intent" )
@@ -1237,7 +1372,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1269,7 +1404,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1299,7 +1434,66 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+
+ def getIntentState(self, intentsId, intentsJson=None):
+ """
+ Check intent state.
+ Accepts a single intent ID (string type) or a list of intent IDs.
+ Returns the state(string type) of the id if a single intent ID is
+ accepted.
+ Returns a dictionary with intent IDs as the key and its
+ corresponding states as the values
+ Parameters:
+ intentId: intent ID (string type)
+ intentsJson: parsed json object from the onos:intents api
+ Returns:
+ state = An intent's state- INSTALL,WITHDRAWN etc.
+ stateDict = Dictionary of intent's state. intent ID as the keys and
+ state as the values.
+ """
+ try:
+ state = "State is Undefined"
+ if not intentsJson:
+ intentsJsonTemp = json.loads( self.intents() )
+ else:
+ intentsJsonTemp = json.loads( intentsJson )
+ if isinstance( intentsId, types.StringType ):
+ for intent in intentsJsonTemp:
+ if intentsId == intent['id']:
+ state = intent['state']
+ return state
+ main.log.info( "Cannot find intent ID" + str( intentsId ) +
+ " on the list" )
+ return state
+ elif isinstance( intentsId, types.ListType ):
+ dictList = []
+ for ID in intentsId:
+ stateDict = {}
+ for intents in intentsJsonTemp:
+ if ID == intents['id']:
+ stateDict['state'] = intents['state']
+ stateDict['id'] = ID
+ dictList.append( stateDict )
+ break
+ if len( intentsId ) != len( dictList ):
+ main.log.info( "Cannot find some of the intent ID state" )
+ return dictList
+ else:
+ main.log.info("Invalid intents ID entry")
+ 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 )
+ main.cleanup()
+ main.exit()
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1320,7 +1514,7 @@
else:
cmdStr = "flows"
handle = self.sendline( cmdStr )
- if re.search( "Error\sexecuting\scommand:", handle ):
+ if re.search( "Error:", handle ):
main.log.error( self.name + ".flows() response: " +
str( handle ) )
return handle
@@ -1332,13 +1526,13 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
def pushTestIntents( self, dpidSrc, dpidDst, numIntents,
- numMult="", appId="", report=True ):
+ numMult="", appId="", report=True ):
"""
Description:
Push a number of intents in a batch format to
@@ -1391,7 +1585,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1421,7 +1615,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1442,7 +1636,11 @@
else:
cmdStr = "topology-events-metrics"
handle = self.sendline( cmdStr )
- return handle
+ if handle:
+ return handle
+ else:
+ # Return empty json
+ return '{}'
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -1451,7 +1649,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1470,29 +1668,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:
@@ -1503,7 +1688,27 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+
+ def FlowAddedCount( self, deviceId ):
+ """
+ Determine the number of flow rules for the given device id that are
+ in the added state
+ """
+ try:
+ cmdStr = "flows any " + str( deviceId ) + " | " +\
+ "grep 'state=ADDED' | wc -l"
+ handle = self.sendline( cmdStr )
+ 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 Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1549,7 +1754,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1563,22 +1768,15 @@
list of node id's
"""
try:
- nodesStr = self.nodes()
+ nodesStr = self.nodes( jsonFormat=True )
idList = []
-
+ # Sample nodesStr output
+ # id=local, address=127.0.0.1:9876, state=ACTIVE *
if not nodesStr:
main.log.info( "There are no nodes to get id from" )
return idList
-
- # Sample nodesStr output
- # id=local, address=127.0.0.1:9876, state=ACTIVE *
-
- # Split the string into list by comma
- nodesList = nodesStr.split( "," )
- tempList = [ node for node in nodesList if "id=" in node ]
- for arg in tempList:
- idList.append( arg.split( "id=" )[ 1 ] )
-
+ nodesJson = json.loads( nodesStr )
+ idList = [ node.get('id') for node in nodesJson ]
return idList
except TypeError:
@@ -1589,7 +1787,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1599,7 +1797,6 @@
Return the first device from the devices api whose 'id' contains 'dpid'
Return None if there is no match
"""
- import json
try:
if dpid is None:
return None
@@ -1621,28 +1818,28 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
def checkStatus( self, ip, numoswitch, numolink, logLevel="info" ):
"""
- Checks the number of swithes & links that ONOS sees against the
+ Checks the number of switches & links that ONOS sees against the
supplied values. By default this will report to main.log, but the
- log level can be specifid.
+ log level can be specified.
Params: ip = ip used for the onos cli
numoswitch = expected number of switches
- numlink = expected number of links
+ numolink = expected number of links
logLevel = level to log to. Currently accepts
'info', 'warn' and 'report'
logLevel can
- Returns: main.TRUE if the number of switchs and links are correct,
- main.FALSE if the numer of switches and links is incorrect,
+ Returns: main.TRUE if the number of switches and links are correct,
+ main.FALSE if the number of switches and links is incorrect,
and main.ERROR otherwise
"""
try:
@@ -1653,20 +1850,19 @@
# 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
linkCheck = ( int( links ) == int( numolink ) )
if ( switchCheck and linkCheck ):
# We expected the correct numbers
- output = output + "The number of links and switches match "\
- + "what was expected"
+ 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 matc\
- h what was expected"
+ 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)" % (
@@ -1687,7 +1883,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1730,7 +1926,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1773,7 +1969,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1825,7 +2021,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1866,7 +2062,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1907,7 +2103,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1933,7 +2129,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1959,7 +2155,7 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
@@ -1984,19 +2180,61 @@
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
- except:
+ except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
- def testExceptions( self, obj ):
+ def intentSummary( self ):
"""
- Test exception logging
+ Returns a dictionary containing the current intent states and the count
"""
- # FIXME: Remove this before you commit
-
try:
- return obj[ 'dedf' ]
+ intents = self.intents( )
+ intentStates = []
+ for intent in json.loads( intents ):
+ intentStates.append( intent.get( 'state', None ) )
+ out = [ (i, intentStates.count( i ) ) for i in set( intentStates ) ]
+ main.log.info( dict( out ) )
+ return dict( out )
+ 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 )
+ main.cleanup()
+ main.exit()
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+
+ def leaders( self, jsonFormat=True ):
+ """
+ Returns the output of the leaders command.
+ Optional argument:
+ * jsonFormat - boolean indicating if you want output in json
+ """
+ # FIXME: add json output
+ # Sample JSON
+ # {
+ # "electedTime": "13m ago",
+ # "epoch": 4,
+ # "leader": "10.128.30.17",
+ # "topic": "intent-partition-3"
+ # },
+ try:
+ if jsonFormat:
+ cmdStr = "onos:leaders -j"
+ output = self.sendline( cmdStr )
+ ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
+ cleanedOutput = ansiEscape.sub( '', output )
+ return cleanedOutput
+ else:
+ cmdStr = "onos:leaders"
+ output = self.sendline( cmdStr )
+ return output
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
@@ -2009,3 +2247,71 @@
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
+
+ def pendingMap( self, jsonFormat=True ):
+ """
+ Returns the output of the intent Pending map.
+ """
+ try:
+ if jsonFormat:
+ cmdStr = "onos:intents -p -j"
+ output = self.sendline( cmdStr )
+ ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
+ cleanedOutput = ansiEscape.sub( '', output )
+ return cleanedOutput
+ else:
+ cmdStr = "onos:intents -p"
+ output = self.sendline( cmdStr )
+ return output
+ 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 )
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+
+ def partitions( self, jsonFormat=True ):
+ """
+ Returns the output of the raft partitions command for ONOS.
+ """
+ # Sample JSON
+ # {
+ # "leader": "tcp://10.128.30.11:7238",
+ # "members": [
+ # "tcp://10.128.30.11:7238",
+ # "tcp://10.128.30.17:7238",
+ # "tcp://10.128.30.13:7238",
+ # ],
+ # "name": "p1",
+ # "term": 3
+ # },
+ try:
+ if jsonFormat:
+ cmdStr = "onos:partitions -j"
+ output = self.sendline( cmdStr )
+ ansiEscape = re.compile( r'\r\r\n\x1b[^m]*m' )
+ cleanedOutput = ansiEscape.sub( '', output )
+ return cleanedOutput
+ else:
+ cmdStr = "onos:partitions"
+ output = self.sendline( cmdStr )
+ return output
+ 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 )
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanup()
+ main.exit()
+