Thursday, December 9, 2010

How to start a Node Agent using scripting?

This is a tricky question.  The quick answer is that it can't be done using the typical wsadmin commands.  But it can be done by 'shelling out' from your python script to issue an operating system command.

My colleague and fellow wsadmin contributor Jose Luis provided this Q&A dialog...


1) Is it possible to start the Node agent using wsadmin scripting?

No.

You can not do any operations on a Node agent if it is down. A Node agent must be running in order to work with it.

2) Why don't wsadminlin.py methods such as 'startServer' and 'isServerRunning' work for Node agents?

The job of the node agent is to start and stop servers, and to monitor them.  Under the covers, the wsadmin startServer command asks a running node agent to start servers.  But the node agent can not start itself.  Therefore the 'startServer' command can not start a node agent.

However, method 'isServerRunning' does work on Node agents. It returns True if the node agent is running and False if it is down.

3) How do I start a Node agent that is not running?

Wednesday, December 1, 2010

Request for Feedback

Are you using wsadminlib.py?   Does it work well for you?

Would you like an update with some fixes and new methods?

Please send me a note.  I promise to keep your email private, no spam, no sharing.





Thanks

Thursday, November 11, 2010

Python 'not callable' errors

Be careful not to heist the names of methods in wsadminlib.py...

The python language allows you to dynamically redefine a method to a variable, and vice-versa. This can be a nice feature if you do it intentionally. But it can be a nuisance to debug if unintentional. Here is a quick example:

First, define a method which returns the sum of two numbers:

ding@dingp:~$ python
Python 2.5.2 (r252:60911, Jan 20 2010, 21:48:48)
[GCC 4.2.4 (Ubuntu 4.2.4-1ubuntu3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> def myMethod(i,j):
... return i+j
...
>>>

Pass in two numbers, set the return value to another variable, and it works as expected.

>>> k = myMethod(1,2)
>>> print k
3
>>>


But watch what happens next...

Monday, August 16, 2010

How to set custom properties in Global Security?

Use wsadminlib's method setCustomPropertyOnObject().

Here is the method signature. The parameters are straightforward:

setCustomPropertyOnObject(object_id, propname, propvalue)

The pydoc is pretty good too. If a property with this name does not exist, the method creates it. If one already exists, the method sets the new value.

Here is an example:

sid = getObjectsOfType('Security')[0]
setCustomPropertyOnObject(sid,'andy.propkey','andy.propvalue')
save()


We can then browse to the admin console and see the new custom property in the list.

Extra info:  We can also query the value of a custom property with this method.

getObjectCustomProperty(object_id, propname)

Friday, July 9, 2010

How to handle object-like strings?

Several wsadmin commands return 'object-like' strings as responses. That is, they return strings which look like objects, but are just strings. Very annoying.

We wrote several helper methods in wsadminlib.py to convert these object-like strings into real python lists and dictionaries. The helpers may seem silly at first, but having real objects makes searching and extracting values from responses much easier. Here are two examples...

Example 1

Consider this string:

'[ [key0 value0] [key1 value1] [key2 value2] ]'

This is the format of the response string which you get from several wsadmin commands. To a human, it is visually recognizable as a set of keys and values. But to python, it is nothing. It is a string which is tedious to parse and search, and the code is confusing to duplicate inline in various functional methods. What to do?

Wednesday, May 12, 2010

How to install an application?

Use wsadminlib's method installApplication().

Here is the method signature. The parameter names are straightforward, and the pydoc is pretty good. The list of servers is meant to specify individual non-clustered servers. If a server is part of a cluster, just specify the cluster name.

def installApplication( filename, servers, clusternames, options )

Clusters

First let's install an app on a cluster of servers. Define the name of the ear file, and the name of the cluster. Then install the app, specifying an empty list for individual servers, and no options.

filename = '/tmp/pxyapps.ear'
clusternames = [ 'cluster1' ]
installApplication( filename, [], clusternames, None )


After saving the config, we can browse to the admin console, look at the app's mappings, and see it worked:

Individual servers

Next let's install an app on an individual non-clustered server. Define the server in a list of dictionaries containing the node name and server name. This time we specify an empty list for the clusternames.

Wednesday, April 21, 2010

How to create a cluster and servers?

Use wsadminlib methods createCluster() and createServerInCluster().

First create a cluster, specifying the cell name and cluster name:

createCluster( 'cell1', 'cluster1')

Then create servers, specifying the cluster name, node name, and server name:

createServerInCluster( 'cluster1', 'node1', 'server1')
createServerInCluster( 'cluster1', 'node1', 'server2')


That was easy. We created one cluster with two servers. This screenshot shows the two servers with the cluster name in the Admin Console.

It's also easy to create a replication domain and enable session replication with these same commands. If you look at the two method signatures in wsadminlib.py, you'll see optional parameters for replication. They are disabled by default, and you can override them as follows:

Friday, April 9, 2010

Who wrote wsadminlib.py?

wsadminlib.py was originally created by two IBM product developers in 2006. They shared it with teammates and it grew into an internal community project with several dozen volunteer contributors thus far.

Click on the thumbnail image to see the list of people who have contributed to the first version published on developerWorks (and who gave permission to publish their names).

Friday, April 2, 2010

How to set a custom property on a channel?

Use wsadminlib's method setChannelCustomProperty().

Before we start, here is an example of channel custom properties in the admin console: Click Application Servers-> server1-> Web container settings-> Web container transport chains-> WCInboundDefault-> Web container inbound channel (WCC2)-> Custom properties. I have no idea what a channel is, but I can show you how to set a custom property on one...

Method setChannelCustomProperty() allows us to specify the channel either by an end point name or the channel name. Take a look at the method in wsadminlib, where there is actually good pydoc to explain the parameters.

The first five parameters are required, in the specified sequence. The last two, endPointName and channelName, are optional and have defaults. You must specify exactly one of them.

So let's add a hypothetical custom property, enablePlayaDust=true, by specifying the channel name. Create a python script file named setChannelCustProp.py:

Wednesday, March 31, 2010

How to set a server's listening port number?

Use wsadminlib's method setServerPort(). Here's an example of setting the web container's default port:

nodename = 'node1'
servername = 'server1'
endPointName = 'WC_defaulthost'
port = 9083
setServerPort(nodename, servername, endPointName, port)

Note that the name arguments are python strings, but the port is a number. Here is a screenshot:

Tuesday, March 30, 2010

How to save my changes?

Use wsadminlib's method save(). This method saves your changes and pushes them out to all the nodes immediately (if you are running in a cell environment). It also displays all the changes, for debug purposes.

Here is a screenshot from the end of an exercise where I created a new server:

wsadmin>save()
[2010-0301-1150-2400] save: AdminConfig.queryChanges()
[2010-0301-1150-2400] save: WASX7146I: The following configuration files contain unsaved changes:
[2010-0301-1150-2400] save: cells/ndcell/nodes/node1/servers/server1/server.xml
[2010-0301-1150-2400] save: AdminConfig.hasChanges()
[2010-0301-1150-2400] save: AdminConfig.getSaveMode()
[2010-0301-1150-2400] save: rollbackOnConflict
[2010-0301-1150-2400] save: AdminConfig.save()
[2010-0301-1150-2400] save: Save complete!
[2010-0301-1150-2500] wsadminlib.syncall Start
[2010-0301-1150-2500] wsadminlib.syncall Sync config to node node1
[2010-0301-1150-2600] wsadminlib.syncall Done
0
wsadmin>

Monday, March 29, 2010

How to set the trace spec on a server?

Use wsadminlib's method setServerTrace(). Here is a simple example:

nodename = 'node1'
servername = 'server1'
tracespec = '*=info:com.ibm.ws.sip.*=all'
setServerTrace(nodename, servername, tracespec)

And a screen capture:

root@ding6: /opt/WAS70/bin/wsadmin.sh -lang jython -host ding6 -port 8879
WASX7209I: Connected to process "dmgr" on node dmgr using SOAP connector; The type of process is: DeploymentManager
WASX7031I: For help, enter: "print Help.help()"
wsadmin>
wsadmin>execfile('wsadminlib.py')
$Id: wsadminlib.py 50 2009-01-14 14:42:11Z ding $
wsadmin>
wsadmin>enableDebugMessages()
[2010-0301-1149-3100] enableDebugMessages Verbose trace messages are now enabled; future debug messages will now be printed.
wsadmin>
wsadmin>nodename = 'node1'
wsadmin>servername = 'server1'
wsadmin>tracespec = '*=info:com.ibm.ws.sip.*=all'
wsadmin>setServerTrace(nodename, servername, tracespec)
[2010-0301-1150-0800] setServerTrace: Setting tracing on server node1/server1 to *=info:com.ibm.ws.sip.*=all
wsadmin>


Be sure to take a look at the method in wsadminlib.py. It has defaults which you can override for the number and size of backup log files. And on z/OS, it automatically stores the log files in the same location as they appear on non-Z platforms.

Sunday, March 28, 2010

What is this method sop()?

wsadminlib.py has a rudimentary trace/logging facility in method sop(). The name is a snarky acronym taken from Java's System.out.println() command.

Input: Method sop() takes two strings as parameters, the name of the calling method, and the message.

Output: Method sop() prints these to the console, along with a terse, internationally-understandable timestamp: [YYYY-MMDD-hhmm-ss00]

You can turn these messages on and off dynamically by calling these toggle methods:
- enableDebugMessages()
- disableDebugMessages()
sop() messages are disabled by default. I like verbose messages, so all of my scripts call enableDebugMessages() right at the start.

Note that wsadminlib contains many calls to sop() which are commented-out. These are usually very verbose messages which were written by the original method developer, but not needed since. However, we left them in intentionally. If you are having trouble making a specific method work, or you want to see the gory details for use in your own method, try uncommenting some of these messages for extra hints.

Oh, and one more thing. You can call method sop() from your own script files as well. That way, your messages will have the same fancy timestamp as wsadminlib's, and your messages will look consistent with wsadminlib's too (which I find makes everything easier to read).

Saturday, March 27, 2010

How to use wsadminlib.py

There are several ways to make use of wsadminlib. Here are the basic ideas...

1. Reference

If you are looking for the secrets of how to issue some command, browse wsadminlib and search for it. We try to keep related methods together, so you should find similar functions nearby. If you don't find what you need, search the entire file, case-insensitive.

2. Sample code

If you find something you like, feel free to copy/paste from wsadminlib to your own scripts. wsadminlib is provided as a free sample. And if you find something you don't like, feel free to copy and change it.

3. Call from wsadmin shell

You can call methods in wsadminlib directly from the wsadmin shell. I find this really handy when I am setting up a one-time test. For example, go to a command-prompt, and open a wsadmin connection to your deployment manager.

root@ding6:~# /opt/WAS70/bin/wsadmin.sh -lang jython -host ding6 -port 8879
WASX7209I: Connected to process "dmgr" on node dmgr using SOAP connector; The type of process is: DeploymentManager
WASX7031I: For help, enter: "print Help.help()"
wsadmin
>

Include wsadminlib.py:

wsadmin>execfile('/tmp/wsadminlib.py')
$Id: wsadminlib.py 104 2010-02-15 19:06:18Z ding $
wsadmin>


Call a method. For example, list all the servers which exist. This is handy for debug when running things manually:

wsadmin>serverStatus()
Server status
=============
NODE dmgr on ding6 (linux) - Deployment manager
NODE node1 on ding6 (linux)
APPLICATION_SERVER fritzserver stopped
NODE_AGENT nodeagent running
APPLICATION_SERVER server1 stopped
APPLICATION_SERVER sippbx1 stopped
APPLICATIONS:
commsvc.pbx
commsvc.testear
fritzlet_ear
wsadmin>



4. Call from your own scripts

I write my own small script files when I need to set up a complex configuration repeatedly, and don't want to keep typing the same commands over and over. These scripts are small, because they call methods in wsadminlib.py to do all the work. Here is a a simple example of a script which starts a server. Create a python file like this:

root@ding6:/tmp# cat wsadminlib.demo.py
execfile('/tmp/wsadminlib.py')
enableDebugMessages()

# Start server1
servername = 'server1'
nodename = 'node1'
startServer(nodename,servername)


Invoke it and watch the progress:

root@ding6:/tmp# /opt/WAS70/bin/wsadmin.sh -lang jython -host ding6 -port 8879 -f /tmp/wsadminlib.demo.py
WASX7209I: Connected to process "dmgr" on node dmgr using SOAP connector; The type of process is: DeploymentManager
$Id: wsadminlib.py 104 2010-02-15 19:06:18Z ding $
[2010-0329-1341-2800] enableDebugMessages Verbose trace messages are now enabled; future debug messages will now be printed.
[2010-0329-1341-2800] startServer: starting server node1,server1
[2010-0329-1341-2800] startServer: startServer(server1,node1)
[2010-0329-1341-4300] startServer: server node1,server1 not running yet, waiting another 15 secs


Looking at the wsadminlib source code, we see the startServer() method exits silently upon success, and raises a python exception if anything goes wrong. Therefore, the server started successfully. We also see that the method checks every so often to see if the server has started. This provides reassurance that the script is still alive and just waiting for results, especially when you have a mix of fast and slow server machines.

Friday, March 26, 2010

Welcome to wsadminlib.py

Overview


wsadminlib.py is a large python file containing hundreds of methods to help simplify configuring the IBM WebSphere Application Server (WAS) product using scripting.

Where do I get it?


Update 2013-1012: An official version of wsadminlib is now available at https://github.com/wsadminlib/wsadminlib  IBM has made wsadminlib available on this popular software-sharing site for you to copy, fork, and make your own enhancements!

The original is still available here [developerWorks] and search for 'wsadminlib'.  Its official name is "The IBM WebSphere Application Server Sample Script (wsadminlib.py package)".

Design goals


wsadminlib.py was designed to simplify configuration of the IBM WebSphere Application Server (WAS) product by providing much-improved understandability and ease-of-use. The underlying scripting syntax for configuring the WAS product can be complex and challenging to understand. The wsadminlib package was created to provide simple method names and simple parameter names, and hide the underlying nonsense.

A wide variety of methods have been developed. These methods perform tasks such as creating servers, starting servers, creating clusters, installing applications, proxies, core groups, core group bridge, dynacache, shared libraries, classloaders, replication domains, security, BLA, JDBC, etc, etc, etc.

History

wsadminlib.py was originally created in 2006 by two IBM product developers who were having trouble understanding the native wsadmin syntax. They were both encountering the same problems and both spending time researching the same solutions. They joined forces to split the work and share the benefits, and the original wsadminlib.py was born.

By word of mouth, other teammates discovered the joys of wsadminlib, using it as both a code reference and in production. Eventually, many of these teammates began contributing new methods which they had researched and debugged, thus sharing solutions with others.

Community interest grew steadily over time. By 2010, several dozen people had contributed methods related to component areas they understood, and wsadminlib was being used in production by a good number of components in the current strategic agile automated test infrastructure.

Other script packages

wsadminlib is one of many sample script packages available from IBM and others. Here are some comparisons to guide your selection. Pick your favorite. Vive la difference.

- The developers of wsadminlib like having everything in one monolithic file. There is only one file to include, and only one place to search. Other script developers prefer smaller files, organized in subdirectories, in a more object-oriented fashion.

- The developers of wsadminlib strive to write methods with self-documenting names, and intuitively named parameters. They write pydoc only when necessary. Other script developers like to write verbose documentation.

- Other packages may support multiple languages. Wsadminlib is English-only.

Limitations

- Error-handling is not consistent. Some methods raise python exceptions, others use a return code.

- All wsadminlib methods work well on WAS V7 and V8 (beta). Some methods work on V6.1, but not all have been tested. WAS 6.0.2 is unknown.

- wsadminlib is not a formally-supported product. It is provided as a sample, on an as-is basis. The official disclaimer is in the prologue at the top of wsadminlib.py.

Summary

wsadminlib has been very helpful to many of us inside IBM to speed development of configuration scripts and to run testcases. We hope you find something useful too.