Need help to update wsadmin script


I have a simple application deployment script that I am working on.  I have most of the functionality working, but completely and to my liking.  

I hope that I can get some help to resolve the flaws.  Once that is completed, I would like to extend the capability to allow a few passable arguments, ie appName, appEARName, backUpPath, etc.

One issue that I am having is that WAS 6.1 is based on Jython 2.1 release so does not have the capability of the datetime

One of the functionality that I want to get is able to generate a backup with the datetime current stamp as part of the file name.  I'm sure that there is a way, I just don't know how to yet...

I am attaching an update of what I have so far.

Thanks all for any help.
# Initial attempt to make some what generic deploy script reusable	#	
# Usage: update variables on top approriately and execute    		#
#						     		#
# Using interactive mode wsadmin>execfile('')			#
# <profilePath>\wsadmin -lang jython -conntype SOAP -f       #
# Use "print AdminApp.options()" for install option details	 	#		    
import sys
nl = "\n"
s = " "
# Input variable values: Please fill in appropriately! 
# Make sure that permission settings are valid for file paths
apphostName = 	"localhost"
appCellName = 	"TWCPU4Node01Cell"		#myCell01
appNodeName = 	"t4node01"			#myNode01
appClusterName= ""				#myCluster01
appServerName = "server1"			#myServer1
appName = 	"myAppEAR"			#myAppEAR
appEARName = 	"/tmp/myApp.ear"		#/some_path/myEAR.ear
appBackUpPath=	"/tmp"				#/some_path/backup
appDeployTarget="server" 			#server or cluster
appEJBopt = 	"yes" 				#yes or no
appEJBdbSchema ='<schemaName>'			#schema1
appEJBdbType =	'<dbType>'			#DB2UDBOS390_V8, etc
appOpts = ""					#set variable to blank	
appDate = "11202008"				#datetime stamp
# Refer to installAppOpts.txt for full list of options
# The following options are used for the group of applications
appOpt01="-installed.ear.destination "
appOpt02="-nopreCompileJSPs "
appOpt03="-distributeApp "
appOpt04="-nouseMetaDataFromBinary "
appOpt05="-nodeployejb "
appOpt06="-deployejb "
appOpt07="-appname " + appName + " "
appOpt08="-createMBeansForResources "
appOpt09="-noreloadEnabled "
appOpt10="-nodeployws "
appOpt11="-validateinstall warn "
appOpt12="-processEmbeddedConfig "
appOpt13="-noprocessEmbeddedConfig "
appOpt14="-filepermission .*\.dll=755#.*\.so=755#.*\.a=755#.*\.sl=755 "
appOpt15="-noallowDispatchRemoteInclude "
appOpt16="-noallowServiceRemoteInclude "
appOpt17="-deployejb.dbtype " + appEJBdbType + " "
appOpt18="-deployejb.dbschema " + appEJBdbSchema + " "
appOptCommon = appOpt02 + appOpt03 + appOpt04 + appOpt07 + appOpt08 + appOpt09 + appOpt10 + appOpt11 + appOpt14 + appOpt15 + appOpt16
print "The following are common options used for the applications: " + nl + appOptCommon + nl
# Calculate partial appOpts for use 'AdminApp.install(filename, options)'
appOpts = appOpts + appOptCommon
if appName == "myWebServiceEAR":
	appOpts = appOpts + appOpt13
	appOpts = appOpts + appOpts12
#end if
print "Current appOpts = " + appOpts
if (appName == "myAppsEAR"):
	appOpts = appOpts + appOpt06
	appOpts = appOpts + appOpt05
#end if
print "The current appOpts options for = " + appName + appOpts
#end if	
# Still having to manually figure out application specific install options
# Get cell information
print "Gathering WebSphere configuration information."
hostName = AdminControl.getHost()
print "Currently connected to " + hostName + "."
# The variable 'hostname' only returns the value of 'localhost' - need to investigate
cell = AdminConfig.list('Cell')
cellName = AdminConfig.showAttribute(cell, 'name')
# Can be used instead if connected to a running process
# cellName = AdminControl.getCell() 
print "Currently connected to " + cellName + " cell."
nodes = AdminConfig.list('Node')
nodeName = AdminConfig.showAttribute(nodes, 'name')
# Can be used only if connected to active process.
# nodeName = AdminControl.getNode()
servers = AdminConfig.list('Server')
serverName = AdminConfig.showAttribute(servers, 'name')
#slist = AdminConfig.showAttribute(servers, 'name').split()
#print slist
print "Currently connected to the following " + serverName + " server process(es) on " + \
  	nodeName + " node(s) in " + cellName + " cell."
# Validation - Incomplete
# Compared input value versus detected values, if mismatch then inform and halt
# Need stuff here
# Check if application exists before proceeding
earFile = appEARName
app = AdminConfig.getid('/Deployment:' + appName + '/')
backUpEAR = appBackUpPath + "/" + appName + appDate +".ear"
if (len(app) > 0):
	print "Exporting backup copy of " + appName + " application, saving as" + backUpEAR
	AdminApp.export(appName, appBackUpPath + "/" + appName + appDate +".ear")
   	print "The application exists, proceed to uninstall current application." + nl
   	print "Installing " + appName + " application." + nl
   	AdminApp.install( earFile, [ appOpts , '-node', nodeName, '-server', serverName] )
   	print "Installing " + appName + " application." + nl
   	AdminApp.install( earFile, [ appOpts , '-node', nodeName, '-server', serverName] )
print "Checking to see if the " + appName + " application is ready to start." 
# Is App Ready?
readyvalue = "false"	
while readyvalue == 'false':
   	readyvalue = AdminApp.isAppReady(appName)
if readyvalue == "true":
	"The " + appName + " is ready for starting."
	print "Starting the " + appName + " application."
	# Debug - seem to be having problems with this block,
	# but the application is still starting after completion??
	#runningApp = AdminControl.queryNames("type=Application,name=" + appName + ",*")
	#if (len(runningApp) > 0):
	#while readyvalue == "true":
		#print "The application is already started?  When did this happen"
	#   	appManager = AdminControl.queryNames("cell=" + cellName + ",node=" + nodeName + ",type=ApplicationManager,process=" + serverName + ",*")  	  	
	#   	while (len(appManager) != 0):
	#   		AdminControl.invoke(appManager, 'startApplication', appName)   	
	print "There was a problem with the installation of the " + appName + " application. " + nl + " Please review logs and output messages."
#end if
#httpPort = AdminControl.getPort(??)
# Need to get application bind to port, ServerIndex??
#a = "To test this on current unit system, open brower to :"
#b = hostName + ":" +httpPort+ "/myApps/myAppServlet?ID=5000"
#c = "The browser test should return '-1' if successful."
#d =  a+ nl + b + c
#print d
# End

Open in new window

Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

HonorGodSoftware EngineerCommented:
Pretty straightforward...
wsadmin>import time
wsadmin>print time.__doc__
This module provides various functions to manipulate time values.
There are two standard representations of time.  One is the number
of seconds since the Epoch, in UTC (a.k.a. GMT).  It may be an integer
or a floating point number (to represent fractions of seconds).
The Epoch is system-defined; on Unix, it is generally January 1st, 1970.
The actual value can be retrieved by calling gmtime(0).
The other representation is a tuple of 9 integers giving local time.
The tuple items are:
  year (four digits, e.g. 1998)
  month (1-12)
  day (1-31)
  hours (0-23)
  minutes (0-59)
  seconds (0-59)
  weekday (0-6, Monday is 0)
  Julian day (day in the year, 1-366)
  DST (Daylight Savings Time) flag (-1, 0 or 1)
If the DST flag is 0, the time is given in the regular time zone;
if it is 1, the time is given in the DST time zone;
if it is -1, mktime() should guess based on the date and time.
timezone -- difference in seconds between UTC and local standard time
altzone -- difference in  seconds between UTC and local DST time
daylight -- whether local time should reflect DST
tzname -- tuple of (standard time zone name, DST time zone name)
time() -- return current time in seconds since the Epoch as a float
clock() -- return CPU time since process start as a float
sleep() -- delay for a number of seconds given as a float
gmtime() -- convert seconds since Epoch to UTC tuple
localtime() -- convert seconds since Epoch to local time tuple
asctime() -- convert time tuple to string
ctime() -- convert time in seconds to string
mktime() -- convert local time tuple to seconds since Epoch
strftime() -- convert time tuple to string according to format specification
strptime() -- parse string to time tuple according to format specification
wsadmin>time.strftime( '%Y-%m-%d', time.localtime() )

Open in new window

hu8myphoAuthor Commented:
I dig some digging and found that this worked.
import time
appDate = time.strftime("%Y%m%d%H%M%S%Z",time.localtime())

I'm having a bit of a problem on these:
nl = "\n"
sl = AdminConfig.getid('/Server:')
nl = AdminConfig.getid('/Node:')

servers = AdminConfig.list('Server')
servers = AdminConfig.list('Server').split()
gives me the list, but I just want the server name

basically, I am able to get the config ID and then the name attribute of that id if there is on 1 (node or server)

serverName = AdminConfig.showAttribute(servers, 'name')
This works only if there is one server.

s1 = sl[0]
s1n = AdminConfig.showAttribute(s1, 'name')
gives me "Incomplete config id: need closing parenthesis "n "dmgr(cells/t4cell/nodes/t4dmnode/servers/dmgr:server.xml#Server_1)

Can you help me with a better way to get the attribute 'name' more than one node and servers ?
HonorGodSoftware EngineerCommented:
The date stuff is just what I showed

Your calls to getid() need to have a closing '/'

sl = AdminConfig.getid('/Server:/')
nl = AdminConfig.getid('/Node:/')

You should note, however, that if your are executing the script while connected to a deployment manager, then the result from the first call can return multiple lines...

So, it would be best if you specified the name of the server. e.g.,

sl = AdminConfig.getid( '/Server:server1/' )

However, this too could return multiple configuration ID's, if you have multiple AppServers,
each on its own node, federated into the same Deployment Manager...

So, you might want to consider something like:

servers = AdminConfig.list( 'Server' ).splitlines()

This will create a list of the server configuration ID's.
If the server name is unique (i.e., only occurs once in the list), you can use
list comprehension to locate it (see the assignment statement to "s1" below).

If you know the name of the node, and the server, then you could use the
getid() method to obtain the configuration ID for exactly that node.

For example, say that you have the name of the node in a local variable named "node",
and the name of the server in a local variable named "server", you could then use

configID = AdminConfig.getid( '/Node:%(node)s/Server:%(server)s/' % locals() )


configID = AdminConfig.getid( '/Node:%s/Server:%s/' % ( node, server ) )


configID = AdminConfig.getid( '/Node:' + node + '/Server:' + server + '/' )
wsadmin>print AdminConfig.getid( '/Server:/' )
wsadmin>servers = AdminConfig.list( 'Server' ).splitlines()
wsadmin>len( servers )
wsadmin>s1 = [ x for x in servers if x.startswith( 'server1' ) ]
wsadmin>len( s1 )
wsadmin>for s in s1 : print s

Open in new window


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
CompTIA Network+

Prepare for the CompTIA Network+ exam by learning how to troubleshoot, configure, and manage both wired and wireless networks.

hu8myphoAuthor Commented:

I can't believe my eyes missed the closing slash '/' the entire time! ~ thanks!

That and the s1 example will get me pass a few obstacles.  Thank you, I will update with results.
HonorGodSoftware EngineerCommented:
Super.  Let me know how it goes...
HonorGodSoftware EngineerCommented:
Is this done yet?  Or is something else needed?
hu8myphoAuthor Commented:
actually i thought that i posted last night but must have lost or not saved.  

I have been able to use the info you provided to to get a list of nodes, servers, clusters, but I am not sure how to just capture the 'name' only instead of the entire ID.

sl = AdminConfig.getid('/Server:/')
nl = AdminConfig.getif('/Node:/')
cl = AdminConfig.getid('/ServerCluster:/')


AdminConfig.showAttribute(sl, 'name') seems to only work for me if there is one of either.

I will posted sample output of interactive cmd if needed.
HonorGodSoftware EngineerCommented:
The easiest way is to realize that the name portion of a configuration ID
(almost) always is the first part of the configID, i.e., up to, and not including
the open parenthesis.  So, you can use something like:

serveName = AdminConfig.getid('/Server:/').split( '(', 1 ) [ 0 ]

The ", 1" tells the split method to make a maximum of 1 split, so it is a
slight "performance" improvement.  Given a configID like:


The result of the split will be a list of 2 elements, the first of which (i.e., [ 0 ])
will be "server1", which is what you want.

Does this help?
HonorGodSoftware EngineerCommented:
On the other hand, if you want a "field" from within the middle of
the configID, you can either use regular expressions to "parse"
the configID string, to extract the value, or you could use this
utility routine I wrote that converts a configID to a dictionary.

Explanation of the code.

Line  Description
   1   Execution of wsadmin, specifying as a routine to be loaded
2-4   Startup messages from wsadmin
   5   Obtain configuration ID of unmanaged node / application server
   6   Statement to display value of serverID variable
   7   Current value of serverID (leading & trailing quotes show that this is a string)
   8   Call to ConfigIdAsDict() routine to process specified configID & return a dictionary
   9   Get the dictionary key names & put them in a list (named "names")
  10  Sort the list of dictionary key names
  11  Use list comprehension to determine the widest key name
  12  For each name in the list
  13  Use a formatted print statement to display the name & value from dictionary
  14  Blank line needed to indicate the end of the "for" statement in line 12
15-18 = Formatted output of dictionary contents...
 1|C:\IBM\WebSphere\AppServer\bin>wsadmin -profile -conntype none
 2|WASX7357I: By request, this scripting client is not connected to any server process. Certain configuration and application opera
 3|tions will be available in local mode.
 4|WASX7031I: For help, enter: "print"
 5|wsadmin>serverID = AdminConfig.list( 'Server' )
 8|wsadmin>dict = ConfigIdAsDict( serverID )
 9|wsadmin>names = dict.keys()
11|wsadmin>width = max( [ len( x ) for x in names ] )
12|wsadmin>for name in names :
13|wsadmin>  print '%*s : %s' % ( width, name, dict[ name ] )
15|   Name : server1
16|  cells : HonorGodNode01Cell
17|  nodes : HonorGodNode00
18|servers : server1

Open in new window
hu8myphoAuthor Commented:
the first option is looks simple to start out with, does the 2nd option handle clusters?
HonorGodSoftware EngineerCommented:
The second can be used for any configurationID.
Notice how the value of the configurationID is shown on line  7, and the
result of using the function to create a dictionary.  The contents of the
dictionary are shown on lines 15-18.

The "Name" element contains the stuff before the open parenthesis,
The "cells" element contains the data that follows "cells" after the '/'
The "nodes" element contains the data that follows "nodes" after the '/'
and the "servers" element contains the data that follows "servers" after the '/', and up to, but not including the '|' portion of the configuration ID.

Does this help?
hu8myphoAuthor Commented:
it does, thank you for your clarification.

What I need now to continue is handle a clustered environment.  I am able stop, start, uninstall and install application on server/node base, I need to expand to handle clusters.  Can you help me on this thread, or should I create a new request?
HonorGodSoftware EngineerCommented:
Since this "topic/question" is stand-alone, it would probably be best to open a new question for that different topic/question.
hu8myphoAuthor Commented:

WASX7015E: Exception running command: "execfile('c:/tmp/')"; exception information: WASX7077E: Incomplete config id: need closing parenthesis
in "WebSphere:name=t4cluster01,process=dmgr,platform=common,node=t4dmnode,version=,type=Clus

something about the statement in the for loop that is giving me this error.
nl = "\n"
appClusterName = "t4cluster01"
targetProcess = "cluster"
cell = AdminConfig.list("Cell")
cellName = AdminConfig.showAttribute(cell, "name")
clist = AdminConfig.list('ServerCluster').splitlines()
if (len(clist) > 0):
	clm = [ x for x in clist if x.startswith( appClusterName)]
	if (len(clm) == 1):
		print clm
	#end if
	clusterID = AdminControl.completeObjectName("cell=" + cellName + ",type=Cluster,name=" + appClusterName +",*")
	print clusterID
	clusterState = AdminControl.getAttribute(clusterID, "state")
	print clusterState
	#if (clusterState.find('stopped')) > 0:
		#print "Error: Cluster "+ appClusterName +" must be started."
	#end if
	clusterMembers = AdminConfig.list("ClusterMember", clusterID)
	print clusterMembers
	clusterMemberList = clusterMembers.split(nl)
	print clusterMemberList
	for clusterMember in clusterMemberList:
		server = clusterMember.rstrip()
		print server
		serverName = AdminConfig.showAttribute(server, "memberName")
		print serverName
		print "Starting Application " + appName + " on Server " + appClusterName
	#end for
#end if

Open in new window

hu8myphoAuthor Commented:
WASX7015E: Exception running command: "execfile('c:/tmp/')"; exception information: WASX7077E: Incomplete config id: need closing parenthesis in "WebSphere:name=t4cluster01,process=dmgr,platform=common,node=t4dmnode,version=,type=Cluster,mbeanIdentifier=t4cluster01,cell=t4cell,spec=1.0"
HonorGodSoftware EngineerCommented:
ok, the line after the wsadmin command prompt must be the output of

  print clm

The next line of text, i.e., the one that starts with "WebSphere:name..."
is the output of your call to AdminControl.completeObjectName()

Remember!  The result of calling AdminControl.completeObjectName() is either an empty string, or an MBean identifier.  

This is the source of your problem.  The error is when you try to call
AdminConfig.list("ClusterMember", clusterID)
and pass an MBean identifier as a configID.

hu8myphoAuthor Commented:
Thanks! I think that did the trick.  Can you give a little validation before I close on this question?
nl = "\n"
appName = "Samples14"
appClusterName = "t4cluster01"
cell = AdminConfig.list("Cell")
cellName = AdminConfig.showAttribute(cell, "name")
clist = AdminConfig.list('ServerCluster').splitlines()
global AdminControl
if (len(clist) > 0):
	clm = [ x for x in clist if x.startswith( appClusterName)]
	if (len(clm) == 0):
		print "The specified cluster: " + appClusterName + " does not exist."
		print "The specified cluster: " + appClusterName + " exists, continuing."
	#end if
	clusterID = AdminConfig.getid('/ServerCluster:' + appClusterName + '/')
	clusterStateID = AdminControl.completeObjectName("cell=" + cellName + ",type=Cluster,name=" + appClusterName +",*")
	clusterState = AdminControl.getAttribute(clusterStateID, "state")
	print "The " + appClusterName + " " + clusterState
	if (clusterState.find('stopped')) > 0:
		print "Error: Cluster "+ appClusterName +" must be started."
	#end if
	clusterMembers = AdminConfig.list("ClusterMember", clusterID)
	clusterMemberList = clusterMembers.split(nl)
	for clusterMember in clusterMemberList:
		server = clusterMember.rstrip()
		serverName = AdminConfig.showAttribute(server, "memberName")
		print "Starting Application " + appName + " on Server " + serverName
		amc = AdminControl.queryNames("cell=" + cellName + ",type=ApplicationManager,process=" + serverName + ",*")
		rc = AdminControl.invoke(amc, 'stopApplication', appName)
		if (rc):
			print "Start Application "+appName+" failed."
			print "Start Application "+appName+" was successful."
	#end for
#end if

Open in new window

HonorGodSoftware EngineerCommented:
Unfortunately, the code to stop an Application, i.e.,

rc = AdminControl.invoke(amc, 'stopApplication', appName)

is wrong (for a couple of reasons).

  It looks like you took the command from the "online documentation".
Unfortunately, it is incomplete, and needs to be fixed.  When AdminControl.invoke()
is used to call an MBean method (e.g., "stopAppliation") and pass 1, or more
parameters, the dataType of each parameter needs to be specified.  So, instead of

rc = AdminControl.invoke( amc, 'stopApplication', appName )

you need to use something like:

rc = AdminControl.invoke(amc, 'stopApplication', appName, 'java.lang.String' )

  The next problem is that the result of calling AdminControl.invoke() for the
'stopApplication' method will not return a "return code" (which I am guessing
what you are expecting). If the call fails, e.g., the specified application does
not exist, an exception is thrown, so what you need to do is something like:

try :
  AdminControl.invoke(amc, 'stopApplication', appName, 'java.lang.String' )
except :
  ( kind, value ) = sys.exc_info()[ :2 ]
  ( kind, value ) = str( kind ), str( value )
  print 'stopApplication failed for: ' + appName
HonorGodSoftware EngineerCommented:
Interesting.  I came back later, and now, I don't seem to need to supply the
'java.lang.String' parameter.  The following is working for me...

I don't yet know why...  still investigating.

wsadmin>AdminControl.invoke( am, 'stopApplication', 'DefaultApplication' )
wsadmin>AdminControl.invoke( am, 'startApplication', 'DefaultApplication' )

Open in new window

HonorGodSoftware EngineerCommented:
Something else that I just noticed.  In line 20, you have:

      if (clusterState.find('stopped')) > 0:

if clusterState == 'stopped' then the result of
clusterState.find( 'stopped' ) == 0 (the index where the string was found).
If you want to test for "not found", then the result needs to be < 0.
find() returns -1 if the specified substring (parameter) is not found in the
given string.
hu8myphoAuthor Commented:
I was checking to see of all of the members of the cluster were already started.  if any member was found to be stopped then I still have to figure out if I should continue with the install or not.  

I still need to consider the same fore the node/server install, if the server is stopped, should I start the server.  I have used the command assistant tool and find that it also adds the java.lang.String but I have tested my code and it does the work.  I don't know if that is the best way but appears to be working for now.

websphere.cluster.stopped  - this is what I'm checking for.
HonorGodSoftware EngineerCommented:
If the nodeagent is stopped, then you can't tell the status of any managed application server.

In order to have a accurate state of the cluster, the nodeagents really need to be active.

Does that make sense?
hu8myphoAuthor Commented:
ahh another that I overlooked, thanks.
HonorGodSoftware EngineerCommented:
Not at all.  That is why it is always good to chat it over with someone whenever possible.
hu8myphoAuthor Commented:
Over the course of time since I started working on this, I have change the structure and style of how I want to implement this.  I am close to completion and have been able to successfully done minor testing in stand alone server and managed server.  I seem to be experiencing a bit of difficulty when trying to test a cluster.
hu8myphoAuthor Commented:
starting app...
The t4cluster01 websphere.cluster.running
Starting Application Samples14 on cluster t4cluster01
WASX7017E: Exception received while running file "\tmp\"; exception information:
.scripting.ScriptingException: WASX7025E: Error found in String ""; cannot create ObjectName.
hu8myphoAuthor Commented:
hu8myphoAuthor Commented:
I think I figured out my problem...
AdminControl.invoke('WebSphere:name=ApplicationManager,process=t4sr01,platform=dynamicproxy,node=t4node01,version=,type=ApplicationManager,mbeanIdentifier=ApplicationManager,cell=t4cell,spec=1.0', 'startApplication', '[Samples14]', '[java.lang.String]')

amc = AdminControl.queryNames("cell=" + cellName + ",type=ApplicationManager,process=" + scopeName + ",*")
rc = AdminControl.invoke(amc, 'startApplication', appName)
now I might need a hand with the solution :-)
hu8myphoAuthor Commented:
ha, figured it out, it was an oops, I fat fingered the 'scopeName' it should have been 'serverName' :-).  So far so good, will update after more tests.
HonorGodSoftware EngineerCommented:
Sounds like you are making progress.

Let me know if there is anything else with which I can help.
hu8myphoAuthor Commented:
Thank you very much for your answers, they have aided me to complete my desired task.
HonorGodSoftware EngineerCommented:
Thank you for the grade & points.  Thank you also for the nice compliments.

Good luck & have a Merry Christmas.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java App Servers

From novice to tech pro — start learning today.