Additional work towards application subsystem drivers
- appStatus function
- activateApp function
- deactivateApp function
- uninstallApp function
- refactor PingallExample test to use the new functions
NOTE: PingallExample needs to be cleaned up before merged to master
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index da17a1b..d971471 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -2347,16 +2347,65 @@
main.cleanup()
main.exit()
+ def appStatus( self, appName ):
+ """
+ Uses the onos:apps cli command to return the status of an application.
+ Returns:
+ "ACTIVE" - If app is installed and activated
+ "INSTALLED" - If app is installed and deactivated
+ "UNINSTALLED" - If app is not installed
+ None - on error
+ """
+ # FIXME also use app-ids to see if an uninstalled app is registered?
+ # FIXME "UNREGISTERED"?
+ try:
+ if not isinstance( appName, types.StringType ):
+ main.log.error( self.name + ".appStatus(): appName must be" +
+ " a string" )
+ return None
+ output = self.apps( jsonFormat=True )
+ appsJson = json.loads( output )
+ state = None
+ for app in appsJson:
+ if appName == app.get('name'):
+ state = app.get('state')
+ break
+ if state == "ACTIVE" or state == "INSTALLED":
+ return state
+ elif state is None:
+ return "UNINSTALLED"
+ elif state:
+ main.log.error( "Unexpected state from 'onos:apps': " +
+ str( state ) )
+ return state
+ 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 app( self, appName, option ):
"""
Interacts with the app command for ONOS. This command manages
application inventory.
"""
# Validate argument types
- if isinstance( appName, types.StringType ):
+ valid = True
+ if not isinstance( appName, types.StringType ):
main.log.error( self.name + ".app(): appName must be a string" )
- if isinstance( option, types.StringType ):
- main.log.error( self.name + ".option(): option must be a string" )
+ valid = False
+ if not isinstance( option, types.StringType ):
+ main.log.error( self.name + ".app(): option must be a string" )
+ valid = False
+ if not valid:
+ return main.FALSE
# Validate Option
option = option.lower()
# NOTE: Install may become a valid option
@@ -2369,10 +2418,11 @@
else:
# Invalid option
main.log.error( "The ONOS app command argument only takes the " +
- "values: (activate|deactivate|uninstall)." )
+ "values: (activate|deactivate|uninstall); was " +
+ "given '" + option + "'")
return main.FALSE
try:
- cmdStr = "onos:app" + option + appName
+ cmdStr = "onos:app " + option + " " + appName
output = self.sendline( cmdStr )
# FIXME: look at specific exceptions/Errors
# Some Possible outputs:
@@ -2381,11 +2431,16 @@
if "Error executing command" in output:
main.log.error( "Error in processing onos:app command: " +
str( output ) )
- return main.ERROR
+ return main.FALSE
elif "No such application" in output:
main.log.error( "The application '" + appName +
"' is not installed in ONOS" )
- return main.ERROR
+ return main.FALSE
+ elif "Command not found:" in output:
+ main.log.error( "Error in processing onos:app command: " +
+ str( output ) )
+ return main.FALSE
+
# NOTE: we may need to add more checks here
main.log.debug( "app response: " + str( output ) )
return main.TRUE
@@ -2401,3 +2456,124 @@
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
+
+ def activateApp( self, appName ):
+ """
+ Activate an app that is already installed in ONOS
+ Returns main.TRUE if the command was successfully sent
+ main.FALSE if the cli responded with an error or given
+ incorrect input
+ """
+ try:
+ if not isinstance( appName, types.StringType ):
+ main.log.error( self.name + ".activateApp(): appName must be" +
+ " a string" )
+ return main.FALSE
+ status = self.appStatus( appName )
+ if status == "INSTALLED":
+ response = self.app( appName, "activate" )
+ return response
+ elif status == "ACTIVE":
+ return main.TRUE
+ elif status == "UNINSTALLED":
+ main.log.error( self.name + ": Tried to activate the " +
+ "application '" + appName + "' which is not " +
+ "installed." )
+ else:
+ main.log.error( "Unexpected return value from appStatus: " +
+ str( status ) )
+ return main.ERROR
+ except TypeError:
+ main.log.exception( self.name + ": Object not as expected" )
+ return main.ERROR
+ 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 deactivateApp( self, appName ):
+ """
+ Deactivate an app that is already activated in ONOS
+ Returns main.TRUE if the command was successfully sent
+ main.FALSE if the cli responded with an error or given
+ incorrect input
+ """
+ try:
+ if not isinstance( appName, types.StringType ):
+ main.log.error( self.name + ".deactivateApp(): appName must " +
+ "be a string" )
+ return main.FALSE
+ status = self.appStatus( appName )
+ if status == "INSTALLED":
+ return main.TRUE
+ elif status == "ACTIVE":
+ response = self.app( appName, "deactivate" )
+ return response
+ elif status == "UNINSTALLED":
+ main.log.warn( self.name + ": Tried to deactivate the " +
+ "application '" + appName + "' which is not " +
+ "installed." )
+ return main.TRUE
+ else:
+ main.log.error( "Unexpected return value from appStatus: " +
+ str( status ) )
+ return main.ERROR
+ except TypeError:
+ main.log.exception( self.name + ": Object not as expected" )
+ return main.ERROR
+ 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 uninstallApp( self, appName ):
+ """
+ Uninstall an app that is already installed in ONOS
+ Returns main.TRUE if the command was successfully sent
+ main.FALSE if the cli responded with an error or given
+ incorrect input
+ """
+ # TODO: check with Thomas about the state machine for apps
+ try:
+ if not isinstance( appName, types.StringType ):
+ main.log.error( self.name + ".uninstallApp(): appName must " +
+ "be a string" )
+ return main.FALSE
+ status = self.appStatus( appName )
+ if status == "INSTALLED":
+ response = self.app( appName, "uninstall" )
+ return response
+ elif status == "ACTIVE":
+ main.log.warn( self.name + ": Tried to uninstall the " +
+ "application '" + appName + "' which is " +
+ "currently active." )
+ response = self.app( appName, "uninstall" )
+ return response
+ elif status == "UNINSTALLED":
+ return main.TRUE
+ else:
+ main.log.error( "Unexpected return value from appStatus: " +
+ str( status ) )
+ return main.ERROR
+ except TypeError:
+ main.log.exception( self.name + ": Object not as expected" )
+ return main.ERROR
+ 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()
diff --git a/TestON/tests/PingallExample/PingallExample.params b/TestON/tests/PingallExample/PingallExample.params
index 12bebcd..1e4cfc1 100644
--- a/TestON/tests/PingallExample/PingallExample.params
+++ b/TestON/tests/PingallExample/PingallExample.params
@@ -1,12 +1,12 @@
<PARAMS>
<testcases>1,2,3</testcases>
<ENV>
- <cellName>kelvin</cellName>
+ <cellName>SingleHA</cellName>
</ENV>
<Git>xe</Git>
<CTRL>
- <ip1>10.128.10.21</ip1>
+ <ip1>10.128.30.11</ip1>
<port1>6633</port1>
</CTRL>
</PARAMS>
diff --git a/TestON/tests/PingallExample/PingallExample.py b/TestON/tests/PingallExample/PingallExample.py
index dab380f..5f7334e 100644
--- a/TestON/tests/PingallExample/PingallExample.py
+++ b/TestON/tests/PingallExample/PingallExample.py
@@ -143,7 +143,7 @@
def CASE3( self, main ):
"""
- Assign intents
+ Install forwarding app, Pingall and unistall the app
"""
import time
@@ -152,7 +152,19 @@
# install onos-app-fwd
main.log.info( "Install reactive forwarding app" )
- main.ONOScli1.featureInstall( "onos-app-fwd" )
+ import json
+ main.log.warn(" pretty print json")
+ main.log.debug( json.dumps( json.loads( main.ONOScli1.apps() ),
+ sort_keys=True,
+ indent=4, separators=(',',':') ) )
+ main.log.warn(" get the status of the app")
+ print main.ONOScli1.appStatus( "org.onosproject.fwd" )
+ main.log.warn(" print the standard apps output")
+ main.log.debug( main.ONOScli1.apps( jsonFormat=False ) )
+ main.log.warn(" activate the app")
+ print main.ONOScli1.activateApp( "org.onosproject.fwd" )
+ main.log.warn(" print the standard apps output")
+ main.log.debug( main.ONOScli1.apps( jsonFormat=False ) )
# REACTIVE FWD test
pingResult = main.FALSE
@@ -163,7 +175,16 @@
# uninstall onos-app-fwd
main.log.info( "Uninstall reactive forwarding app" )
- main.ONOScli1.featureUninstall( "onos-app-fwd" )
+ main.log.warn(" print the standard apps output")
+ main.log.debug( main.ONOScli1.apps( jsonFormat=False ) )
+ main.log.warn(" deactivate the app")
+ print main.ONOScli1.deactivateApp( "org.onosproject.fwd" )
+ main.log.warn(" print the standard apps output")
+ main.log.debug( main.ONOScli1.apps( jsonFormat=False ) )
+ main.log.warn(" uninstall the app")
+ print main.ONOScli1.uninstallApp( "org.onosproject.fwd" )
+ main.log.warn(" print the standard apps output")
+ main.log.debug( main.ONOScli1.apps( jsonFormat=False ) )
utilities.assert_equals( expect=main.TRUE, actual=pingResult,
onpass="All hosts are reachable",
diff --git a/TestON/tests/PingallExample/PingallExample.topo b/TestON/tests/PingallExample/PingallExample.topo
index dba7a5d..3eda540 100644
--- a/TestON/tests/PingallExample/PingallExample.topo
+++ b/TestON/tests/PingallExample/PingallExample.topo
@@ -2,7 +2,7 @@
<COMPONENT>
<ONOSbench>
- <host>10.128.10.20</host>
+ <host>10.128.30.10</host>
<user>admin</user>
<password></password>
<type>OnosDriver</type>
@@ -11,7 +11,7 @@
</ONOSbench>
<ONOScli1>
- <host>10.128.10.20</host>
+ <host>10.128.30.10</host>
<user>admin</user>
<password></password>
<type>OnosCliDriver</type>
@@ -20,7 +20,7 @@
</ONOScli1>
<ONOS1>
- <host>10.128.10.21</host>
+ <host>10.128.30.11</host>
<user>admin</user>
<password></password>
<type>OnosDriver</type>
@@ -29,7 +29,7 @@
</ONOS1>
<Mininet1>
- <host>10.128.10.20</host>
+ <host>10.128.30.9</host>
<user>admin</user>
<password></password>
<type>MininetCliDriver</type>