mirror of https://github.com/sipwise/heartbeat.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
572 lines
12 KiB
572 lines
12 KiB
#!/bin/sh
|
|
#
|
|
#
|
|
# WAS
|
|
#
|
|
# Description: Manages a Websphere Application Server as an HA resource
|
|
#
|
|
#
|
|
# Author: Alan Robertson
|
|
# Support: linux-ha@lists.linux-ha.org
|
|
# License: GNU General Public License (GPL)
|
|
# Copyright: (C) 2002 - 2005 International Business Machines, Inc.
|
|
#
|
|
#
|
|
# An example usage in /etc/ha.d/haresources:
|
|
# node1 10.0.0.170 WAS::/opt/WebSphere/ApplicationServer/config/server-cfg.xml
|
|
#
|
|
# See usage() function below for more details...
|
|
#
|
|
# OCF parameters are as below:
|
|
# OCF_RESKEY_config
|
|
# (WAS-configuration file, used for the single server edition of WAS)
|
|
# OCF_RESKEY_port
|
|
# (WAS-<snoop>-port-number, used for the advanced edition of WAS)
|
|
|
|
#######################################################################
|
|
# Initialization:
|
|
|
|
. ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs
|
|
|
|
#######################################################################
|
|
|
|
WASDIR=/opt/WebSphere/AppServer
|
|
if
|
|
[ ! -d $WASDIR ]
|
|
then
|
|
WASDIR=/usr/WebSphere/AppServer
|
|
fi
|
|
STARTTIME=300 # 5 minutes
|
|
DEFAULT_WASPORTS="9080"
|
|
#
|
|
#
|
|
WASBIN=$WASDIR/bin
|
|
DEFAULT=$WASDIR/config/server-cfg.xml
|
|
|
|
#
|
|
# Print usage message
|
|
#
|
|
usage() {
|
|
methods=`WAS_methods | grep -v methods`
|
|
methods=`echo $methods | tr ' ' '|'`
|
|
cat <<-!
|
|
usage: $0 ($methods)
|
|
|
|
For the single server edition of WAS, you have to set the following
|
|
enviroment virable:
|
|
OCF_RESKEY_config
|
|
(WAS-configuration file)
|
|
|
|
For the advanced edition of WAS, you have to set the following
|
|
enviroment virable:
|
|
OCF_RESKEY_port
|
|
(WAS-<snoop>-port-number)
|
|
|
|
$0 manages a Websphere Application Server (WAS) as an HA resource
|
|
|
|
The 'start' operation starts WAS.
|
|
The 'stop' operation stops WAS.
|
|
The 'status' operation reports whether WAS is running
|
|
The 'monitor' operation reports whether the WAS seems to be working
|
|
(httpd also needs to be working for this case)
|
|
The 'validate-all' operation reports whether the OCF instance parameter (OCF_RESKEY_config or OCF_RESKEY_port) is valid
|
|
The 'methods' operation reports on the methods $0 supports
|
|
|
|
This is known to work with the Single Server edition of Websphere,
|
|
and is believed to work with the Advanced edition too.
|
|
Since the Advanced Edition has no configuration file (it's in a the
|
|
database) you need to give a port number instead of a
|
|
configuration file for this config parameter.
|
|
|
|
The default configuration file for the single server edition is:
|
|
$DEFAULT
|
|
|
|
The default snoop-port for the advanced edition is: $DEFAULT_WASPORTS
|
|
|
|
The start and stop operations must be run as root.
|
|
|
|
The status operation will report a pid of "-" for the
|
|
WAS root process using unless it is run as root.
|
|
|
|
If you don't have xmllint on your system, parsing of WAS
|
|
configuration files is very primitive.
|
|
In this case, the port specification we need from the XML
|
|
config file has to be on the same line as the
|
|
first part of the <transports/> tag.
|
|
|
|
We run servlet/snoop on the first transport port listed in
|
|
the config file for the "monitor" operation.
|
|
|
|
!
|
|
}
|
|
|
|
meta_data() {
|
|
cat <<END
|
|
<?xml version="1.0"?>
|
|
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
|
<resource-agent name="WAS">
|
|
<version>1.0</version>
|
|
|
|
<longdesc lang="en">
|
|
Resource script for WAS. It manages a Websphere Application Server (WAS) as
|
|
an HA resource.
|
|
</longdesc>
|
|
<shortdesc lang="en">WAS resource agent</shortdesc>
|
|
|
|
<parameters>
|
|
<parameter name="config" unique="0" required="1">
|
|
<longdesc lang="en">
|
|
The WAS-configuration file.
|
|
</longdesc>
|
|
<shortdesc lang="en">configration file</shortdesc>
|
|
<content type="string" default="$DEFAULT" />
|
|
</parameter>
|
|
|
|
<parameter name="port" unique="0">
|
|
<longdesc lang="en">
|
|
The WAS-(snoop)-port-number.
|
|
</longdesc>
|
|
<shortdesc lang="en">port</shortdesc>
|
|
<content type="integer" default="$DEFAULT_WASPORTS" />
|
|
</parameter>
|
|
</parameters>
|
|
|
|
<actions>
|
|
<action name="start" timeout="300" />
|
|
<action name="stop" timeout="300" />
|
|
<action name="status" depth="0" timeout="30" interval="10" start-delay="10" />
|
|
<action name="monitor" depth="0" timeout="30" interval="10" start-delay="10" />
|
|
<action name="validate-all" timeout="5" />
|
|
<action name="meta-data" timeout="5" />
|
|
<action name="methods" timeout="5" />
|
|
</actions>
|
|
</resource-agent>
|
|
END
|
|
}
|
|
|
|
#
|
|
# Reformat the XML document in a sort of canonical form
|
|
# if we can. If we don't have xmllint, we just cat it out
|
|
# and hope for the best ;-)
|
|
#
|
|
xmlcat() {
|
|
if
|
|
[ "X$XMLcat" = X ]
|
|
then
|
|
XMLcat=`which xmllint 2>/dev/null`
|
|
if
|
|
[ "X${XMLcat}" = X -o ! -x "${XMLcat}" ]
|
|
then
|
|
XMLcat=cat
|
|
else
|
|
XMLcat="$XMLcat --recover --format"
|
|
fi
|
|
fi
|
|
for j in "$@"
|
|
do
|
|
${XMLcat} "$j"
|
|
done
|
|
}
|
|
|
|
#
|
|
#This is a bit skanky, but it works anyway...
|
|
#
|
|
#<transports xmi:type="applicationserver:HTTPTransport" xmi:id="HttpTransport_1" hostname="*" port="9080"/>
|
|
#<transports xmi:type="applicationserver:HTTPTransport" xmi:id="HttpTransport_2" hostname="*" port="9443" sslEnabled="true"/>
|
|
#<transports xmi:type="applicationserver:HTTPTransport" xmi:id="HttpTransport_3" hostname="*" port="9090" external="false"/>
|
|
#
|
|
# It's not really skanky if we can find xmllint on the system, because it
|
|
# reformats tags so they are all on one line, which is all we we need...
|
|
#
|
|
|
|
#
|
|
# Get the numbers of the ports WAS should be listening on...
|
|
#
|
|
# If we don't have xmllint around, then the applicationserver and the
|
|
# port= specification have to be on the same line in the XML config file.
|
|
#
|
|
GetWASPorts() {
|
|
case $1 in
|
|
[0-9]*) echo "$1" | tr ',' '\012';;
|
|
*)
|
|
xmlcat $1 | grep -i 'transports.*applicationserver:HTTPTransport' |
|
|
grep port= |
|
|
sed -e 's%.*port= *"* *%%' \
|
|
-e 's%[^0-9][^0-9]*.*$%%'
|
|
# Delete up to port=, throw away optional quote and optional
|
|
# white space.
|
|
# Throw away everything after the first non-digit.
|
|
# This should leave us the port number all by itself...
|
|
esac
|
|
}
|
|
|
|
#
|
|
# We assume that the first port listed in the <transports/>
|
|
# is the one we should run servlet/snoop on.
|
|
#
|
|
GetWASSnoopPort() {
|
|
GetWASPorts "$@" | head -n1
|
|
}
|
|
|
|
#
|
|
# Return information on the processname/id for the WAS ports
|
|
#
|
|
# pid/java is the expected output. Several lines, one per port...
|
|
#
|
|
#
|
|
WASPortInfo() {
|
|
pat=""
|
|
once=yes
|
|
PortCount=0
|
|
for j in $*
|
|
do
|
|
case $pat in
|
|
"") pat="$j";;
|
|
*) pat="$pat|$j";;
|
|
esac
|
|
PortCount=`expr $PortCount + 1`
|
|
done
|
|
netstat -ltnp 2>/dev/null| egrep -i "($pat) .*LISTEN" | sed 's%.*LISTEN *%%'
|
|
}
|
|
|
|
#
|
|
# Return the number of WAS ports which are open
|
|
#
|
|
CheckWASPortsInUse() {
|
|
count=`WASPortInfo "$@" | wc -l`
|
|
echo $count
|
|
}
|
|
|
|
#
|
|
# Return the pid(s) of the processes that have WAS ports open
|
|
#
|
|
WASPIDs() {
|
|
WASPortInfo "$@" | sort -u | cut -f1 -d/
|
|
}
|
|
|
|
#
|
|
# The version of ps that returns all processes and their (long) args
|
|
# It's only used by WAS_procs, which isn't used for anything ;-)
|
|
#
|
|
ps_long() {
|
|
ps axww
|
|
}
|
|
|
|
|
|
#
|
|
# The total set of WAS processes (single server only)
|
|
#
|
|
WAS_procs() {
|
|
ps_long | grep -i "config=$1" | grep -i java | cut -d' ' -f1
|
|
}
|
|
|
|
|
|
|
|
#
|
|
# methods: What methods/operations do we support?
|
|
#
|
|
WAS_methods() {
|
|
cat <<-!
|
|
start
|
|
stop
|
|
status
|
|
methods
|
|
validate-all
|
|
meta-data
|
|
usage
|
|
!
|
|
if
|
|
have_binary $WGET
|
|
then
|
|
echo monitor
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Return WAS status (silently)
|
|
#
|
|
WAS_status() {
|
|
WASPorts=`GetWASPorts $1`
|
|
PortsInUse=`CheckWASPortsInUse $WASPorts`
|
|
case $PortsInUse in
|
|
0) false;;
|
|
*) true;;
|
|
esac
|
|
}
|
|
|
|
#
|
|
# Report on WAS status to stdout...
|
|
#
|
|
WAS_report_status() {
|
|
WASPorts=`GetWASPorts $1`
|
|
PortCount=`echo $WASPorts | wc -w`
|
|
PortCount=`echo $PortCount`
|
|
PortsInUse=`CheckWASPortsInUse $WASPorts`
|
|
case $PortsInUse in
|
|
0) ocf_log debug "WAS: server $1 is stopped."; return $OCF_NOT_RUNNING;;
|
|
*)
|
|
pids=`WASPIDs $WASPorts`
|
|
if
|
|
[ $PortsInUse -ge $PortCount ]
|
|
then
|
|
ocf_log debug "WAS: server $1 is running (pid" $pids "et al)."
|
|
else
|
|
ocf_log debug "WAS: server $1 is running (pid $pids et al) but not listening on all ports."
|
|
fi
|
|
return $OCF_SUCCESS;;
|
|
esac
|
|
}
|
|
|
|
#
|
|
# Monitor WAS - does it really seem to be working?
|
|
#
|
|
# For this we invoke the snoop applet via wget.
|
|
#
|
|
# This is actually faster than WAS_status above...
|
|
#
|
|
WAS_monitor() {
|
|
tmpfile=`maketempfile`
|
|
SnoopPort=`GetWASSnoopPort $1`
|
|
output=`$WGET -nv -O$tmpfile http://localhost:$SnoopPort/servlet/snoop 2>&1`
|
|
rc=$?
|
|
if
|
|
[ $rc -eq 0 ]
|
|
then
|
|
if
|
|
grep -i 'user-agent.*Wget' $tmpfile >/dev/null
|
|
then
|
|
: OK
|
|
else
|
|
ocf_log "err" "WAS: $1: no user-agent from snoop application"
|
|
rc=$OCF_ERR_GENERIC
|
|
fi
|
|
else
|
|
ocf_log "err" "WAS: $1: wget failure: $output"
|
|
rc=$OCF_ERR_GENERIC
|
|
fi
|
|
rm -fr $tmpfile
|
|
return $rc
|
|
}
|
|
|
|
#
|
|
# Start WAS instance
|
|
#
|
|
WAS_start() {
|
|
# Launch Arguments:
|
|
#
|
|
# -configFile <configFile>
|
|
# -nodeName <nodeName>
|
|
# -serverName <serverName>
|
|
# -oltEnabled
|
|
# -oltHost <hostname>
|
|
# -oltPort <port>
|
|
# -debugEnabled
|
|
# -jdwpPort <port>
|
|
# -debugSource <sourcePath>
|
|
# -serverTrace <traceString>
|
|
# -serverTraceFile <traceFile>
|
|
# -script [<scriptFile>]
|
|
# -platform <platformName>
|
|
# -noExecute
|
|
# -help
|
|
if
|
|
[ -x $WASBIN/startServer.sh ]
|
|
then
|
|
cmd="$WASBIN/startServer.sh -configFile $1"
|
|
else
|
|
cmd="$WASBIN/startupServer.sh"
|
|
fi
|
|
|
|
if
|
|
ocf_run $cmd
|
|
then
|
|
if
|
|
WAS_wait_4_start $STARTTIME "$@"
|
|
then
|
|
#true
|
|
return $OCF_SUCCESS
|
|
else
|
|
ocf_log "err" "WAS server $1 did not start correctly"
|
|
return $OCF_ERR_GENERIC
|
|
fi
|
|
else
|
|
#false
|
|
return $OCF_ERR_GENERIC
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Wait for WAS to actually start up.
|
|
#
|
|
# It seems to take between 30 and 60 seconds for it to
|
|
# start up on a trivial WAS instance.
|
|
#
|
|
WAS_wait_4_start() {
|
|
max=$1
|
|
retries=0
|
|
shift
|
|
while
|
|
[ $retries -lt $max ]
|
|
do
|
|
if
|
|
WAS_status "$@"
|
|
then
|
|
return $OCF_SUCCESS
|
|
else
|
|
sleep 1
|
|
fi
|
|
retries=`expr $retries + 1`
|
|
done
|
|
WAS_status "$@"
|
|
}
|
|
|
|
|
|
#
|
|
# Shut down WAS
|
|
#
|
|
WAS_stop() {
|
|
# They don't return good return codes...
|
|
# And, they seem to allow anyone to stop WAS (!)
|
|
if
|
|
[ -x $WASBIN/stopServer.sh ]
|
|
then
|
|
ocf_run $WASBIN/stopServer.sh -configFile $1
|
|
else
|
|
WASPorts=`GetWASPorts $1`
|
|
kill `WASPIDs $WASPorts`
|
|
fi
|
|
if
|
|
WAS_status $1
|
|
then
|
|
ocf_log "err" "WAS: $1 did not stop correctly"
|
|
#false
|
|
return $OCF_ERR_GENERIC
|
|
else
|
|
#true
|
|
return $OCF_SUCCESS
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Check if the port is valid
|
|
#
|
|
CheckPort() {
|
|
ocf_is_decimal "$1" && [ $1 -gt 0 ]
|
|
}
|
|
|
|
WAS_validate_all() {
|
|
if [ -x $WASBIN/startServer.sh ]; then
|
|
# $arg should be config file
|
|
if [ ! -f "$arg" ]; then
|
|
ocf_log err "Configuration file [$arg] does not exist"
|
|
exit $OCF_ERR_ARGS
|
|
fi
|
|
|
|
# $arg should specify a valid port number at the very least
|
|
local WASPorts=`GetWASPorts $arg`
|
|
if [ -z "$WASPorts" ]; then
|
|
ocf_log err "No port number specified in configuration file [$arg]"
|
|
exit $OCF_ERR_CONFIGURED
|
|
fi
|
|
|
|
local port
|
|
local have_valid_port=false
|
|
for port in "$WASPorts"; do
|
|
if CheckPort $port; then
|
|
have_valid_port=true
|
|
break
|
|
fi
|
|
done
|
|
if [ "false" = "$have_valid_port" ]; then
|
|
ocf_log err "No valid port number specified in configuration file [$arg]"
|
|
exit $OCF_ERR_CONFIGURED
|
|
fi
|
|
|
|
elif [ -x $WASBIN/startupServer.sh ]; then
|
|
# $arg should be port number
|
|
if CheckPort "$arg"; then
|
|
ocf_log err "Port number is required but [$arg] is not valid port number"
|
|
exit $OCF_ERR_ARGS
|
|
fi
|
|
else
|
|
# Do not know hot to validate_all
|
|
ocf_log warn "Do not know how to validate-all, assuming validation OK"
|
|
return $OCF_SUCCESS
|
|
fi
|
|
}
|
|
#
|
|
# 'main' starts here...
|
|
#
|
|
|
|
if
|
|
( [ $# -ne 1 ] )
|
|
then
|
|
usage
|
|
exit $OCF_ERR_ARGS
|
|
fi
|
|
|
|
#
|
|
# Supply default configuration parameter(s)
|
|
#
|
|
|
|
if
|
|
( [ -z $OCF_RESKEY_config ] && [ -z $OCF_RESKEY_port ] )
|
|
then
|
|
if
|
|
[ -f $DEFAULT ]
|
|
then
|
|
arg=$DEFAULT
|
|
else
|
|
arg=$DEFAULT_WASPORTS
|
|
fi
|
|
elif
|
|
[ ! -z $OCF_RESKEY_config ]
|
|
then
|
|
arg=$OCF_RESKEY_config
|
|
else
|
|
arg=$OCF_RESKEY_port
|
|
fi
|
|
|
|
if
|
|
[ ! -f $arg ]
|
|
then
|
|
case $arg in
|
|
[0-9]*) ;; # ignore port numbers...
|
|
*) ocf_log "err" "WAS configuration file $arg does not exist!"
|
|
usage
|
|
exit $OCF_ERR_ARGS;;
|
|
esac
|
|
fi
|
|
|
|
|
|
# What kind of method was invoked?
|
|
case "$1" in
|
|
|
|
meta-data) meta_data
|
|
exit $OCF_SUCCESS;;
|
|
|
|
start) WAS_start $arg
|
|
exit $?;;
|
|
|
|
stop) WAS_stop $arg
|
|
exit $?;;
|
|
|
|
status) WAS_report_status $arg
|
|
exit $?;;
|
|
|
|
monitor) WAS_monitor $arg
|
|
exit $?;;
|
|
|
|
validate-all) WAS_validate_all $arg
|
|
exit $?;;
|
|
|
|
methods) WAS_methods
|
|
exit $?;;
|
|
|
|
usage) usage
|
|
exit $OCF_SUCCESS;;
|
|
|
|
*) usage
|
|
exit $OCF_ERR_UNIMPLEMENTED;;
|
|
esac
|