Friday, April 10, 2009

Automating Websphere with Maven and WebSphere Administrative Scripting tools

Looking on automating Tuscany iTests to run on the context of a web-container, and for most of Tuscany supported web-containers we had a maven-plugin available such as cargo for Tomcat and Jetty, Geronimo had it's own one, but could not find anything that was supporting WebSphere application server.

Requirement to automate the following tasks with Websphere :
- Start/Stop Server
- Deploy a given application and set specific classloader configuration required by Tuscany
- Start/Stop the application
- Undeploy the application

So started looking into some Websphere documentation, and noticed I could use some phython and decided to get this integration the following way :

Tuscany maven build -> ant scripts -> phython -> websphere admin tools

Below is the phython script that interfaces with the Websphere Admin tools and would provide the actual integration necessary for the automation. The code below should be saved in a file named "wasAdmin.py"


import sys

def getCellName():
"""Return the name of the cell connected to"""
return AdminControl.getCell()

def getNodeName():
"""Return the name of the node connected to"""
return AdminControl.getNode()

def startApplicationOnServer(appName,serverName):
"""Start the named application on one server"""
print "startApplicationOnServer: Entry. appname=%s servername=%s" % ( appName,serverName )
cellName = getCellName()
nodeName = getNodeName()
# Get the application manager
appManager = AdminControl.queryNames('cell=%s,node=%s,type=ApplicationManager,process=%s,*' %(cellName,nodeName,serverName))
print "startApplicationOnServer: appManager=%s" % ( repr(appManager) )
# start it
rc = AdminControl.invoke(appManager, 'startApplication', appName)
print "startApplicationOnServer: Exit. rc=%s" % ( repr(rc) )

def stopApplicationOnServer(appName,serverName):
"""Stop the named application on one server"""
print "stopApplicationOnServer: Entry. appname=%s servername=%s" % ( appName,serverName )
cellName = getCellName()
nodeName = getNodeName()
# Get the application manager
appManager = AdminControl.queryNames('cell=%s,node=%s,type=ApplicationManager,process=%s,*' %(cellName,nodeName,serverName))
print "stopApplicationOnServer: appManager=%s" % ( repr(appManager) )
# start it
rc = AdminControl.invoke(appManager, 'stopApplication', appName)
print "stopApplicationOnServer: Exit. rc=%s" % ( repr(rc) )

def installApplicationOnServer( fileName, appName, contextRoot, serverName ):
"""Install given application on the named server using given context root"""
print "installApplicationOnServer: fileName=%s appName=%s contextRoot=%s ServerName=%s" % ( fileName, appName,contextRoot,serverName )
AdminApp.install(fileName,'[-appname ' + appName + ' -contextroot ' + contextRoot + ' -server ' + serverName + ' -usedefaultbindings ]')
AdminConfig.save()
"""modify classloader model for application"""
deploymentID = AdminConfig.getid('/Deployment:' + appName + '/')
deploymentObject = AdminConfig.showAttribute(deploymentID, 'deployedObject')
classldr = AdminConfig.showAttribute(deploymentObject, 'classloader')
print AdminConfig.showall(classldr)
AdminConfig.modify(classldr, [['mode', 'PARENT_LAST']])
"""Modify WAR class loader model"""
AdminConfig.show(deploymentObject, 'warClassLoaderPolicy')
AdminConfig.modify(deploymentObject, [['warClassLoaderPolicy', 'SINGLE']])
AdminConfig.save()

def uninstallApplicationOnServer( appName ):
"""Delete the named application from the cell"""
AdminApp.uninstall( appName )
AdminConfig.save()



"""-----------------------------------------------------------
Phyton script to interface with WAS Admin/Management Tools
-----------------------------------------------------------"""

if len(sys.argv) < 1:
print "wasAdmin.py : need parameters : functionName [args]"
sys.exit(0)
if(sys.argv[0] == 'installApplicationOnServer'):
installApplicationOnServer(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
elif(sys.argv[0] == 'startApplicationOnServer'):
startApplicationOnServer(sys.argv[1], sys.argv[2])
elif(sys.argv[0] == 'uninstallApplicationOnServer'):
uninstallApplicationOnServer(sys.argv[1])
else:
print "Exiting without doing anything"



Now that we have the Phyton scripts that interfaces with the WebpShpere admin tools ready, we need a way to integrate them with the Tuscany maven build. Let's use ant scripts to do the bridge between maven and phython.
































Now, to integrate this to your project maven build, simply call the ant targets passing the right parameters. Below is a sample maven profile that exercise the automation.



websphere

false


8080
http://127.0.0.1:${http.port}
${env.WAS_HOME}





org.apache.maven.plugins
maven-antrun-plugin
1.1



start-container
pre-integration-test

run









deploy-war
pre-integration-test

run















undeploy-war
post-integration-test

run












stop-container
post-integration-test

run

















Hope this help people in the future. Also, for a working sample, see Tuscany iTests that are automated to run in the context of various web application containers, including Websphere.