Showing posts with label scripting. Show all posts
Showing posts with label scripting. Show all posts

Thursday, 19 March 2015

Configure JVM heap for WAS cluster members

Nice and simple if you have many JVM's in your cluster.
Note the wildcard feature when listing AdminConfig types (Line 24), very handy.

#=================================================================
# Setup
#=================================================================
import sys
clusterName = sys.argv[0]
min = sys.argv[1]
max = sys.argv[2]

#=================================================================
# Subs
#=================================================================
def getJvms(clusterName):
        # Get the cluster ID
        cluster = AdminConfig.list('ServerCluster', '*'+clusterName+'*')

        # Get a list of the clusters members
        members = AdminConfig.showAttribute(cluster, 'members')
        memberArray = members.split('[')[1].split(']')[0].split(' ')

        # Detemine JVM's
        jvms = []
        for member in memberArray:
                memberName = AdminConfig.showAttribute(member, 'memberName')
                jvms.append(AdminConfig.list('JavaVirtualMachine', '*'+memberName+'*'))
        return jvms

 

def setHeap(jvms, min, max):
        for jvm in jvms:
                print 'Setting '+jvm+' heap sizes of '+str(min)+' and '+str(max)
                AdminConfig.modify(jvm, [['initialHeapSize', min]])
                AdminConfig.modify(jvm, [['maximumHeapSize', max]])


#=================================================================
# Main
#=================================================================
jvms = getJvms(clusterName)
setHeap(jvms, min, max)
AdminConfig.save()

Monday, 5 January 2015

wsadmin - list methods of a Python module

This can be quite handy.

To see a list of references (to modules, strings, arrays etc) type dir() from the wsadmin prompt as follows...

wsadmin>dir()

The response will be something like...
['AdminApp', 'AdminApplication', 'AdminAuthorizations', 'AdminBLA', 'AdminClusterManagement', 'AdminConfig', 'AdminControl', 'AdminJ2C', 'AdminJDBC', 'AdminJMS', 'AdminLibHelp', 'AdminNodeGroupManagement', 'AdminNodeManagement', 'AdminResources', 'AdminServerManagement', 'AdminTask', 'AdminUtilities', 'ApplyPerfTuning', 'Help', 'LTPA_LDAPSecurityOff', 'LTPA_LDAPSecurityOn', 'TypedProxy', '__builtin__', '__doc__', '__name__', 'bsf', 'cellName', 'checkuserpw', 'doAuthenticationMechanism', 'doGlobalSecurity', 'doGlobalSecurityDisable', 'doLDAPUserRegistry', 'domainHostname', 'exportLTPAKey', 'flag', 'foo', 'forceSync', 'generateLTPAKeys', 'getLDAPUserRegistryId', 'getLTPAId', 'getSecId', 'getSecurityAdminMbean', 'imp', 'java', 'ldapPassword', 'ldapPort', 'ldapServer', 'ldapServerId', 'ldapUserRegistryId', 'lineSeparator', 'ltpaId', 'main', 'nodeName', 'osgiApplicationConsole', 'secMbean', 'securityId', 'securityoff', 'securityon', 'sleep', 'sys', 'whatEnv'] 

For those that are python modules (for example AdminResources is a module) you can run dir(<module name>) to list the methods within the function, fot exmaple...

wsadmin>dir(AdminResources)

Produces the following output...
['AdminUtilities', '__doc__', '__file__', '__name__', 'bundleName', 'createCompleteMailProvider', 'createCompleteMailProviderAtScope', 'createCompleteResourceEnvProvider', 'createCompleteResourceEnvProviderAtScope', 'createCompleteURLProvider', 'createCompleteURLProviderAtScope', 'createJAASAuthenticationAlias', 'createLibraryRef', 'createMailProvider', 'createMailProviderAtScope', 'createMailSession', 'createMailSessionAtScope', 'createProtocolProvider', 'createProtocolProviderAtScope', 'createResourceEnvEntries', 'createResourceEnvEntriesAtScope', 'createResourceEnvProvider', 'createResourceEnvProviderAtScope', 'createResourceEnvProviderRef', 'createResourceEnvProviderRefAtScope', 'createScheduler', 'createSchedulerAtScope', 'createSharedLibrary', 'createSharedLibraryAtScope', 'createURL', 'createURLAtScope', 'createURLProvider', 'createURLProviderAtScope', 'createWorkManager', 'createWorkManagerAtScope', 'help', 'resourceBundle', 'sys']

You'll see that one of the methods is createJAASAuthenticationAlias, which means you can run

wsadmin>AdminResources.createJAASAuthenticationAlias( authAlias, uid, password)

NOTE: I found out the args by running AdminResources.help('createJAASAuthenticationAlias')

Here's an example of importing a python module and querying/using it accordingly ...

wsadmin>import time

wsadmin>dir()
['AdminApp', 'AdminApplication', 'AdminAuthorizations', 'AdminBLA', 'AdminClusterManagement', 'AdminConfig', 'AdminControl', 'AdminJ2C', 'AdminJDBC', 'AdminJMS', 'AdminLibHelp', 'AdminNodeGroupManagement', 'AdminNodeManagement', 'AdminResources', 'AdminServerManagement', 'AdminTask', 'AdminUtilities', 'ApplyPerfTuning', 'Help', 'LTPA_LDAPSecurityOff', 'LTPA_LDAPSecurityOn', 'TypedProxy', '__builtin__', '__doc__', '__name__', 'bsf', 'cellName', 'checkuserpw', 'doAuthenticationMechanism', 'doGlobalSecurity', 'doGlobalSecurityDisable', 'doLDAPUserRegistry', 'domainHostname', 'exportLTPAKey', 'flag', 'foo', 'forceSync', 'generateLTPAKeys', 'getLDAPUserRegistryId', 'getLTPAId', 'getSecId', 'getSecurityAdminMbean', 'imp', 'java', 'ldapPassword', 'ldapPort', 'ldapServer', 'ldapServerId', 'ldapUserRegistryId', 'lineSeparator', 'ltpaId', 'main', 'nodeName', 'osgiApplicationConsole', 'secMbean', 'securityId', 'securityoff', 'securityon', 'sleep', 'sys', 'time', 'whatEnv']
 

wsadmin>time
<jclass org.python.modules.time at -1272186292>


wsadmin>type(time)
<jclass org.python.core.PyJavaClass at -779978699>


wsadmin>dir(time)
['__doc__', 'accept2dyear', 'altzone', 'asctime', 'classDictInit', 'clock', 'ctime', 'daylight', 'gmtime', 'localtime', 'mktime', 'sleep', 'strftime', 'time', 'timezone', 'tzname']


wsadmin>time.ctime()
'Tue Jan 06 10:20:33 2015'


Thursday, 4 September 2014

Create JNDI entries for scalars with wsadmin

# createJndiEntry.py
# Author: Bob Clarke
# Date: 28/08/2014

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define subs
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def repExists(repName):
        print 'Checking if Resource Env Provider '+repName+' exists'
        rep = AdminConfig.getid('/ResourceEnvironmentProvider:'+repName+'/')
        return rep

def createRep(repName):
        print 'Creating Resource Env Provider with name '+repName
        rep = AdminConfig.create('ResourceEnvironmentProvider', cellId, [['name',repName]] )
        # Not sure why I need this "Referencable", seems to be a requirement
        AdminConfig.create('Referenceable', rep, [['factoryClassname', 'fClass1'],['classname', 'Class1']])
        return rep

def reeExists(key):
        print 'Checking if jndi entry of salsa/'+key+' exists'
        ree = AdminConfig.getid('/ResourceEnvEntry:'+key+'/')
        return ree

def createJndiRef(rep,key):
        print 'Creating JNDI entry salsa/'+key
        ree = AdminConfig.create('ResourceEnvEntry', rep, [['name', key], ['jndiName', 'salsa/'+key]])
        return ree

def createPropSet(ree,key):
        print 'Creating an empty property set'
        propSet = AdminConfig.create('J2EEResourcePropertySet',ree, [])
        return propSet

def createProp(propSet,key):
        print 'Creating property, key='+key+' : value='+val
        AdminConfig.create('J2EEResourceProperty', propSet, [['name', key], ['type', 'java.lang.String'], ['value', val], ['required', 'false']])
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Setup
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

repName = sys.argv[0]
key = sys.argv[1]
val = sys.argv[2]
cellId = AdminConfig.getid('/Cell:/')
rep=""
ree=""

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Main program
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
existingRep=repExists(repName)
if existingRep:
        print repName+' exists'
        print 'Setting rep to '+str(existingRep)
        rep=existingRep
else:
        rep=createRep(repName)

existingRee=reeExists(key)

if existingRee:
        print 'salsa/'+key+' exists'
        print 'Setting ree to '+str(existingRee)
        ree=existingRee
else:
        ree=createJndiRef(rep,key)

propSet=createPropSet(ree,key)
createProp(propSet,key)
AdminConfig.save()



Avoid getting tied in knots with nested jython lists

I usually get tied in knots trying to use nested lists when creating / modifying config with wsadmin.       

Consider this example:
AdminConfig.create( 'J2EEResourceProperty', propSet, 
    '[[name "key"] 
     [type "java.lang.String"] 
     [description "My property"] 
     [value "Hello"] 
     [required "false"]]' )
       
When you add some passed in params to the mix it gets messy:
AdminConfig.create( 'J2EEResourceProperty', propSet, 
    '[[name " ’ + keyParam + ’ "] 
     [type "java.lang.String"] 
     [description "My property"] 
     [value " ’ + valueParam + ’ "] 
     [required "false"]]' )

The above looks fiddly to me, much better to use the following approach:
AdminConfig.create( 'J2EEResourceProperty', propSet, 
    [['name', keyParam], 
    ['type', 'java.lang.String'], 
    ['description', 'My property'], 
    ['value', valueParam], 
    ['required', 'false']] )

Monday, 9 June 2014

AdminTask help using wildcards

Quite handy ... in this example I'm searching for AdminTask commands that contain the string SDK

wsadmin> print AdminTask.help('-commands', '*SDK*')

Friday, 16 May 2014

wsadmin script to gather Dynacache stats


# dynaCacheMon.py
# Author: Bob Clarke
# Date: 05/01/2015
#

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set up
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import time
count = 0
month = time.ctime().split()[1]
day = time.ctime().split()[2]
year = time.ctime().split()[4]
timeStamp = time.ctime().split()[3]
logFile='/tmp/dynaCacheMon_'+timeStamp+'_'+month+'_'+day+'_'+year+'.log'
file = open(logFile,'a')

if(len(sys.argv) == 2):
        maxLoops = float(sys.argv[0])
        waitTime = float(sys.argv[1])
else:
        # Default values
        maxLoops = 3
        waitTime = 10

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Main program
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
print '\nRunning '+str(maxLoops)+' loops with '+str(waitTime)+' seconds delay. Logging results to '+logFile

while (count < maxLoops):
        print "Loop number "+str(count)
        mBeans = AdminControl.queryNames('type=DynaCache,*')
        for mBean in mBeans.splitlines():
                process = mBean.split(',')[1]
                jvm = AdminControl.queryNames('type=JVM,'+process+',*')
                freeHeap = AdminControl.invoke(jvm, 'getFreeMemory')
                maxHeap = AdminControl.invoke(jvm, 'getMaxMemory')
                file.write('------------------- JVM Details --------------------\n')
                file.write('Loop: '+str(count)+'\n')
                file.write('Time: '+str(time.ctime())+'\n')
                file.write('JVM: '+process+'\n')
                file.write('Max heap: '+maxHeap+'\n')
                file.write('Free heap: '+freeHeap+'\n')
                file.write('---------- Cache instances for this JVM ------------\n')

                for cacheInstance in AdminControl.invoke(mBean, 'getCacheInstanceNames').splitlines():
                        #stats = AdminControl.invoke(mBean, 'getCacheStatistics', cacheInstance+' [MemoryCacheSizeInMB  MemoryCacheEntries]')
                        stats = AdminControl.invoke(mBean, 'getAllCacheStatistics', cacheInstance)
                        file.write('### Instance Name: '+cacheInstance+' ###\n')
                        file.write(stats+',\n\n')
        file.flush()
        count = count+1
        sleep(waitTime)
                                             

Friday, 22 November 2013

Getting JConsole to connect to a secured WebSphere ND Cell

I've often used JConsole to get the basic stats for JVM's, but I wanted to get right into all the juicy stuff - JDBC connection pools, ThreadPools ... and even better, Lombardi Event Manager and checking for failed BPD Instances !!.. now that's more like it.

The problem I had initially with getting this to work was that I kept getting authentication failures .. the classic "Cannot connect due to insufficient or empty credentials". I kept seeing this even though com.ibm.ws.admin.client_7.0.0.jar was in my classpath and I had correctly a correctly populated sas.client.props file. They key to this problem was that (strangely enough) the com.ibm.CORBA package (used when you set com.ibm.CORBA.ConfigURL as a JVM param - see below) which is NOT in com.ibm.ws.admin.client_7.0.0.jar !!!

This meant that the JVM param I refer to (i.e com.ibm.CORBA.ConfigURL) was being ignored and  the sas.client.props file wasn't being read.... no wonder I wasn't authenticating!

So, I thought to myself, this is easy enough, I just need to find that JAR that does contain the  com.ibm.CORBA package.  At this timely point, my colleague Jeff leaned over and said "Why don't you just use an IBM runtime, I bet this will work" .... I said that this wasn't logical because surely I just needed to find the right JAR... but I was running low on time, so I reluctantly plugged in the IBM runtime and it sprung into life. Great stuff, it works, but I would have preferred not to be forced into having to use the IBM runtime
... all a bit too mysterious and black boxy for my liking ... I must return to solve it properly one day, not that I'm OCD or anything :-)

So, moving on....
Assuming you have an X-Window server running, the example script below will let you wield all sorts of power over your WAS Cell.

$HOST is the Deployment Manager
$PORT can be the Deployment Manager's RMI port or it's ORB Port.



#!/bin/bash

export BASE=/opt/bpm
ex port JAVA_HOME=${BASE}/java
export CLASSPATH=${JAVA_HOME}/lib/jconsole.jar
export CLASSPATH=${CLASSPATH}:${JAVA_HOME}/lib/tools.jar
export CLASSPATH=${CLASSPATH}:${BASE}/runtimes/com.ibm.ws.admin.client_7.0.0.jar
export HOST=saturnbpm.stack1.com
export PORT=11004
export DISPLAY=<your desktop IP>:0
export JCP=java.class.path=${CLASSPATH}
export CLIENTSSL=com.ibm.SSL.ConfigURL="file:${BASE}/bob/ssl.client.props"
export CLIENTSAS=com.ibm.CORBA.ConfigURL="file:${BASE}/bob/sas.client.props"
export JMXURL=service:jmx:iiop://${HOST}:${PORT}/jndi/JMXConnector

${JAVA_HOME}/bin/jconsole -J-Djavax.net.debug=ssl \
                      -J-D${JCP} -J-D${CLIENTSSL} -J-D${CLIENTSAS} $JMXURL

... and here's what your sas.client.props and ssl.client.props should contain

sas.client.props
com.ibm.CORBA.securityEnabled=true
com.ibm.CORBA.authenticationTarget=BasicAuth
com.ibm.CORBA.authenticationRetryEnabled=true
# com.ibm.CORBA.loginSource can be set to prompt, stdin or properties
# If properties is specified you'll need to also specify 
# com.ibm.CORBA.loginUserid and com.ibm.CORBA.loginPassword
com.ibm.CORBA.loginSource=properties
com.ibm.CORBA.loginUserid=admin
com.ibm.CORBA.loginPassword={xor}< Your XOR'd password >
com.ibm.CORBA.requestTimeout=180
com.ibm.CORBA.validateBasicAuth=true
com.ibm.CORBA.authenticationRetryCount=3

ssl.client.props
com.ibm.ssl.defaultAlias=DefaultSSLSettings
com.ibm.ssl.alias=DefaultSSLSettings
com.ibm.ssl.protocol=SSL_TLS
com.ibm.ssl.trustManager=IbmPKIX
com.ibm.ssl.enableSignerExchangePrompt=gui
com.ibm.ssl.trustStoreName=ClientDefaultTrustStore
com.ibm.ssl.trustStore=myTrustStore.p12
com.ibm.ssl.trustStorePassword={xor}< The XOR'd password of your SSL truststore>
com.ibm.ssl.trustStoreType=PKCS12
com.ibm.ssl.trustStoreProvider=IBMJCE
com.ibm.ssl.trustStoreFileBased=true
com.ibm.ssl.trustStoreReadOnly=false

Friday, 4 October 2013

wsadmin - passing arguments when usng execfile()

I understand the correct way to execute a script with arguments from within wsadmin is to use the subprocess as follows

wsadmin>import subprocess
wsadmin>subprocess.call([sys.executable, 'abc.py', 'argument1', 'argument2'])

However, I can't seem to successfully import the subprocess module

This being the case I'm using the following approach...

wsadmin>import sys
wsadmin>sys.argv = ['argument1', 'argument2']
wsadmin>execfile('abc.py')

Thursday, 4 July 2013

Wsadmin thin client

Here's how to write a cut down wsadmin.sh 

Thanks to the author of the Clever Monkey blog (http://ksoni-java.blogspot.co.uk/2010/03/wsadmin-thin-client.html) for this one.

The key advantage of this is that you can run it anywhere so long as you have Java installed ... i.e. you don't need WebSphere, instead you need just two jars

  • com.ibm.ws.admin.client_7.0.0.jar (you can find this under $WAS_HOME/runtimes)
  • com.ibm.ws.security.crypto.jar (you can find this under deploytool/itp/plugins/com.ibm.websphere.v7*/plugins)


 You might wonder why you need to set $WAS_HOME.... I don't know the answer but I do know that $WAS_HOME only needs to point to the directory that contains your wsadmin.sh script, I guess it's just a hard coded throwback.

NOTE: I did have one problem whereby I was unable to import the regular expression package (import re). I thought I'd be able to find a jar with everything I needed but in the end I just copied the following py files from an existing WAS install  ($WAS_HOME/optionalLibraries/jython/Lib) to the same dir as my wsadmin.sh script (couldn't work out how to use them if they were placed in a different directory)

  • copy_reg.py  
  • javaos.py  
  • javapath.py  
  • re.py  
  • sre_compile.py  
  • sre_constants.py 
  • sre_parse.py  
  • sre.py  
  • string.py  
  • UserDict.py


Here's my wsadmin.sh



#!/bin/sh

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set paths
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WAS_HOME=/opt/bpm/scripts/certCheck
USER_INSTALL_ROOT=${WAS_HOME}
JAVA_HOME=/opt/bpm/bpm751/java
JAVA_EXE=${JAVA_HOME}/bin/java
CLASSPATH=${WAS_HOME}/lib/com.ibm.ws.admin.client_7.0.0.jar:${WAS_HOME}/lib/com.ibm.ws.security.crypto.jar

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set location of properties files
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SOAPURL=-Dcom.ibm.SOAP.ConfigURL=file:${WAS_HOME}/props/soap.client.props
CLIENTSSL=-Dcom.ibm.SSL.ConfigURL=file:${WAS_HOME}/props/ssl.client.props

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Trace settings
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wsadminTraceString=-Dcom.ibm.ws.scripting.traceString=*=off
wsadminTraceFile=-Dcom.ibm.ws.scripting.traceFile=wsadmin.traceout
wsadminValOut=-Dcom.ibm.ws.scripting.validationOutput=wsadmin.valout

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Process command line arguments
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
isJavaOption=false
nonJavaOptionCount=1
for option in "$@" ; do
        if [ "$option" = "-javaoption" ] ; then
                isJavaOption=true
        else
                if [ "$isJavaOption" = "true" ] ; then
                        javaOption="$javaOption $option"
                        isJavaOption=false
                else
                        nonJavaOption[$nonJavaOptionCount]="$option"
                        nonJavaOptionCount=$((nonJavaOptionCount+1))
                fi
        fi
done

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Run the command
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
${JAVA_EXE} \
-classpath "$CLASSPATH" \
-Duser.install.root=$USER_INSTALL_ROOT \
-Dwas.install.root=$USER_INSTALL_ROOT \
$CLIENTSSL \
$SOAPURL \
$wsadminValOut \
$wsadminTraceString \
-Dcom.ibm.websphere.thinclient=true \
com.ibm.ws.scripting.WasxShell ${nonJavaOption[@]}

Use wsadmin to monitoring WebSphere App Server SSL certificate expiry

A Jython script to check all certificates that are stored in keystores under Cell management. At my client's site I added IHS, Plugin and CACerts keystores to the Cell so that they too can be checked.
If you have access to an SMTP service this script will send an email when a cert is due to expire in less than X days. I run this from a bourne wrapper (I'll place the code for this at the end of this post) which also sends an email if it can't run the AdminTask methods it needs to for any reason.

Here's the Jython code

# --------------------------------------------------------------------------------
# checkCertificates.py
# Author: Bob Clarke (IBM)
# Date: 19/06/2013
# --------------------------------------------------------------------------------

# --------------------------------------------------------------------------------
# Setup
# --------------------------------------------------------------------------------
import re
import sys
import time
import os
import javaos
from java.text import SimpleDateFormat ;
dateFormat = SimpleDateFormat("dd-MMM-yyyy");
emailRecipients = "bob.clarke@stack1.com"
emailContent = "props/email.content"
smtpUrl = "smtp=smtp://smtphub.stack1.com"

# --------------------------------------------------------------------------------
# Define Subroutines 
# --------------------------------------------------------------------------------
def dateDiff(keystoreName, issuedTo, expString, scopeName):
        todayString =  time.strftime("%d-%b-%Y", time.gmtime())
        todayDate = dateFormat.parse(todayString)
        expiryDate = dateFormat.parse(expString)
        e = expiryDate.getTime()
        t = todayDate.getTime()
        d = e - t
        days = d / (1000 * 60 * 60 * 24)
        print "\tExpires "+expString
        if(days < 31):
                if(re.search("blueworks",  issuedTo)):
                        print "\tIgnoring BlueworksLive cert"
                else:
                        print "\tALERT - this certificate will expire in "+str(days)+" days"
                        file = open('props/email.content','w')
                        file.write('ACTION REQUIRED : The following certificate will expire in '+str(days)+' days\n\n')
                        file.write('- Environment '+env+'\n\n')
                        file.write('- Expiry Date '+expString+'\n\n')
                        file.write('- '+str(issuedTo)+'\n\n')
                        file.write('- Keystore name '+str(keystoreName)+'\n\n')
                        file.write('- Keystore scope '+str(scopeName)+'\n')
                        file.close()
                        sendEmail()

def sendEmail():
        os.system('cat '+emailContent+' | mailx -v -s "Certificate expiry notice for '+env+'" -S '+smtpUrl+' -S from="smtp@stack1.com" '+emailRecipients+' >> logs/smtp.log 2>&1')

# ---------------------------------------------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------------------------------------------

env = sys.argv[0]
print
print 'Obtaining keystore information for '+env

# Iterate through all keystores, print each cert with expiry dates and ask user if they want to replace
for ks in AdminTask.listKeyStores('[-all true -keyStoreUsage SSLKeys ]').splitlines():
        keystoreName =  AdminConfig.showAttribute(ks, 'name')
        ms = AdminConfig.showAttribute(ks, 'managementScope')
        scopeName = AdminConfig.showAttribute(ms, 'scopeName')

        print '\n## START '+keystoreName +' in scope '+scopeName+'##'

        print '\n\t## START personal certificates ##'
        personalCertsFound=0
        for cert in AdminTask.listPersonalCertificates('[-keyStoreName '+keystoreName+' -keyStoreScope '+scopeName+']').splitlines():
                personalCertsFound=1
                issuedTo=""
                for property in re.split("\] \[", cert):
                        if(re.search("\[\[",  property)):
                                tmp = property
                                property = re.split("\[\[",tmp)[1]
                        if(re.search("] ]",  property)):
                                tmp = property
                                property = re.split("] ]",tmp)[0]
                        if(re.search("alias", property)):
                                alias = re.split("\s+", property)[1]
                                print "\n\t"+property
                        if(re.search("issuedTo", property)):
                                issuedTo=property
                                print "\t"+property
                        if(re.search("issuedBy", property)):
                                print "\t"+property
                        if(re.search("validity", property)):
                                expString = property.split()[5].split('.]')[0]
                                #dateDiff(expString)
                                dateDiff(keystoreName, issuedTo, expString, scopeName)


        if(personalCertsFound==0):
                print '\tNo personal certificates found in '+keystoreName+' in scope '+scopeName
        print '\n\t## END personal certificates ##'

        print '\n\t## START signer certificates ##'
        signerCertsFound=0
        for cert in AdminTask.listSignerCertificates('[-keyStoreName '+keystoreName+' -keyStoreScope '+scopeName+']').splitlines():
                signerCertsFound=1
                issuedTo=""
                for property in re.split("\] \[", cert):
                        if(re.search("\[\[",  property)):
                                tmp = property
                                property = re.split("\[\[",tmp)[1]
                        if(re.search("] ]",  property)):
                                tmp = property
                                property = re.split("] ]",tmp)[0]
                        if(re.search("alias", property)):
                                alias = re.split("\s+", property)[1]
                                print "\n\t"+property
                        if(re.search("issuedTo", property)):
                                issuedTo=property
                                print "\t"+property
                        if(re.search("issuedBy", property)):
                                print "\t"+property
                        if(re.search("validity", property)):
                                expString = property.split()[5].split('.]')[0]
                                #dateDiff(expString)
                                dateDiff(keystoreName, issuedTo, expString, scopeName)

        if(signerCertsFound==0):
                print '\tNo signer certificates found in '+keystoreName+' in scope '+scopeName
        print '\n\t## END signer certificates ##'

        print '\n## END '+keystoreName +' in scope '+scopeName+'##'



And here's the wrapper script to run it. NOTE: This uses a cutdown version of wadmin.sh (which I've renamed to wsAdminLite.sh - see this post) which I will describe in an upcoming post. They key advantage of this for me is that I was able to point the wsadmin client at my own keystore in which I'd loaded the cell signers for each environment rather than loading all of these (untidily) into the Cell default trust store of another WAS environment.
You'll notice that this script writes a new soap.client.props for each environment, in this way you can XOR encode each password (better than plain text).


#!/bin/sh
# -----------------------------------------------------------------------------
# run.sh
# Author: Bob Clarke (IBM)
# Date: 01/07/2013
# -----------------------------------------------------------------------------
wsaCmd="./wsAdminLite.sh -lang jython"
envProps="props/env.props"
soapProps="props/soap.client.props"
run_log="logs/run.log"
emailRecipients="bob.clarke@stack1.com"
pwd=`pwd`
timestamp=`date "+%d/%m/%y %H:%M:%S"`
scripthost=`hostname`

cat $envProps | grep -v '^#' | while read line
do
        # Parse props
        env=`echo $line | awk -F: '{print $1}'`
        host=`echo $line | awk -F: '{print $2}'`
        port=`echo $line | awk -F: '{print $3}'`
        user=`echo $line | awk -F: '{print $4}'`
        pw=`echo $line | awk -F: '{print $5}'`

        # Write soap.client.props
        echo "com.ibm.SOAP.loginUserid=admin" > ${soapProps}
        echo "com.ibm.SOAP.loginPassword={xor}"${pw} >> ${soapProps}
        echo "com.ibm.ssl.alias=DefaultSSLSettings" >> ${soapProps}

        echo >> $run_log
        echo ENV is $env >> $run_log
        echo Timestamp is $timestamp >> $run_log
        echo "Running: $wsaCmd -host $host -port $port -f checkCertificates.py $env using $soapProps" >> $run_log
        out=`$wsaCmd -host $host -port $port -f checkCertificates.py $env`
        echo "Command output is: $out" >> $run_log

        # Check if we successfully connected to the deployment manager and obtained cert details
        echo $out | grep "END signer certificates" 2>&1 > /dev/null
        if [ $? -ne 0 ]; then
                echo
                echo "It seems the attempt to run checkCertificates.py on environment (${env}) has failed"
                echo "Invocation of checkCertificates.py on host (${scripthost}) to check certificates on environment (${env}) has failed, please check ${pwd}/${run_log}" | mailx -v -s "ACTION REQUIRED :Certificate check for $env has failed" -S smtp=smtp://smtphub.stack1.com -S from="smtp@stack1.com" $emailRecipients >> logs/smtp.log 2>&1
                echo
        fi
done


.... and here's an example env.props file


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# NOTE: The first column is a simple flag that is passed
# to wsadmin so that it can print out a meaningful
# string to describe the environment being checked
# It's up to the person who edits this file to ensure it's accurate
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
PNL_PERF002:jupiter.stack1.com:11005:admin:gfe8Shm1sPSjy
PNL_DEV001:pluto.stack1.com:8887:admin:HQ8SbhdsS8y
PNL_PROC_CENTRE:saturn.stack1.com::12005:admin:Lhjhju98zxubW==
PNL_SIT001:mars.stack1.com::8879:admin:HQ8Sjkj654kjk==
PNL_PERF001:venus.stack1.com::11005:admin:t65hhjtPS8y=

Thursday, 6 June 2013

Determine wsadmin variable types

To determine the type of something returned by AdminConfig or AdminTask .... for example AdminTask.listSignerCertificates( .... )

Use the type command

e.g.

certs =  AdminTask.listSignerCertificates('[-keyStoreName ford -keyStoreScope (cell):marvin']')
print type(certs)

(Ref http://www.ibm.com/developerworks/websphere/library/techarticles/0801_simms/0801_simms.html)

Tuesday, 7 May 2013

Send mail via SMTP server from command line


mailx -v -s "SMTP Test" -S smtp=smtp://smtp.stack1.com -S from="bob.clarke@stack1.com" john.smith@gmail.com

If you want to do the same without needing to terminate manually with a . (dot) or CTRL-D.. do this ...

cat email.content | mailx -v -s "SMTP Test" -S smtp=smtp://smtp.stack1.com -S from="bob.clarke@stack1.com" john.smith@gmail.com

Friday, 3 May 2013

Sharing general Jython stuff

Feel free to use

 #----------------------------------------------------------  
 # Import the regualar expression engine  
 #----------------------------------------------------------  
 import re  
 #----------------------------------------------------------  
 # Define functions  
 #----------------------------------------------------------  
 def heap(serverName, iHeap, mHeap):  
     print "Configuring int/max heap for "+ serverName +" with "+ iHeap +"/" +mHeap  
     nodeName=serverName.split('.')[2]  
     print "<INFO> Setting heap to " + str(iHeap) + " and " + str(mHeap) + " for " + serverName + " on "+ nodeName  
     AdminTask.setJVMProperties('[-serverName '+serverName+' -nodeName '+nodeName+' -verboseModeGarbageCollection true -initialHeapSize '+str(iHeap)+' -maximumHeapSize '+str(mHeap)+' ]')  
     print ""  
 def genArgs(serverName, args):  
     print "<INFO> Configuring "+ serverName +" with generic JVM args of "+ args  
     nodeName=serverName.split('.')[2]  
     AdminTask.setJVMProperties('[-serverName '+serverName+' -nodeName '+nodeName+' -genericJvmArguments "' + args + '"]')  
     #print AdminTask.showJVMProperties('[-serverName '+serverName+' -nodeName '+nodeName+' ]')  
     print ""  
 def threadPools(server):  
     # Get threadpools for this server  
     for threadPool in AdminConfig.list('ThreadPool', serverName).splitlines():  
         if(re.search("Default", threadPool)):  
             print "<INFO> Configuring the Default ThreadPool "+ threadPool  
             AdminConfig.modify(threadPool, '[[maximumSize "75"] [name "Default"] [minimumSize "75"]]')  
             print ""  
         if(re.search("WebContainer", threadPool)):  
             print "<INFO> Configuring the WebContainer ThreadPool "+ threadPool  
             AdminConfig.modify(threadPool, '[[maximumSize "75"] [name "WebContainer"] [minimumSize "75"]]')  
             print ""  
 def dataSources():  
     for ds in AdminConfig.list('DataSource').splitlines():  
         jndi = AdminConfig.showAttribute(ds, "jndiName")  
         if(re.search("jdbc/TeamWorksDB", jndi)):  
             print "<INFO> Configuring jdbc/TeamWorksDB for min/max of 100/300 and statement cache of 250"  
             connPool = AdminConfig.showAttribute(ds, "connectionPool")  
             AdminConfig.modify(connPool, '[[maxConnections "300"] [minConnections "100"]]')  
             AdminConfig.modify(ds, '[[statementCacheSize "250"]]')  
         elif(re.search("jdbc/BPEDB", jndi)):  
             print "<INFO> Configuring jdbc/BPEDB for min/max of 75/200 and statement cache of 150"  
             connPool = AdminConfig.showAttribute(ds, "connectionPool")  
             AdminConfig.modify(connPool, '[[maxConnections "200"] [minConnections "75"]]')  
             AdminConfig.modify(ds, '[[statementCacheSize "150"]]')  
         elif(re.search("jdbc/ODS", jndi)):  
             print "<INFO> Configuring jdbc/ODS for min/max of 75/200 and statement cache of 100"  
             connPool = AdminConfig.showAttribute(ds, "connectionPool")  
             AdminConfig.modify(connPool, '[[maxConnections "200"] [minConnections "75"]]')  
             AdminConfig.modify(ds, '[[statementCacheSize "100"]]')  
 #----------------------------------------------------------  
 # Main program  
 #----------------------------------------------------------  
 for server in AdminConfig.list("Server").splitlines():  
     serverName=AdminConfig.showAttribute(server, 'name')  
     # Search for the cluster memener JVM's  
     if(re.search("AppTarget", serverName)):  
         threadPools(server)  
         dataSources()  
         heap(serverName, str(7680), str(7680))  
         genArgs(serverName, "-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=85 -XX:+UseCMSInitiatingOccupancyOnly -XX:NewRatio=3 -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:Parallel  
 GCThreads=8 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+DisableExplicitGC -server -d64 -XX:PermSize=768m -XX:+PrintHeapAtGC -XX:MaxPermSize=1024m")  
     elif(re.search("Messaging", serverName)):  
         heap(serverName, str(768), str(768))  
         genArgs(serverName, "-XX:ParallelGCThreads=2 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -d64 -XX:MaxPermSize=512m")  
     elif(re.search("WebApp", serverName)):  
         heap(serverName, str(1024), str(1024))  
         genArgs(serverName, "-XX:ParallelGCThreads=2 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -d64 -XX:MaxPermSize=512m")  
     elif(re.search("Support", serverName)):  
         heap(serverName, str(768), str(768))  
         genArgs(serverName, "-XX:ParallelGCThreads=2 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -d64 -XX:MaxPermSize=512m")  
     else:  
         print "No server match for "+serverName  
 AdminConfig.save()  

Friday, 1 March 2013

Linking the JavaVirtualMachine and Server AdminConfig types

Sounds simple but I had a bit of bother with this.

I wanted to be able to itterate through all of the JVM's within a Cell (to get heap sizes etc) . This is simpe enough using something like

for jvm in AdminConfig.list('JavaVirtualMachine').splitlines():
        print AdminConfig.show(jvm);


Then I wanted to be able to get config information "higher up" such as which Cluster this JVM belonged to and which apps are deployed to it etc etc

To do this I needed to be able to map the JavaVirtualMachine type to the Server type. However, I didn't see an obvious way to do this.... so here's what I did...

import re;
for jvm in AdminConfig.list('JavaVirtualMachine').splitlines():
        print "===============================================";
        allProps = AdminConfig.showAttribute(jvm, 'systemProperties');
        if(re.search('cells', allProps)): # Filter out the null data
                serverProp = allProps.split('(')[1].split('#')[0]
                print "("+serverProp+")";
                a = "("+serverProp+")";
                print AdminConfig.show(a); 



The key line is serverProp = allProps.split('(')[1].split('#')[0]. This grabs the first element in the System props which will be something like com.ibm.security.jgss.debug(cells/myCell/nodes/node1/servers/server1|server.xml#Property_1349200741174).

The important thing is that this is something to do with the Server (type) running on this JavaVirtualMachine (type). So I thought to myself "if I strip the property name off of the end, surely I'll get an object reference to the whole server".. so this is what the split does, provides a reference to cells/myCell/nodes/node1/servers/server1|server.xml. 

Append the brackets and you're now able to get a reference to the Server (type). From here, the world's your oyster :-)




Sunday, 2 December 2012

Control Websphere clusters with AdminControl


I needed to start a four cluster environment the other day and used AdminControl to do this as follows...

1./ Start wsadmin (connecting to the Deployment Manager)
2./ Get the MBean references for each Cluster with AdminControl.queryNames. For example, in my case I'm doing this on Process Server so I have a cluster named RMRS.Messaging. To find the MBean for this cluster I can run the following...

m_cluster = AdminControl.queryNames('type=Cluster,name=RMRS.Messaging,*')
or, because I'm lazy I could wildcard the name as follows
m_cluster = AdminControl.queryNames('type=Cluster,name=*Messa*,*')

(Note, the wildcard doesn't seem to work on node names)

Do this for al lof the Clusters you need to start.

3./ Start each cluster with AdminControl.invoke. For example, to start my messaging cluster I would use
AdminControl.invoke(m_cluster, "start")

4./ To check whether the cluster members have actually started, you can attempt to get an MBean for each server, again using AdminControl.queryNames. For example, if I need to check whether the RMRS.Messaging member has started on node1 I would run ...
AdminControl.queryNames('type=Server,name=*Messaging*,node=node1,*')

(Notice the type is now Server as opposed to Cluster)

If an MBean is returned by this command it means the Cluster member is running, if nothing is returned it means the Cluster member is not running.

One thing I found confusing is that the rule stating that an MBean is returned if the entity being queried is running does not appear to apply to Clusters. I.e. at the beginning of this post you'll remember I obtained the MBean of a cluster who's members were not running, therefore you could say the cluster was not running.

Write to a file from wsadmin


This one is dead simple, but (for me) really usefull especially as I cant stand spending hours navigating IBM websites trying to find a simple AdminTask command for WPS.

With these three lines you can dump pages of stuff out to a file without leaving the wsadmin command line...

wsadmin> file = open('c:\\temp\\admin_task_commands.txt','w')
wsadmin> file.write(AdminTask.help('-commands'))
wsadmin> file.close()

Some handy wsadmin tips


List Datasources scoped at a particular cluster

myCluster = a = 'PCUAT001.AppTarget(cells/saturn/clusters/PCUAT001.AppTarget|cluster.xml#ServerCluster_1351877220658)'

print AdminConfig.list('DataSource', myCluster)

Set heap size
for server in AdminControl.queryNames('type=Server,processType=ManagedProcess,*').splitlines():        serverName=server.split(',')[0].split(':')[1].split('=')[1]
        nodeName=server.split(',')[3].split('=')[1]
        AdminTask.setJVMProperties('[-serverName '+serverName+' -nodeName '+nodeName+'  -initialHeapSize 768 -maximumHeapSize 2048]')

 AdminConfig.save()

Set connection pools
import re
for dataSource in AdminConfig.list('DataSource').splitlines():
        jndi= AdminConfig.showAttribute(dataSource, 'jndiName')
        if(re.search("PerformanceDB", jndi)):
                connPool=AdminConfig.showAttribute(dataSource, 'connectionPool')
                AdminConfig.modify(connPool, '[[maxConnections "200"]]')

AdminConfig.save()

Check if server is up or down

This will only return the servers that are running

for server in AdminControl.queryNames('type=Server,*').splitlines():
        name=server.split(',')[0].split(':')[1].split('=')[1]
        print name

If you want to filter out the deployment manager and nodeagent to only show the App servers you're interested i, use the  ManagedProcess qualifier as below

for server in AdminControl.queryNames('type=Server,processType=ManagedProcess,*').splitlines():
        name=server.split(',')[0].split(':')[1].split('=')[1]
        print name

Prepared statements cache (and limiting to specific datasources)

import re
for dsName in 'BPEDB PerformanceDB PDWDB TwqlDB TeamWorksDB ProcessDB WPSDB'.split():
        for dataSource in AdminConfig.list('DataSource').splitlines():
                jndi= AdminConfig.showAttribute(dataSource, 'jndiName')
                if(re.search(dsName, jndi)):
                        print "Setting prepared statement cache "+jndi
                        AdminConfig.modify(dataSource, '[[statementCacheSize "100"]]')

AdminConfig.save()

Find a running cluster and stop it
for cluster in AdminControl.queryNames('type=Cluster,*').splitlines():        if(re.search("RMRS.WebApp",cluster)):
        AdminControl.invoke(cluster, 'stop')

Looking for an AdminConfig Type
import re
for line in AdminConfig.types().splitlines():
        if(re.search("Server",line)):
                print line

Actually a better way to do it might be

AdminControl.queryNames('type=*Security*,*')


Get the config object of the Mashups Config Service

import re
for rep in AdminConfig.list('ResourceEnvironmentProvider').splitlines():
        if(re.search("Mashups_ConfigService",rep)):
               mashup_cs=rep

List all of the custom properties for the Mashups Config Service
for prop in AdminConfig.show( AdminConfig.showAttribute(mashup_cs,"propertySet") ).split():        print prop

or

for prop in AdminConfig.show( AdminConfig.showAttribute(mashup_cs,"propertySet") ).split():print prop

Actually, it's a tad more tricky because of square brackets

for a in AdminConfig.show( AdminConfig.showAttribute(mashup_cs,"propertySet") ).split('resourceProperties')[1].split(']]')[0].split('[')[1].split(' '):


Find a running cluster using wildcard search and stop it

cluster = AdminControl.queryNames('type=Cluster,name=*WebApp*,*')
AdminControl.invoke(cluster, 'stop')

The cluster reference appears to remain after it's stopped (which is not the case for the server names) so you're able
to start with AdminControl.invoke(cluster, 'start')

You cant do this with a server though because the object reference dissapears and even if you kept it in a variable
If you try you get an error stating that the object instance doesn't exists
Instead use the fllowing

AdminControl.startServer(servername, nodename , time)

Example...
AdminControl.startServer('RMRS.WebApp.node1.0', 'node1',120)

(Not really sure what time is)


Queue depth
for Q in AdminControl.queryNames('type=*QueuePoint,SIBMessagingEngine=*BPC*,name=*HldQueue*,*').splitlines():

more specifically
q = AdminControl.queryNames('type=*QueuePoint,SIBMessagingEngine=*BPC*,name=*BPEHldQueue*,*').splitlines()[0]
then
AdminControl.getAttribute(q, "depth")

Misc
#----------------------------------------------------------
# Import the regualar expression engine
#----------------------------------------------------------
import re

#----------------------------------------------------------
# Define functions
#----------------------------------------------------------
def heap(serverName, iHeap, mHeap):
        print "Configuring int/max heap for "+ serverName +" with "+ iHeap +"/" +mHeap
        nodeName=serverName.split('.')[2]
        print "<INFO> Setting heap  to " + str(iHeap) + " and " + str(mHeap) + " for " + serverName + " on "+ nodeName
        AdminTask.setJVMProperties('[-serverName '+serverName+' -nodeName '+nodeName+' -verboseModeGarbageCollection true -initialHeapSize '+str(iHeap)+' -maximumHeapSize '+str(mHeap)+' ]')
        print ""

def genArgs(serverName, args):
        print "<INFO> Configuring "+ serverName +" with generic JVM args of "+ args
        nodeName=serverName.split('.')[2]
        AdminTask.setJVMProperties('[-serverName '+serverName+' -nodeName '+nodeName+' -genericJvmArguments "' + args + '"]')
        #print AdminTask.showJVMProperties('[-serverName '+serverName+' -nodeName '+nodeName+' ]')
        print ""

def threadPools(serverName):
        # Get threadpools for this server
        for threadPool in AdminConfig.list('ThreadPool', serverName).splitlines():
                if(re.search("Default", threadPool)):
                        print "<INFO> Configuring the Default ThreadPool "+ threadPool
                        AdminConfig.modify(threadPool, '[[maximumSize "75"] [name "Default"] [minimumSize "75"]]')
                        print ""

                if(re.search("WebContainer", threadPool)):
                        print "<INFO> Configuring the WebContainer ThreadPool "+ threadPool
                        AdminConfig.modify(threadPool, '[[maximumSize "75"] [name "WebContainer"] [minimumSize "75"]]')
                        print ""

def dataSources():
        for ds in AdminConfig.list('DataSource').splitlines():
                jndi = AdminConfig.showAttribute(ds, "jndiName")
                if(re.search("jdbc/TeamWorksDB", jndi)):
                        print "<INFO> Configuring jdbc/TeamWorksDB for min/max of 100/300 and statement cache of 250"
                        connPool = AdminConfig.showAttribute(ds, "connectionPool")
                        AdminConfig.modify(connPool, '[[maxConnections "300"] [minConnections "100"]]')
                        AdminConfig.modify(ds, '[[statementCacheSize "250"]]')
                elif(re.search("jdbc/BPEDB", jndi)):
                        print "<INFO> Configuring jdbc/BPEDB for min/max of 75/200 and statement cache of 150"
                        connPool = AdminConfig.showAttribute(ds, "connectionPool")
                        AdminConfig.modify(connPool, '[[maxConnections "200"] [minConnections "75"]]')
                        AdminConfig.modify(ds, '[[statementCacheSize "150"]]')
                elif(re.search("jdbc/ODS", jndi)):
                        print "<INFO> Configuring jdbc/ODS for min/max of 75/200 and statement cache of 100"
                        connPool = AdminConfig.showAttribute(ds, "connectionPool")
                        AdminConfig.modify(connPool, '[[maxConnections "200"] [minConnections "75"]]')
                        AdminConfig.modify(ds, '[[statementCacheSize "100"]]')

#----------------------------------------------------------
# Main program
#----------------------------------------------------------
for server in AdminConfig.list("Server").splitlines():
        serverName=AdminConfig.showAttribute(server, 'name')

        # Search for the cluster memener JVM's
        if(re.search("AppTarget", serverName)):
                threadPools(server)
                #heap(serverName, str(7680), str(7680))
                #genArgs(serverName, "-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=85 -XX:+UseCMSInitiatingOccupancyOnly -XX:NewRatio=3 -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:Paralle
lGCThreads=8 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+DisableExplicitGC -server -d64 -XX:PermSize=768m -XX:+PrintHeapAtGC -XX:MaxPermSize=1024m")
        elif(re.search("Messaging", serverName)):
                heap(serverName, str(768), str(768))
                #genArgs(serverName, "-XX:ParallelGCThreads=2 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -d64 -XX:MaxPermSize=512m")
        elif(re.search("WebApp", serverName)):
                heap(serverName, str(1024), str(1024))
                #genArgs(serverName, "-XX:ParallelGCThreads=2 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -d64 -XX:MaxPermSize=512m")
        elif(re.search("Support", serverName)):
                heap(serverName, str(768), str(768))
                #genArgs(serverName, "-XX:ParallelGCThreads=2 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -d64 -XX:MaxPermSize=512m")
        else:
                print "No server match for "+serverName

AdminConfig.save()

Emergency upgrade of WebSphere JVM to 64 bit

Should you accidentally install a 32 bit JVM under your BPM stack (doh!!) ... here's how to upgrade it without tearing down the whole thing and re-installing 

1./ Create a new Installation Manager new response file as below. Set the path and the offering profile to be different from any existing installations on the target machine. what you're doing here is just installing a new temporary version of WAS and you'll only be using the bin, java and lib directories.

For this example we'll use an install dir of /opt/bpm/WAS_64 and an Installation Manager profile of WAS_64 

<?xml version="1.0" encoding="UTF-8"?>
<agent-input>
<server>
        <repository location='/opt/bpm/install/repository'/>
</server>
<profile installLocation='/opt/bpm/WAS_64' id='WAS_64'>
        <data key='eclipseLocation' value='/opt/bpm/WAS_64' />
        <data key="cic.selector.nl" value="en" />
        <data key='user.import.profile' value='false'/>
        <data key='user.select.64bit.image,com.ibm.websphere.ND.v70' value='true'/>
</profile>
<install>
        <offering profile="WAS_64" id="com.ibm.websphere.ND.v70" features='core.feature,import.productProviders.feature,import.configLauncher.feature' installFixes='none'/>
    <!--
        ANy WAS patches that you need also need to be installed
    -->   

</install>
<preference name='com.ibm.cic.common.core.preferences.eclipseCache' value='/opt/bpm/eclipsecache'/>
<preference value="30" name="com.ibm.cic.common.core.preferences.connectTimeout" />
<preference value="30" name="com.ibm.cic.common.core.preferences.readTimeout" />
<preference value="0" name="com.ibm.cic.common.core.preferences.downloadAutoRetryCount" />
<preference value="true" name="offering.service.repositories.areUsed" />
<preference value="false" name="com.ibm.cic.common.core.preferences.ssl.nonsecureMode" />
<preference value="false" name="com.ibm.cic.common.core.preferences.http.disablePreemptiveAuthentication" />
<preference value="true" name="com.ibm.cic.common.core.preferences.preserveDownloadedArtifacts" />
<preference value="false" name="PassportAdvantageIsEnabled" />
<preference value="true" name="com.ibm.cic.common.core.preferences.searchForUpdates" />
<preference value="true" name="com.ibm.cic.common.core.preferences.import.enabled" />
</agent-input>


2./ Now run Installation Manager using the response file created above as the input.
  • /opt/bpm/im/eclipse/IBMIM -acceptLicense -input <response file> -silent -nosplash
3./ Save versionInfo (for version comparison later on)
  • /opt/bpm/<original BPM install>/versionInfo.sh -maintenancePackageDetail > /tmp/bpm-version32
4./ Shut down all JVM's and carry out the following moves in the EXISTING install:
  • mv /opt/bpm/<original BPM install>/java /opt/bpm/<original BPM install>/java_32
  • mv /opt/bpm/<original BPM install>/bin /opt/bpm/<original BPM install>/bin_32
  • mv /opt/bpm/<original BPM install>/lib /opt/bpm/<original BPM install>/lib_32
5./ Recursively copy the java, bin and lib directories fron the new 64 bit install:
  • cp -rp /opt/bpm/WAS_64/java /opt/bpm/<original BPM install>
  • cp -rp /opt/bpm/WAS_64/bin /opt/bpm/<original BPM install>
  • cp -rp /opt/bpm/WAS_64/lib /opt/bpm/<original BPM install>
5./ Re-instate any lib/ext libraries you may have
  • cp -rp /opt/bpm/<original BPM install>/lib_32/ext/* /opt/bpm/<original BPM install>/lib/ext
  • cp -rp /opt/bpm/<original BPM install>/lib_32/task* /opt/bpm/<original BPM install>/lib
6./ Re-instate CACerts (I'm assuming you've worked out that BPM 7.5.* and 8.0.* both use CACerts in 2 cases... a.) The Process Centre uses it for a trust store when it needs to trust a remote process server and b.) the RAL (Remote Artifact Loader) uses it as a trust store and as a keystore if it needs to use an SSL key to authenticate to any endpoints where you may have enabled client SSL auth)
  • cp -p /opt/bpm/<original BPM install>/java_32/jre/lib/security/cacerts /opt/bpm/<original BPM install>/java/jre/lib/security
7./ Save new versionInfo (see step 3) 

/opt/bpm/<original BPM install>/bin/versionInfo.sh -maintenancePackageDetail > /tmp/bpm-version64
8./ Compare versionInfo outputs
  • diff /tmp/bpm-version32 /tmp/bpm-version64
9./ If this is Solaris, you'll need to add the -d64 flag to all jvm parameters (under Generic JVM args)

You now have a 64 bit stack ... phew :-)  

Tuesday, 6 November 2012

Configure JDBC connection pools with wsadmin

import re
for dataSource in AdminConfig.list('DataSource').splitlines():
        jndi= AdminConfig.showAttribute(dataSource, 'jndiName')
        if(re.search("PerformanceDB", jndi)):
                connPool=AdminConfig.showAttribute(dataSource, 'connectionPool')
                AdminConfig.modify(connPool, '[[maxConnections "200"]]')
AdminConfig.save()