diff options
Diffstat (limited to 'heartbeat/anything')
-rwxr-xr-x | heartbeat/anything | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/heartbeat/anything b/heartbeat/anything new file mode 100755 index 0000000..137a612 --- /dev/null +++ b/heartbeat/anything @@ -0,0 +1,344 @@ +#!/bin/sh +# +# OCF Resource Agent compliant resource script. +# +# Copyright (c) 2009 IN-telegence GmbH & Co. KG, Dominik Klein +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + +# OCF instance parameters +# OCF_RESKEY_binfile +# OCF_RESKEY_cmdline_options +# OCF_RESKEY_workdir +# OCF_RESKEY_pidfile +# OCF_RESKEY_logfile +# OCF_RESKEY_errlogfile +# OCF_RESKEY_user +# OCF_RESKEY_monitor_hook +# OCF_RESKEY_stop_timeout +# +# This RA starts $binfile with $cmdline_options as $user in $workdir and writes a $pidfile from that. +# If you want it to, it logs: +# - stdout to $logfile, stderr to $errlogfile or +# - stdout and stderr to $logfile +# - or to will be captured by lrmd if these options are omitted. +# Monitoring is done through $pidfile or your custom $monitor_hook script. +# The RA expects the program to keep running "daemon-like" and +# not just quit and exit. So this is NOT (yet - feel free to +# enhance) a way to just run a single one-shot command which just +# does something and then exits. + +# Initialization: +: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} +. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs + +# Parameter defaults + +OCF_RESKEY_binfile_default="" +OCF_RESKEY_workdir_default="" +OCF_RESKEY_pidfile_default="${HA_VARRUN}/anything_${OCF_RESOURCE_INSTANCE}.pid" +OCF_RESKEY_logfile_default="/dev/null" +OCF_RESKEY_user_default="root" +OCF_RESKEY_stop_timeout_default="" + +: ${OCF_RESKEY_binfile=${OCF_RESKEY_binfile_default}} +: ${OCF_RESKEY_workdir=${OCF_RESKEY_workdir_default}} +: ${OCF_RESKEY_pidfile=${OCF_RESKEY_pidfile_default}} +: ${OCF_RESKEY_logfile=${OCF_RESKEY_logfile_default}} +: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}} +: ${OCF_RESKEY_stop_timeout=${OCF_RESKEY_stop_timeout_default}} + +getpid() { + grep -o '[0-9]*' $1 +} + +anything_status() { + if test -f "$pidfile" + then + if pid=`getpid $pidfile` && [ "$pid" ] && kill -s 0 $pid + then + return $OCF_SUCCESS + else + # pidfile w/o process means the process died + return $OCF_ERR_GENERIC + fi + else + return $OCF_NOT_RUNNING + fi +} + +anything_start() { + if ! anything_status + then + #Make sure that PID Directory exists and is writable by proper user + piddir=`dirname $pidfile` + if ! su -s /bin/sh - $user -c "test -w $piddir"; then + #PID Directory is not writeable by user + ocf_log warn "Directory $piddir is not writable by $user, attempting to fix." + ocf_log info "Creating directory $piddir" + mkdir -p $piddir + ocf_log info "Changing permissions for $piddir for user $user" + chown $user: $piddir + else + ocf_log debug "Directory $piddir exists, and is writeable by $user. All fine" + fi + if [ -n "$logfile" -a -n "$errlogfile" ] + then + # We have logfile and errlogfile, so redirect STDOUT und STDERR to different files + cmd="su - $user -c \"cd $workdir; nohup $binfile $cmdline_options >> $logfile 2>> $errlogfile & \"'echo \$!' " + else + # We only have logfile so redirect STDOUT and STDERR to the same file + cmd="su - $user -c \"cd $workdir; nohup $binfile $cmdline_options >> $logfile 2>&1 & \"'echo \$!' " + fi + ocf_log debug "Starting $process: $cmd" + # Execute the command as created above + eval $cmd | tail -n 1 > $pidfile + if anything_status + then + ocf_log debug "$process: $cmd started successfully, calling monitor" + anything_monitor + myres=$? + return $myres + else + ocf_log err "$process: $cmd could not be started" + return $OCF_ERR_GENERIC + fi + else + # If already running, consider start successful + ocf_log debug "$process: $cmd is already running" + return $OCF_SUCCESS + fi +} + +anything_stop() { + local rc=$OCF_SUCCESS + + if [ -n "$OCF_RESKEY_stop_timeout" ] + then + stop_timeout=$OCF_RESKEY_stop_timeout + elif [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then + # Allow 2/3 of the action timeout for the orderly shutdown + # (The origin unit is ms, hence the conversion) + stop_timeout=$((OCF_RESKEY_CRM_meta_timeout/1500)) + else + stop_timeout=10 + fi + if anything_status + then + pid=`getpid $pidfile` + kill $pid + i=0 + while [ $i -lt $stop_timeout ] + do + if ! anything_status + then + rm -f $pidfile + return $OCF_SUCCESS + fi + sleep 1 + i=$((i+1)) + done + ocf_log warn "Stop with SIGTERM failed/timed out, now sending SIGKILL." + kill -s 9 $pid + while : + do + if ! anything_status + then + ocf_log warn "SIGKILL did the job." + rc=$OCF_SUCCESS + break + fi + ocf_log info "The job still hasn't stopped yet. Waiting..." + sleep 1 + done + fi + rm -f $pidfile + return $rc +} + +anything_monitor() { + anything_status + ret=$? + if [ $ret -eq $OCF_SUCCESS ] + then + if [ -n "$OCF_RESKEY_monitor_hook" ]; then + eval "$OCF_RESKEY_monitor_hook" + if [ $? -ne $OCF_SUCCESS ]; then + return ${OCF_ERR_GENERIC} + fi + return $OCF_SUCCESS + else + true + fi + else + return $ret + fi +} + +# FIXME: Attributes special meaning to the resource id +process="$OCF_RESOURCE_INSTANCE" +binfile="$OCF_RESKEY_binfile" +cmdline_options="$OCF_RESKEY_cmdline_options" +workdir="$OCF_RESKEY_workdir" +pidfile="$OCF_RESKEY_pidfile" +[ -z "$pidfile" ] && pidfile=${HA_VARRUN}/anything_${process}.pid +logfile="${OCF_RESKEY_logfile:-/dev/null}" +errlogfile="$OCF_RESKEY_errlogfile" +user="$OCF_RESKEY_user" +[ -z "$user" ] && user=root + +anything_validate() { + if ! su - $user -c "test -x $binfile" + then + ocf_log err "binfile $binfile does not exist or is not executable by $user." + exit $OCF_ERR_INSTALLED + fi + if ! getent passwd $user >/dev/null 2>&1 + then + ocf_log err "user $user does not exist." + exit $OCF_ERR_INSTALLED + fi + for logfilename in "$logfile" "$errlogfile" + do + if [ -n "$logfilename" ]; then + mkdir -p `dirname $logfilename` || { + ocf_log err "cannot create $(dirname $logfilename)" + exit $OCF_ERR_INSTALLED + } + fi + done + [ "x$workdir" != x -a ! -d "$workdir" ] && { + ocf_log err "working directory $workdir doesn't exist" + exit $OCF_ERR_INSTALLED + } + return $OCF_SUCCESS +} + +anything_meta() { +cat <<END +<?xml version="1.0"?> +<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> +<resource-agent name="anything" version="1.0"> +<version>1.0</version> +<longdesc lang="en"> +This is a generic OCF RA to manage almost anything. +</longdesc> +<shortdesc lang="en">Manages an arbitrary service</shortdesc> + +<parameters> +<parameter name="binfile" required="1" unique="0"> +<longdesc lang="en"> +The full name of the binary to be executed. This is expected to keep running with the same pid and not just do something and exit. +</longdesc> +<shortdesc lang="en">Full path name of the binary to be executed</shortdesc> +<content type="string" default="${OCF_RESKEY_binfile_default}"/> +</parameter> +<parameter name="cmdline_options" required="0"> +<longdesc lang="en"> +Command line options to pass to the binary +</longdesc> +<shortdesc lang="en">Command line options</shortdesc> +<content type="string" /> +</parameter> +<parameter name="workdir" required="0" unique="0"> +<longdesc lang="en"> +The path from where the binfile will be executed. +</longdesc> +<shortdesc lang="en">Full path name of the work directory</shortdesc> +<content type="string" default="${OCF_RESKEY_workdir_default}"/> +</parameter> +<parameter name="pidfile"> +<longdesc lang="en"> +File to read/write the PID from/to. +</longdesc> +<shortdesc lang="en">File to write STDOUT to</shortdesc> +<content type="string" default="${OCF_RESKEY_pidfile_default}"/> +</parameter> +<parameter name="logfile" required="0"> +<longdesc lang="en"> +File to write STDOUT to +</longdesc> +<shortdesc lang="en">File to write STDOUT to</shortdesc> +<content type="string" default="${OCF_RESKEY_logfile_default}" /> +</parameter> +<parameter name="errlogfile" required="0"> +<longdesc lang="en"> +File to write STDERR to +</longdesc> +<shortdesc lang="en">File to write STDERR to</shortdesc> +<content type="string" /> +</parameter> +<parameter name="user" required="0"> +<longdesc lang="en"> +User to run the command as +</longdesc> +<shortdesc lang="en">User to run the command as</shortdesc> +<content type="string" default="${OCF_RESKEY_user_default}"/> +</parameter> +<parameter name="monitor_hook"> +<longdesc lang="en"> +Command to run in monitor operation +</longdesc> +<shortdesc lang="en">Command to run in monitor operation</shortdesc> +<content type="string"/> +</parameter> +<parameter name="stop_timeout"> +<longdesc lang="en"> +In the stop operation: Seconds to wait for kill -TERM to succeed +before sending kill -SIGKILL. Defaults to 2/3 of the stop operation timeout. +</longdesc> +<shortdesc lang="en">Seconds to wait after having sent SIGTERM before sending SIGKILL in stop operation</shortdesc> +<content type="string" default="${OCF_RESKEY_stop_timeout_default}"/> +</parameter> +</parameters> +<actions> +<action name="start" timeout="20s" /> +<action name="stop" timeout="20s" /> +<action name="monitor" depth="0" timeout="20s" interval="10s" /> +<action name="meta-data" timeout="5s" /> +<action name="validate-all" timeout="5s" /> +</actions> +</resource-agent> +END +exit 0 +} + +case "$1" in + meta-data|metadata|meta_data) + anything_meta + ;; + start) + anything_start + ;; + stop) + anything_stop + ;; + monitor) + anything_monitor + ;; + validate-all) + anything_validate + ;; + *) + ocf_log err "$0 was called with unsupported arguments: $*" + exit $OCF_ERR_UNIMPLEMENTED + ;; +esac |