I had a 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
I 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.
<project name="was-integration" default="main" basedir=".">
<property environment="env"/>
<target name="startServer">
<exec dir="." executable="${env.WAS_HOME}/bin/startServer.sh">
<arg value="server1" />
</exec>
</target>
<target name="stopServer">
<exec dir="." executable="${env.WAS_HOME}/bin/stopServer.sh">
<arg value="server1" />
</exec>
</target>
<target name="installApplication">
<exec dir="." executable="${env.WAS_HOME}/bin/wsadmin.sh">
<arg line="-conntype SOAP -lang jython -f ${was.python.script} installApplicationOnServer ${application.war} ${application.name} ${application.contextRoot} ${application.server}" />
</exec>
<exec dir="." executable="${env.WAS_HOME}/bin/wsadmin.sh">
<arg line="-conntype SOAP -lang jython -f ${was.python.script} startApplicationOnServer ${application.name} ${application.server}" />
</exec>
</target>
<target name="uninstallApplication">
<exec dir="." executable="${env.WAS_HOME}/bin/wsadmin.sh">
<arg line="-conntype SOAP -lang jython -f ${was.python.script} uninstallApplicationOnServer ${application.name}" />
</exec>
</target>
</project>
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.
<profile>
<id>websphere</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<http.port>8080</http.port>
<http.base>http://127.0.0.1:${http.port}</http.base>
<websphere.home>${env.WAS_HOME}</websphere.home>
</properties>
<build>
<!--WAS ant integration -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<!-- start Websphere server -->
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<ant antfile="${was.ant.script}" target="startServer"/>
</tasks>
</configuration>
</execution>
<!-- Deploy war application -->
<execution>
<id>deploy-war</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<ant antfile="${was.ant.script}" target="installApplication">
<property name="was.python.script" value="${was.python.script}"/>
<property name="application.war" value="${project.build.directory}/${project.build.finalName}.war"/>
<property name="application.name" value="${project.build.finalName}.war"/>
<property name="application.contextRoot" value="${project.build.finalName}"/>
<property name="application.server" value="server1"/>
</ant>
</tasks>
</configuration>
</execution>
<!-- unDeploy war application -->
<execution>
<id>undeploy-war</id>
<phase>post-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<ant antfile="${was.ant.script}" target="uninstallApplication">
<property name="was.python.script" value="${was.python.script}"/>
<property name="application.name" value="${project.build.finalName}.war"/>
</ant>
</tasks>
</configuration>
</execution>
<!-- Stop Websphere server -->
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<ant antfile="${was.ant.script}" target="stopServer"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
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.
Hi Luciano
ReplyDeleteVery interesting post.I've used your ideas here and can start and stop my appserver.My intention is to deploy a portlet war into a Websphere Portal Server and this requires login.How would one pass the admin username/password?
Hi Luciano, maybe you would find this Mojo valuable http://boss.bekk.no/maven-was-plugin/
ReplyDeleteOr this plugin: http://mojo.codehaus.org/was6-maven-plugin/
ReplyDeletedavidkarlsen, I'm using http://mojo.codehaus.org/was6-maven-plugin/, to deploy my apps. But once that they are deployed, I have to run Administrative Console to set manually the classloader in "Application First" .
ReplyDeleteCan I automatize this step too? I hope your answers.
Regards
There is no [ant] task for that out of the box. However the setting should be preserved if you update instead of reinstall the app. You can provide a custom script for the admintask: http://mojo.codehaus.org/was6-maven-plugin/wsAdmin-mojo.html to script whatever you want in was.
ReplyDeleteBTW: Doing application 1st will eventually lead you into havoc with WAS - be prepared :)
There is no [ant] task for that out of the box. However the setting should be preserved if you update instead of reinstall the app. You can provide a custom script for the admintask: http://mojo.codehaus.org/was6-maven-plugin/wsAdmin-mojo.html to script whatever you want in was.
ReplyDeleteBTW: Doing application 1st will eventually lead you into havoc with WAS - be prepared :)