Adding WAS JVM Arguments

Adding JVM arguments in a safe way: update existing, adding new.

############################################################################
# Safely adding JVM arguments.
# New arguments are provided in the command line, for example:
#
# wsadmin -language=jython -f was_jvm.py \  
# JVM_ARGS="-Xgcpolicy:gencon -Xcompressedrefs" \ 
# JVM_RM_ARGS="-Xhealthcenter"
#
# if provided argument exists, it will be updated.
# if it does not exit, it will be added
############################################################################
 
DEBUG = 1
 
# default parameters
pars = { 
	'JVM_ARGS'     : '',
	'JVM_RM_ARGS'  : ''
 
}
 
 
#########################################################
# update defaults from command line
#########################################################
for arg in sys.argv:
	arr = arg.split("=", 1)
	if len(arr) > 1:
		pars[arr[0].upper()] = arr[1]
 
 
if DEBUG :
	for key in pars.keys():
		print key + " = '" + pars[key] + "'"
 
 
#########################################################
# Parse JVM Args
#########################################################
jvm_pars = {}
jvm_rm_pars = {}
 
for jvm_par in pars['JVM_ARGS'].split() :
	pair = jvm_par.split(":", 1)
	jvm_pars[pair[0]] = pair
 
for jvm_par in pars['JVM_RM_ARGS'].split() :
	pair = jvm_par.split(":", 1)
	jvm_rm_pars[pair[0]] = pair
 
if DEBUG:
	for key in jvm_pars.keys() :
		pair = jvm_pars[key]
		if len(pair) > 1 :
			print "Key='" + pair[0] + "', value='" + pair[1] + "'"
		else :
			print "Key='" + pair[0] + "'"
 
	for key in jvm_rm_pars.keys() :
		pair = jvm_rm_pars[key]
		if len(pair) > 1 :
			print "RM Key='" + pair[0] + "', value='" + pair[1] + "'"
		else :
			print "RM Key='" + pair[0] + "'"
# end if
 
#########################################################
# Java Virtual Machine configurations                   #
#########################################################
servers = AdminTask.listServers('[-serverType APPLICATION_SERVER ]')
if (servers != ['']):
	servers = servers [0:len(servers)].split(lineSeparator)
	for server in servers:
		serverName = AdminConfig.showAttribute(server, "name")
		print "\nSetting configuration for Application Server " + serverName
		jvm = AdminConfig.list('JavaVirtualMachine', server)
 
		#########################################################
		# Set recommended JVM args                              #
		#########################################################
		jvm_args = {}
		try:
			_excp_ = 0
			result = AdminConfig.showAttribute(jvm, 'genericJvmArguments')
			print "\nCurrent JVM Settings: " + result + "\n"
			newJvmSettings = []
			params = result.split()
			for param in params :
				pair = param.split(':', 1)
				key = pair[0]
				jvm_args[key] = 1
				if jvm_rm_pars.get(key) == None :
					if jvm_pars.get(key) == None :
						newJvmSettings.append(param)
					else :
						pair = jvm_pars[key]
						newParam = key
						if len(pair) > 1 :
							newParam += ":" + pair[1]
						# end if
						newJvmSettings.append(newParam)
					# end if
				# end if
			# end for
			for key in jvm_pars.keys() :
				if jvm_args.get(key) == None :
					# new argument has not been set yet
					# in it is not in the list of args to be removed
					if jvm_rm_pars.get(key) == None :
						pair = jvm_pars[key]
						newParam = key
						if len(pair) > 1 :
							newParam += ":" + pair[1]
						# end if
						newJvmSettings.append(newParam)
					# end if	
				# end if
			# end for
			newJvmSettingsString = " ".join(newJvmSettings)
			print "New JVM Settings: " + newJvmSettingsString + "\n"
 
			result = AdminConfig.modify(jvm, [['genericJvmArguments', newJvmSettingsString]])
			print "Set JVM args successfully"
		except:
			_type_, _value_, _tbck_ = sys.exc_info()
			result = `_value_`
			_excp_ = 1
		#endTry 
		if (_excp_ ):
			print "Error setting JVM args"
			print "Error = "+result
		#endIf
	#endFor
#endIf
 
# save configuration
AdminConfig.save()

 

Changing WAS Log Detail Level

WebSphere command assistant and command log are extremely helpful to create WAS automation scripts, but these do not cover many commands from troubleshooting and monitoring sections of the WebSphere integrated console. I wish documentation would be better too. It takes some time to find the right object, and it require to run multiple tests before the task can be scripted.
Here is an example of Jython script using AdminTask object to update to update WAS Log Detail Level.

##########################################################
# Updating log detail level
# Default settings are "*=info"
# it can be changed by providing LOGDETAILS 
# in the command line: LOGDETAILS="*=info: ...."
#########################################################
DEBUG = 1
# default parameters
pars = { 
	'LOGDETAILS'   : '*=info'
}
 
#########################################################
# update defaults from command line
#########################################################
for arg in sys.argv:
	arr = arg.split("=", 1)
	if len(arr) > 1:
		pars[arr[0].upper()] = arr[1]
 
if DEBUG :
	for key in pars.keys():
		print key + " = '" + pars[key] + "'"
 
# get server and node names
objNameString = AdminControl.completeObjectName('WebSphere:type=Server,*')
node   = AdminControl.getAttribute(objNameString, 'nodeName');
server = AdminControl.getAttribute(objNameString, 'name');
 
#########################################################
# update settings
#########################################################
try:
	_excp_ = 0
	AdminTask.setTraceSpecification('[-serverName ' + server + \
		' -nodeName ' + node + \
		' -persist true -traceSpecification "' + pars['LOGDETAILS'] + '"]')
	# Save to master configuration
	AdminConfig.save()	
except:
	_type_, _value_, _tbck_ = sys.exc_info()
	result = `_value_`
	_excp_ = 1
#endTry 
if (_excp_ ):
	print "Error = " + result
#endIf

Creating CLM Application Friend

Adding new application to a CLM infrastructure might require registering it as a friend to existing applications. Unfortunately, no public API to command line utility is available to automate this process.

Nevertheless, it can be done using undocumented administrative REST services. In order to add new friend, we need to create OAuth consumer key on the remote server first (or request provisional key if we do not have administrative access to the server). Then, CLM application friend could be registered using the following REST service:

https://server:port/context/service/com.ibm.team.repository.service.internal.discovery.IFriendsAdminRestService/newFriend

This service accepts the following parameters (URL-encoded):
title – friend’s name;
oauthConsumerKey – consumer key unique ID;
oauthConsumerSecret – consumer secret string;
rootServices – new application root services URL.

Perl code sample:

use LWP::UserAgent;
use HTTP::Request::Common;
use HTTP::Headers;
...
my $app = 'https://server:port/context';
my $register_friend = 'service/com.ibm.team.repository.service.internal.discovery.IFriendsAdminRestService/newFriend';
# Create user agent
my $ua = LWP::UserAgent->new( cookie_jar => {}, default_headers => HTTP::Headers->new( Accept => 'text/xml'));
...
# login to the CLM application
...
# set referrer header
$ua->default_header('Referer' => "$app/admin");
 
# Register new friend
my $response = $ua->request( POST "$app/$register_friend",
        [
          title               => 'Friend Name',
          rootServices        => 'https://remote_application:port/context/rootservices',
          oauthConsumerKey    => 'consumer key id',
          oauthConsumerSecret => 'consumer secret'
        ]
 );

 

Creating RTC Consumer Key from Command Line

There is no public API available to register OAuth consumer key with Jazz application. The only workaround I found so far would be to use undocumented admin services REST API.

A new consumer key can be registered using the following URI:

http(s)://server:port/<context>/service/com.ibm.team.repository.service.internal.oauth.IOAuthRestService/registerNewConsumer

This service accepts four parameters (URL-encoded):
name – consumer key name;
consumerKey – consumer key unique ID (It is optional parameter, and the key will be generated by the application is missing);
consumerSecret – consumer secret object;
secretType – usually ‘STRING’.

Perl code sample:

use LWP::UserAgent;
use HTTP::Request::Common;
use HTTP::Headers;
...
my $app = 'https://server:port/context';
my $oauth_register = 'service/com.ibm.team.repository.service.internal.oauth.IOAuthRestService/registerNewConsumer';
# Create user agent
my $ua = LWP::UserAgent->new( cookie_jar => {}, default_headers => HTTP::Headers->new( Accept => 'text/xml'));
# login to the CLM application
...
# set referrer header
$ua->default_header('Referer' => "$app/admin");
 
# Register consumer key with provided id
my $response = $ua->request( POST "$app/$oauth_register",
        [
          consumerSecret => 'secret',
          secretType     => 'STRING',
          name           => 'key name',
          consumerKey    => 'key id'
        ]
 );

 

Allow consumer key id to be generated by the server.

my $response = $ua->request( POST "$app/$oauth_register",
        [
          consumerSecret => 'secret',
          secretType     => 'STRING',
          name           => 'key name'
        ]
);
# check response
if($response->code() != 200){
   print $response->content() . "\n";
   die "Cannot create consumer key\n Message: " . $response->message() . "\n";
}
# get consumer key value
if( $response->content() !~ /\<value\>([^\<]+)\<\/value\>/ ){
   die "Cannot find consumer key value in registration response\n";
}
my $oauth_id = $1;
print "Consumer key id = $oauth_id\n"

 

In order to set consumer key properties or assign specific user id to the key, the following service could be used:

http(s)://server:port/<context>/service/com.ibm.team.repository.service.internal.oauth.IOAuthRestService/setConsumerAttributes

Perl sample:

my $oauth_setattrs = 'service/com.ibm.team.repository.service.internal.oauth.IOAuthRestService/setConsumerAttributes';
...
# update consumer attributes
$response = $ua->request( POST "$app/$oauth_setattrs",
   [
     consumerKey    => $oauth_id,
     trusted        => 'true',
     userId         => 'desirable_user_id'
   ]
);

 

These services are not documented, but I did not find a better way to automate consumer creation task so far. I was able to use it with CLM 3.x, 4.x, and 5.x applications.