#
#
# 	Common helper functions for the OCF Resource Agents supplied by
# 	heartbeat.
#
# Copyright (c) 2004 SUSE LINUX AG, Lars Marowsky-Brée
#                    All Rights Reserved.
#
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
# 


# TODO: Some of this should probably split out into a generic OCF
# library for shell scripts, but for the time being, we'll just use it
# ourselves...
#

# TODO wish-list:
# - Generic function for evaluating version numbers
# - Generic function(s) to extract stuff from our own meta-data
# - Logging function which automatically adds resource identifier etc
#   prefixes
# TODO: Move more common functionality for OCF RAs here.
#

# This was common throughout all legacy Heartbeat agents
unset LC_ALL; export LC_ALL
unset LANGUAGE; export LANGUAGE

__SCRIPT_NAME=`basename $0`
. /etc/ha.d/shellfuncs

if [ -z "$OCF_ROOT" ]; then
    : ${OCF_ROOT=/usr/local/lib/ocf/}
fi

. ${OCF_ROOT}/resource.d/heartbeat/.ocf-binaries
. ${OCF_ROOT}/resource.d/heartbeat/.ocf-returncodes
. ${OCF_ROOT}/resource.d/heartbeat/.ocf-directories

ocf_is_root() {
	case `id` in
	  *'uid=0(root)'*)	true;;
	  *)			false;;
	esac
}

# Portability comments:
# o The following rely on Bourne "sh" pattern-matching, which is usually
#   that for filename generation (note: not regexp).
# o The "*) true ;;" clause is probably unnecessary, but is included
#   here for completeness.
# o The negation in the pattern uses "!".  This seems to be common
#   across many OSes (whereas the alternative "^" fails on some).
# o If an OS is encountered where this negation fails, then a possible
#   alternative would be to replace the function contents by (e.g.):
#	[ -z "`echo $1 | tr -d '[0-9]'`" ]
#
ocf_is_decimal() {
	case "$1" in
	""|*[!0-9]*)	# empty, or at least one non-decimal
		false ;;
	*)
		true ;;
	esac
}

ocf_is_hex() {
	case "$1" in
        ""|*[!0-9a-fA-F]*)	# empty, or at least one non-hex
		false ;;
	*)
		true ;;
	esac
}

ocf_is_octal() {
	case "$1" in
        ""|*[!0-7]*)	# empty, or at least one non-octal
		false ;;
	*)
		true ;;
	esac
}

__ocf_set_defaults() {
	__OCF_ACTION="$1"

	# Return to sanity for the agents...
	unset LANG
	LC_ALL=C
	export LC_ALL

	# TODO: Review whether we really should source this. Or rewrite
	# to match some emerging helper function syntax...? This imports
	# things which no OCF RA should be using...

	# Strip the OCF_RESKEY_ prefix from this particular parameter
	if [ -z "$OCF_RESKEY_OCF_CHECK_LEVEL" ]; then
		: ${OCF_CHECK_LEVEL:=0}
	else
		: ${OCF_CHECK_LEVEL:=$OCF_RESKEY_OCF_CHECK_LEVEL}
	fi

	if [ ! -d "$OCF_ROOT" ]; then
		ha_log "ERROR: OCF_ROOT points to non-directory $OCF_ROOT."
		exit $OCF_ERR_GENERIC
	fi

	if [ -z "$OCF_RESOURCE_TYPE" ]; then
		: ${OCF_RESOURCE_TYPE:=$__SCRIPT_NAME}
	fi

	if [ -z "$OCF_RA_VERSION_MAJOR" ]; then
		: We are being invoked as an init script.
		: Fill in some things with reasonable values.
		: ${OCF_RESOURCE_INSTANCE:="default"}
		return 0
        fi

	if [ "x$__OCF_ACTION" = "xmeta-data" ]; then
		OCF_RESOURCE_INSTANCE="undef"
	fi	

	if [ -z "$OCF_RESOURCE_INSTANCE" ]; then
		ha_log "ERROR: Need to tell us our resource instance name."
		exit $OCF_ERR_ARGS
	fi
}

ocf_log() {
	# TODO: Revisit and implement internally.
	if
          [ $# -lt 2 ]
        then
          ocf_log err "Not enough arguments [$#] to ocf_log."
        fi
        __OCF_PRIO="$1"
        shift
        __OCF_MSG="$*"

        case "${__OCF_PRIO}" in
          crit)	__OCF_PRIO="CRIT";;
          err)	__OCF_PRIO="ERROR";;
          warn)	__OCF_PRIO="WARNING";;
          info)	__OCF_PRIO="INFO";;
          debug)__OCF_PRIO="DEBUG";;
          *)	__OCF_PRIO=`echo ${__OCF_PRIO}| tr '[a-z]' '[A-Z]'`;;
	esac

	if [ "${__OCF_PRIO}" = "DEBUG" ]; then
		ha_debug "${__OCF_PRIO}: $__OCF_MSG"
	else
		ha_log "${__OCF_PRIO}: $__OCF_MSG"
	fi
}

#
# Ocf_run: Run a script, and log its output.
# Usage:   ocf_run <command>
#
ocf_run() {
	output=`"$@" 2>&1`
	rc=$?
	output=`echo $output`
	if [ $rc -eq 0 ]; then 
	    if [ ! -z "$output" ]; then
		ocf_log info "$output"
	    fi
	    return $OCF_SUCCESS
	else
	    if [ ! -z "$output" ]; then
		ocf_log err "$output"
	    else
		ocf_log err "command failed: $*"
	    fi
	    return $OCF_ERR_GENERIC
	fi
}

ocf_pidfile_status() {
    pidfile=$1
    if [ ! -e $pidfile ]; then
	# Not exists
	return 2
    fi
    pid=`cat $pidfile`
    kill -0 $pid 2>&1 > /dev/null
    if [ $? = 0 ]; then
	return 0
    fi

    # Stale
    return 1
}

ocf_take_lock() {
    lockfile=$1

    if [ ! -n $RANDOM ]; then
	# Something sane-ish in case a shell doesn't support $RANDOM
	RANDOM=$$
    fi

    sleep 0.$RANDOM
    while 
	ocf_pidfile_status $lockfile
    do
	ocf_log info "Sleeping until $lockfile is released..."
	sleep 0.$RANDOM
    done
    echo $$ > $lockfile
}


ocf_release_lock_on_exit() {
    lockfile=$1
    trap "rm -f $lockfile" EXIT
}

__ocf_set_defaults "$@"
