diff --git a/heartbeat/README b/heartbeat/README
index aaaff3a9c..604295685 100644
--- a/heartbeat/README
+++ b/heartbeat/README
@@ -1,44 +1,46 @@
 The OCF RA shared code directory
 
 If an RA is too big to be comfortably maintained, split it into
 several source files. Obviosuly, if two or more RAs share some
 code, move that code out to a file which can be shared.
 
 These files will be installed in $OCF_ROOT/lib/heartbeat with
 permissions 644.
 
 Naming practice
 
 Use names such as <RA>.sh or <RA>-check.sh or anything-else.sh
 where "anything-else" should be related to both the RA and the
 code it contains. By adding extension (.sh) it is going to be
 easier to notice that these files are not complete resource
 agents.
 
 For instance, oracle and oralsnr RA can both use code in
 ora-common.sh.
 
 Of course, if the RA is implemented in another programming
 language, use the appropriate extension.
 
 RA tracing
 
 RA tracing may be turned on by setting OCF_TRACE_RA. The trace
-output will be saved to OCF_TRACE_FILE, if set, or by default to
+output will be saved to OCF_TRACE_FILE, if set. If not,
+then the trace would be saved to the OCF_RESKEY_trace_dir.
+If it's also not defined, the log will be saved by default to
 
   $HA_VARLIB/trace_ra/<type>/<id>.<action>.<timestamp>
 
 e.g. $HA_VARLIB/trace_ra/oracle/db.start.2012-11-27.08:37:08
 
 HA_VARLIB is typically set to /var/lib/heartbeat.
 
 OCF_TRACE_FILE can be set to a path or file descriptor:
 
 - FD (small integer [3-9]) in that case it is up to the callers
   to capture output; the FD _must_ be open for writing
 
 - absolute path
 
 NB: FD 9 may be used for tracing with bash >= v4 in case
 OCF_TRACE_FILE is set to a path.
 
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
index 1e83676a7..2956d1264 100644
--- a/heartbeat/ocf-shellfuncs.in
+++ b/heartbeat/ocf-shellfuncs.in
@@ -1,1047 +1,1048 @@
 #
 #
 # 	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
 # 
 
 # Build version: $Format:%H$
 
 # 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
 
 : ${HA_SBIN_DIR:=@sbindir@}
 
 __SCRIPT_NAME=`basename $0`
 
 if [ -z "$OCF_ROOT" ]; then
     : ${OCF_ROOT=@OCF_ROOT_DIR@}
 fi
 
 if [ "$OCF_FUNCTIONS_DIR" = ${OCF_ROOT}/resource.d/heartbeat ]; then  # old
 	unset OCF_FUNCTIONS_DIR
 fi
 
 : ${OCF_FUNCTIONS_DIR:=${OCF_ROOT}/lib/heartbeat}
 
 . ${OCF_FUNCTIONS_DIR}/ocf-binaries
 . ${OCF_FUNCTIONS_DIR}/ocf-returncodes
 . ${OCF_FUNCTIONS_DIR}/ocf-directories
 . ${OCF_FUNCTIONS_DIR}/ocf-rarun
 . ${OCF_FUNCTIONS_DIR}/ocf-distro
 
 # Define OCF_RESKEY_CRM_meta_interval in case it isn't already set,
 # to make sure that ocf_is_probe() always works
 : ${OCF_RESKEY_CRM_meta_interval=0}
 
 ocf_is_root() {
 	if [ X`id -u` = X0 ]; then
 		true
 	else
 		false
 	fi
 }
 
 ocf_maybe_random() {
 	if test -c /dev/urandom; then
 		od -An -N4 -tu4 /dev/urandom | tr -d '[:space:]'
 	else
 		awk -v pid=$$ 'BEGIN{srand(pid); print rand()}' | sed 's/^.*[.]//'
 	fi
 }
 
 # 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_true() {
 	case "$1" in
 	yes|true|1|YES|TRUE|True|ja|on|ON) true ;;
 	*)	false ;;
 	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 [ "x$__OCF_ACTION" = "xmeta-data" ]; then
 		: ${OCF_RESOURCE_INSTANCE:="RESOURCE_ID"}
 	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 [ -z "$OCF_RESOURCE_INSTANCE" ]; then
 		ha_log "ERROR: Need to tell us our resource instance name."
 		exit $OCF_ERR_ARGS
 	fi
 }
 
 hadate() {
   date "+${HA_DATEFMT}"
 }
 
 set_logtag() {
 	if [ -z "$HA_LOGTAG" ]; then
 		if [ -n "$OCF_RESOURCE_INSTANCE" ]; then
 			HA_LOGTAG="$__SCRIPT_NAME($OCF_RESOURCE_INSTANCE)[$$]"
 		else
 			HA_LOGTAG="$__SCRIPT_NAME[$$]"
 		fi
 	fi
 }
 
 __ha_log() {
 	local ignore_stderr=false
 	local loglevel
 
 	[ "x$1" = "x--ignore-stderr" ] && ignore_stderr=true && shift
 
 	[ none = "$HA_LOGFACILITY" ] && HA_LOGFACILITY=""
 	# if we're connected to a tty, then output to stderr
 	if tty >/dev/null; then
 		if [ "x$HA_debug" = "x0" -a "x$loglevel" = xdebug ] ; then
 			return 0
 		elif [ "$ignore_stderr" = "true" ]; then
 			# something already printed this error to stderr, so ignore
 			return 0
 		fi
 		if [ "$HA_LOGTAG" ]; then
 			echo "$HA_LOGTAG: $*"
 		else
 			echo "$*"
 		fi >&2
 		return 0
 	fi
 
 	set_logtag
 
 	if [ "x${HA_LOGD}" = "xyes" ] ; then 
 		ha_logger -t "${HA_LOGTAG}" "$@"
 		if [ "$?" -eq "0" ] ; then
 			return 0
 		fi
 	fi
 
 	if
 	  [ -n "$HA_LOGFACILITY" ]
         then
 	  : logging through syslog
 	  # loglevel is unknown, use 'notice' for now
           loglevel=notice
           case "${*}" in
             *ERROR*)		loglevel=err;;
             *WARN*)		loglevel=warning;;
             *INFO*|info)	loglevel=info;;
 	  esac
 	  logger -t "$HA_LOGTAG" -p ${HA_LOGFACILITY}.${loglevel} "${*}"
         fi	
         if
 	  [ -n "$HA_LOGFILE" ]
 	then
 	  : appending to $HA_LOGFILE
 	  echo `hadate`" $HA_LOGTAG:    ${*}" >> $HA_LOGFILE
 	fi
 	if
 	  [ -z "$HA_LOGFACILITY" -a -z "$HA_LOGFILE" ] && ! [ "$ignore_stderr" = "true" ]
 	then
 	  : appending to stderr
 	  echo `hadate`"${*}" >&2
 	fi
         if
           [ -n "$HA_DEBUGLOG" ]
         then
           : appending to $HA_DEBUGLOG
 		  if [ "$HA_LOGFILE"x != "$HA_DEBUGLOG"x ]; then
             echo "$HA_LOGTAG:	"`hadate`"${*}" >> $HA_DEBUGLOG
           fi
         fi
 }
 
 ha_log()
 {
 	__ha_log "$@"
 }
 
 ha_debug() {
 
         if [ "x${HA_debug}" = "x0" ] || [ -z "${HA_debug}" ] ; then
                 return 0
         fi
 	if tty >/dev/null; then
 		if [ "$HA_LOGTAG" ]; then
 			echo "$HA_LOGTAG: $*"
 		else
 			echo "$*"
 		fi >&2
 		return 0
 	fi
 
 	set_logtag
 
         if [ "x${HA_LOGD}" = "xyes" ] ; then  
 		ha_logger -t "${HA_LOGTAG}" -D "ha-debug" "$@"
                 if [ "$?" -eq "0" ] ; then
                         return 0
                 fi
         fi
 
 	[ none = "$HA_LOGFACILITY" ] && HA_LOGFACILITY=""
 
 	if
 	  [ -n "$HA_LOGFACILITY" ]
 	then
 	  : logging through syslog
 	  logger -t "$HA_LOGTAG" -p "${HA_LOGFACILITY}.debug" "${*}"
 	fi
         if
 	  [ -n "$HA_DEBUGLOG" ]
 	then
 	  : appending to $HA_DEBUGLOG
 	  echo "$HA_LOGTAG:	"`hadate`"${*}" >> $HA_DEBUGLOG
 	fi
 	if
 	  [ -z "$HA_LOGFACILITY" -a -z "$HA_DEBUGLOG" ]
 	then
 	  : appending to stderr
 	  echo "$HA_LOGTAG:	`hadate`${*}:	${HA_LOGFACILITY}" >&2
 	fi
 }
 
 ha_parameter() {
 	local VALUE
     VALUE=`sed -e 's%[	][	]*% %' -e 's%^ %%' -e 's%#.*%%'   $HA_CF | grep -i "^$1 " | sed 's%[^ ]* %%'`
     if
 	[ "X$VALUE" = X ]
     then
 	
 	case $1 in
 	    keepalive)	VALUE=2;;
 	    deadtime)
 		ka=`ha_parameter keepalive`
 		VALUE=`expr $ka '*' 2 '+' 1`;;
 	esac
     fi
     echo $VALUE
 }
 
 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_exit_reason: print exit error string to stderr
 # Usage:           Allows the OCF script to provide a string
 #                  describing why the exit code was returned.
 # Arguments:   reason - required, The string that represents why the error
 #                       occured.
 #
 ocf_exit_reason()
 {
 	local cookie="$OCF_EXIT_REASON_PREFIX"
 	local fmt
 	local msg
 
 	# No argument is likely not intentional.
 	# Just one argument implies a printf format string of just "%s".
 	# "Least surprise" in case some interpolated string from variable
 	# expansion or other contains a percent sign.
 	# More than one argument: first argument is going to be the format string.
 	case $# in
 	0)	ocf_log err "Not enough arguments to ocf_log_exit_msg." ;;
 	1)	fmt="%s" ;;
 
 	*)	fmt=$1
 		shift
 		case $fmt in
 		*%*) : ;; # ok, does look like a format string
 		*) ocf_log warn "Does not look like format string: [$fmt]" ;;
 		esac ;;
 	esac
 
 	if [ -z "$cookie" ]; then
 		# use a default prefix
 		cookie="ocf-exit-reason:"
 	fi
 
 	msg=$(printf "${fmt}" "$@")
 	printf >&2 "%s%s\n" "$cookie" "$msg"
 	__ha_log --ignore-stderr "ERROR: $msg"
 }
 
 #
 # ocf_deprecated: Log a deprecation warning
 # Usage:          ocf_deprecated [param-name]
 # Arguments:      param-name optional, name of a boolean resource
 #                            parameter that can be used to suppress
 #                            the warning (default
 #                            "ignore_deprecation")
 ocf_deprecated() {
     local param
     param=${1:-ignore_deprecation}
     # don't use ${!param} here, it's a bashism
     if ! ocf_is_true $(eval echo \$OCF_RESKEY_$param); then
 	ocf_log warn "This resource agent is deprecated" \
 	    "and may be removed in a future release." \
 	    "See the man page for details." \
 	    "To suppress this warning, set the \"${param}\"" \
 	    "resource parameter to true."
     fi
 }
 
 #
 # Ocf_run: Run a script, and log its output.
 # Usage:   ocf_run [-q] [-info|-warn|-err] <command>
 #	-q: don't log the output of the command if it succeeds
 #	-info|-warn|-err: log the output of the command at given
 #		severity if it fails (defaults to err)
 #
 ocf_run() {
 	local rc
 	local output
 	local verbose=1
 	local loglevel=err
 	local var
 
 	for var in 1 2
 	do
 	    case "$1" in
 		"-q")
 		    verbose=""
 		    shift 1;;
 		"-info"|"-warn"|"-err")
 		    loglevel=`echo $1 | sed -e s/-//g`
 		    shift 1;;
 		*)
 		    ;;		
 	    esac
 	done
 
 	output=`"$@" 2>&1`
 	rc=$?
 	[ -n "$output" ] && output="$(echo "$output" | tr -s ' \t\r\n' ' ')"
 	if [ $rc -eq 0 ]; then 
 	    if [ "$verbose" -a ! -z "$output" ]; then
 		ocf_log info "$output"
 	    fi
 	else
 	    if [ ! -z "$output" ]; then
 		ocf_log $loglevel "$output"
 	    else
 		ocf_log $loglevel "command failed: $*"
 	    fi
 	fi
 
 	return $rc
 }
 
 ocf_pidfile_status() {
     local pid pidfile=$1
     if [ ! -e $pidfile ]; then
 	# Not exists
 	return 2
     fi
     pid=`cat $pidfile`
     kill -0 $pid > /dev/null 2>&1
     if [ $? = 0 ]; then
 	return 0
     fi
 
     # Stale
     return 1
 }
 
 # mkdir(1) based locking
 # first the directory is created with the name given as $1
 # then a file named "pid" is created within that directory with
 # the process PID
 # stale locks are handled carefully, the inode of a directory
 # needs to match before and after test if the process is running
 # empty directories are also handled appropriately
 # we relax (sleep) occasionally to allow for other processes to
 # finish managing the lock in case they are in the middle of the
 # business
 
 relax() { sleep 0.5; }
 ocf_get_stale_pid() {
 	local piddir pid dir_inode
 
 	piddir="$1"
 	[ -z "$piddir" ] && return 2
 	dir_inode="`ls -di $piddir 2>/dev/null`"
 	[ -z "$dir_inode" ] && return 1
 	pid=`cat $piddir/pid 2>/dev/null`
 	if [ -z "$pid" ]; then
 		# empty directory?
 		relax
 		if [ "$dir_inode" = "`ls -di $piddir 2>/dev/null`" ]; then
 			echo $dir_inode
 		else
 			return 1
 		fi
 	elif kill -0 $pid >/dev/null 2>&1; then
 		return 1
 	elif relax && [ -e "$piddir/pid" ] && [ "$dir_inode" = "`ls -di $piddir 2>/dev/null`" ]; then
 		echo $pid
 	else
 		return 1
 	fi
 }
 
 # There is a race when the following two functions to manage the
 # lock file (mk and rm) are invoked in parallel by different
 # instances. It is up to the caller to reduce probability of that
 # taking place (see ocf_take_lock() below).
 
 ocf_mk_pid() {
 	mkdir $1 2>/dev/null && echo $$ > $1/pid
 }
 ocf_rm_pid() {
 	rm -f $1/pid
 	rmdir $1 2>/dev/null
 }
 
 # Testing and subsequently removing a stale lock (containing the
 # process pid) is inherently difficult to do in such a way as to
 # prevent a race between creating a pid file and removing it and
 # its directory. We reduce the probability of that happening by
 # checking if the stale lock persists over a random period of
 # time.
 
 ocf_take_lock() {
 	local lockdir=$1
 	local rnd
 	local stale_pid
 
 	# we don't want it too short, so strip leading zeros
 	rnd=$(ocf_maybe_random | sed 's/^0*//')
 	stale_pid=`ocf_get_stale_pid $lockdir`
 	if [ -n "$stale_pid" ]; then
 		sleep 0.$rnd
 		# remove "stale pid" only if it persists
 		[ "$stale_pid" = "`ocf_get_stale_pid $lockdir`" ] &&
 			ocf_rm_pid $lockdir
 	fi
 	while ! ocf_mk_pid $lockdir; do
 		ocf_log info "Sleeping until $lockdir is released..."
 		sleep 0.$rnd
 	done
 }
 
 ocf_release_lock_on_exit() {
 	trap "ocf_rm_pid $1" EXIT
 }
 
 # returns true if the CRM is currently running a probe. A probe is
 # defined as a monitor operation with a monitoring interval of zero.
 ocf_is_probe() {
     [ "$__OCF_ACTION" = "monitor" -a "$OCF_RESKEY_CRM_meta_interval" = 0 ]
 }
 
 # returns true if the resource is configured as a clone. This is
 # defined as a resource where the clone-max meta attribute is present.
 ocf_is_clone() {
     [ ! -z "${OCF_RESKEY_CRM_meta_clone_max}" ]
 }
 
 # returns true if the resource is configured as a multistate
 # (master/slave) resource. This is defined as a resource where the
 # master-max meta attribute is present, and set to greater than zero.
 ocf_is_ms() {
     [ "${OCF_RESKEY_CRM_meta_promotable}" = "true" ] || { [ ! -z "${OCF_RESKEY_CRM_meta_master_max}" ] && [ "${OCF_RESKEY_CRM_meta_master_max}" -gt 0 ]; }
 }
 
 # version check functions
 # allow . and - to delimit version numbers
 # max version number is 999
 #
 ocf_is_ver() {
 	echo $1 | grep '^[0-9][0-9.-]*[0-9A-Za-z.\+-]*$' >/dev/null 2>&1
 }
 
 # usage: ocf_version_cmp VER1 VER2
 #     version strings can contain digits, dots, and dashes
 #     must start and end with a digit
 # returns:
 #     0: VER1 smaller (older) than VER2
 #     1: versions equal
 #     2: VER1 greater (newer) than VER2
 #     3: bad format
 ocf_version_cmp() {
 	ocf_is_ver "$1" || return 3
 	ocf_is_ver "$2" || return 3
 	local v1=$1
 	local v2=$2
 
 	sort_version="sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n"
 	older=$( (echo "$v1"; echo "$v2") | $sort_version | head -1 )
 
 	if [ "$v1" = "$v2" ]; then
 		return 1
 	elif [ "$v1" = "$older" ]; then
 		return 0
 	else
 		return 2 # -1 would look funny in shell ;-)
 	fi
 }
 
 ocf_local_nodename() {
 	# use crm_node -n for pacemaker > 1.1.8
 	which pacemakerd > /dev/null 2>&1
 	if [ $? -eq 0 ]; then
 		local version=$(pacemakerd -$ | grep "Pacemaker .*" | awk '{ print $2 }')
 		version=$(echo $version | awk -F- '{ print $1 }')
 		ocf_version_cmp "$version" "1.1.8"
 		if [ $? -eq 2 ]; then
 			which crm_node > /dev/null 2>&1
 			if [ $? -eq 0 ]; then
 				crm_node -n
 				return
 			fi
 		fi
 	fi
 
 	# otherwise use uname -n
 	uname -n
 }
 
 # usage: dirname DIR
 dirname()
 {
 	local a
 	local b
 
 	[ $# = 1 ] || return 1
 	a="$1"
 	while [ 1 ]; do
 		b="${a%/}"
 		[ "$a" = "$b" ] && break
 		a="$b"
 	done
 	b=${a%/*}
 	[ -z "$b" -o "$a" = "$b"  ] && b="."
 
 	echo "$b"
 	return 0
 }
 
 # usage: systemd_is_running
 # returns:
 #    0  PID 1 is systemd
 #    1  otherwise
 systemd_is_running()
 {
 	[ "$(cat /proc/1/comm 2>/dev/null)" = "systemd" ]
 }
 
 # usage: systemd_drop_in <name> <After|Before> <dependency.service>
 systemd_drop_in()
 {
 	local conf_file
 	if [ $# -ne 3 ]; then
           ocf_log err "Incorrect number of arguments [$#] for systemd_drop_in."
         fi
 
 	systemdrundir="/run/systemd/system/resource-agents-deps.target.d"
 	mkdir -p "$systemdrundir"
 	conf_file="$systemdrundir/$1.conf"
 	cat >"$conf_file" <<EOF
 [Unit]
 $2=$3
 EOF
 	# The information is accessible through systemd API and systemd would
 	# complain about improper permissions.
 	chmod o+r "$conf_file"
 	systemctl daemon-reload
 }
 
 # usage: crm_mon_no_validation args...
 # run crm_mon without any cib schema validation
 # This is useful when an agent runs in a bundle to avoid potential
 # schema validation errors when host and bundle are not perfectly aligned
 # To be used, your shell must support on process substitution (e.g. bash)
 # returns:
 #    <crm_mon error codes>
 crm_mon_no_validation()
 {
 	# The subshell prevents parsing error with incompatible shells
 	"$SHELL" -c "CIB_file=<(${HA_SBIN_DIR}/cibadmin -Q | sed 's/validate-with=\"[^\"]*\"/validate-with=\"none\"/') \
 	${HA_SBIN_DIR}/crm_mon \$*" -- $*
 }
 
 #
 # pseudo_resource status tracking function...
 #
 # This allows pseudo resources to give correct status information.  As we add
 # resource monitoring, and better resource tracking in general, this will
 # become essential.
 #
 # These scripts work because ${HA_RSCTMP} is cleaned on node reboot.
 #
 # We create "resource-string" tracking files under ${HA_RSCTMP} in a
 # very simple way:
 #
 #	Existence of "${HA_RSCTMP}/resource-string" means that we consider
 #	the resource named by "resource-string" to be running.
 #
 # Note that "resource-string" needs to be unique.  Using the resource type
 # plus the resource instance arguments to make up the resource string
 # is probably sufficient...
 #
 # usage: ha_pseudo_resource resource-string op [tracking_file]
 # 	where op is {start|stop|monitor|status|restart|reload|print}
 #	print is a special op which just prints the tracking file location
 #	user can override our choice of the tracking file location by
 #		specifying it as the third arg
 #	Note that all operations are silent...
 #
 ha_pseudo_resource()
 {
   local ha_resource_tracking_file="${3:-${HA_RSCTMP}/$1}"
   case $2 in
     start|restart|reload)  touch "$ha_resource_tracking_file";;
     stop) rm -f "$ha_resource_tracking_file";;
     status|monitor)
            if
              [ -f "$ha_resource_tracking_file" ]
            then
              return 0
            else
              case $2 in
                status)	return 3;;
                *)	return 7;;
              esac
            fi;;
     print)  echo "$ha_resource_tracking_file";;
     *)	return 3;;
   esac
 }
 
 # usage: rmtempdir TMPDIR
 rmtempdir()
 {
 	[ $# = 1 ] || return 1
 	if [ -e "$1" ]; then
 		rmdir "$1" || return 1
 	fi
 	return 0
 }
 
 # usage: maketempfile [-d]
 maketempfile()
 {
 	if [ $# = 1 -a "$1" = "-d" ]; then
 		mktemp -d
 		return 0
 	elif [ $# != 0 ]; then
 		return 1
 	fi
 
 	mktemp
 	return 0
 }
 
 # usage: rmtempfile TMPFILE
 rmtempfile ()
 {
 	[ $# = 1 ] || return 1
 	if [ -e "$1" ]; then
 		rm "$1" || return 1
 	fi
 	return 0
 }
 
 # echo the first lower supported check level
 # pass set of levels supported by the agent
 # (in increasing order, 0 is optional)
 ocf_check_level()
 {
 	local lvl prev
 	lvl=0
 	prev=0
 	if ocf_is_decimal "$OCF_CHECK_LEVEL"; then
 		# the level list should be very short
 		for lvl; do
 			if [ "$lvl" -eq "$OCF_CHECK_LEVEL" ]; then
 				break
 			elif [ "$lvl" -gt "$OCF_CHECK_LEVEL" ]; then
 				lvl=$prev # the previous one
 				break
 			fi
 			prev=$lvl
 		done
 	fi
 	echo $lvl
 }
 
 # usage: ocf_stop_processes SIGNALS WAIT_TIME PIDS
 #
 # we send signals (use quotes for more than one!) in the order
 # given; if one or more processes are still running we try KILL;
 # the wait_time is the _total_ time we'll spend in this function
 # this time may be slightly exceeded if the processes won't leave
 # 
 # returns:
 #     0: all processes left
 #     1: some processes still running
 #
 # example:
 #
 # ocf_stop_processes TERM 5 $pids
 # 
 ocf_stop_processes() {
 	local signals="$1"
 	local wait_time="$(($2/`echo $signals|wc -w`))"
 	shift 2
 	local pids="$*"
 	local sig i
 	test -z "$pids" &&
 		return 0
 	for sig in $signals KILL; do
 		kill -s $sig $pids 2>/dev/null
 		# try to leave early, and yet leave processes time to exit
 		sleep 0.2
 		for i in `seq $wait_time`; do
 			kill -s 0 $pids 2>/dev/null ||
 				return 0
 			sleep 1
 		done
 	done
 	return 1
 }
 
 #
 # create a given status directory
 # if the directory path doesn't start with $HA_VARRUN, then
 # we return with error (most of the calls would be with the user
 # supplied configuration, hence we need to do necessary
 # protection)
 # used mostly for PID files
 #
 # usage: ocf_mkstatedir owner permissions path
 #
 # owner: user.group
 # permissions: permissions
 # path: directory path
 #
 # example:
 #	ocf_mkstatedir named 755 `dirname $pidfile`
 #
 ocf_mkstatedir()
 {
 	local owner
 	local perms
 	local path
 
 	owner=$1
 	perms=$2
 	path=$3
 
 	test -d $path && return 0
 	[ $(id -u) = 0 ] || return 1
 
 	case $path in
 	${HA_VARRUN%/}/*) : this path is ok ;;
 	*) ocf_log err "cannot create $path (does not start with $HA_VARRUN)"
 		return 1
 	;;
 	esac
 
 	mkdir -p $path &&
 	chown $owner $path &&
 	chmod $perms $path
 }
 
 #
 # create a unique status directory in $HA_VARRUN
 # used mostly for PID files
 # the directory is by default set to
 #   $HA_VARRUN/$OCF_RESOURCE_INSTANCE
 # the directory name is printed to stdout
 #
 # usage: ocf_unique_rundir owner permissions name
 #
 # owner: user.group (default: "root")
 # permissions: permissions (default: "755")
 # name: some unique string (default: "$OCF_RESOURCE_INSTANCE")
 #
 # to use the default either don't set the parameter or set it to
 # empty string ("")
 # example:
 #
 #	STATEDIR=`ocf_unique_rundir named "" myownstatedir`
 #
 ocf_unique_rundir()
 {
 	local path
 	local owner
 	local perms
 	local name
 
 	owner=${1:-"root"}
 	perms=${2:-"755"}
 	name=${3:-"$OCF_RESOURCE_INSTANCE"}
 	path=$HA_VARRUN/$name
 	if [ ! -d $path ]; then
 		[ $(id -u) = 0 ] || return 1
 		mkdir -p $path &&
 		chown $owner $path &&
 		chmod $perms $path || return 1
 	fi
 	echo $path
 }
 
 #
 # RA tracing may be turned on by setting OCF_TRACE_RA
 # the trace output will be saved to OCF_TRACE_FILE, if set, or
 # by default to
 #   $HA_VARLIB/trace_ra/<type>/<id>.<action>.<timestamp>
 #   e.g. $HA_VARLIB/trace_ra/oracle/db.start.2012-11-27.08:37:08
 #
 # OCF_TRACE_FILE:
 # - FD (small integer [3-9]) in that case it is up to the callers
 #   to capture output; the FD _must_ be open for writing
 # - absolute path
 #
 # NB: FD 9 may be used for tracing with bash >= v4 in case
 # OCF_TRACE_FILE is set to a path.
 #
 ocf_bash_has_xtracefd() {
 	[ -n "$BASH_VERSION" ] && [ ${BASH_VERSINFO[0]} -ge 4 ]
 }
 # for backwards compatibility
 ocf_is_bash4() {
 	ocf_bash_has_xtracefd
 }
 ocf_trace_redirect_to_file() {
 	local dest=$1
 	if ocf_bash_has_xtracefd; then
 		exec 9>$dest
 		BASH_XTRACEFD=9
 	else
 		exec 2>$dest
 	fi
 }
 ocf_trace_redirect_to_fd() {
 	local fd=$1
 	if ocf_bash_has_xtracefd; then
 		BASH_XTRACEFD=$fd
 	else
 		exec 2>&$fd
 	fi
 }
 __ocf_test_trc_dest() {
 	local dest=$1
 	if ! touch $dest; then
 		ocf_log warn "$dest not writable, trace not going to happen"
 		__OCF_TRC_DEST=""
 		__OCF_TRC_MANAGE=""
 		return 1
 	fi
 	return 0
 }
 ocf_default_trace_dest() {
 	tty >/dev/null && return
 	if [ -n "$OCF_RESOURCE_TYPE" -a \
 			-n "$OCF_RESOURCE_INSTANCE" -a -n "$__OCF_ACTION" ]; then
 		local ts=`date +%F.%T`
-		__OCF_TRC_DEST=$HA_VARLIB/trace_ra/${OCF_RESOURCE_TYPE}/${OCF_RESOURCE_INSTANCE}.${__OCF_ACTION}.$ts
+		__OCF_TRC_DEST=${OCF_RESKEY_trace_dir}/${OCF_RESOURCE_TYPE}/${OCF_RESOURCE_INSTANCE}.${__OCF_ACTION}.$ts
 		__OCF_TRC_MANAGE="1"
 	fi
 }
 
 ocf_start_trace() {
 	export __OCF_TRC_DEST="" __OCF_TRC_MANAGE=""
 	case "$OCF_TRACE_FILE" in
 	[3-9]) ocf_trace_redirect_to_fd "$OCF_TRACE_FILE" ;;
 	/*/*) __OCF_TRC_DEST=$OCF_TRACE_FILE ;;
 	"") ocf_default_trace_dest ;;
 	*)
 		ocf_log warn "OCF_TRACE_FILE must be set to either FD (open for writing) or absolute file path"
 		ocf_default_trace_dest
 		;;
 	esac
 	if [ "$__OCF_TRC_DEST" ]; then
 		mkdir -p `dirname $__OCF_TRC_DEST`
 		__ocf_test_trc_dest $__OCF_TRC_DEST ||
 			return
 		ocf_trace_redirect_to_file "$__OCF_TRC_DEST"
 	fi
 	if [ -n "$BASH_VERSION" ]; then
 		PS4='+ `date +"%T"`: ${FUNCNAME[0]:+${FUNCNAME[0]}:}${LINENO}: '
 	fi
 	set -x
 	env=$( echo; printenv | sort )
 }
 ocf_stop_trace() {
 	set +x
 }
 
 # Helper functions to map from nodename/bundle-name and physical hostname
 # list_index_for_word "node0 node1 node2 node3 node4 node5" node4 --> 5
 # list_word_at_index "NA host1 host2 host3 host4 host5" 3      --> host2
 
 # list_index_for_word "node1 node2 node3 node4 node5" node7 --> ""
 # list_word_at_index "host1 host2 host3 host4 host5" 8      --> ""
 
 # attribute_target node1                                    --> host1
 list_index_for_word() {
 	echo $1 | tr ' ' '\n' | awk -v x="$2" '$0~x {print NR}'
 }
 
 list_word_at_index() {
 	echo $1 | tr ' ' '\n' | awk -v n="$2" 'n == NR'
 }
 
 ocf_attribute_target() {
 	if [ x$1 = x ]; then
 		if [ x$OCF_RESKEY_CRM_meta_container_attribute_target = xhost -a x$OCF_RESKEY_CRM_meta_physical_host != x ]; then
 			echo $OCF_RESKEY_CRM_meta_physical_host
 		else
 			if [ x$OCF_RESKEY_CRM_meta_on_node != x ]; then
 				echo $OCF_RESKEY_CRM_meta_on_node
 			else
 				ocf_local_nodename
 			fi
 		fi
 		return
 	elif [ x"$OCF_RESKEY_CRM_meta_notify_all_uname" != x ]; then
 		index=$(list_index_for_word "$OCF_RESKEY_CRM_meta_notify_all_uname" $1)
 		mapping=""
 		if [ x$index != x ]; then
 			mapping=$(list_word_at_index "$OCF_RESKEY_CRM_meta_notify_all_hosts" $index)
 		fi
 		if [ x$mapping != x -a x$mapping != xNA ]; then
 			echo $mapping
 			return
 		fi
 	fi
 	echo $1
 }
 
 __ocf_set_defaults "$@"
 
 : ${OCF_TRACE_RA:=$OCF_RESKEY_trace_ra}
+: ${OCF_RESKEY_trace_dir:="$HA_VARLIB/trace_ra"}
 ocf_is_true "$OCF_TRACE_RA" && ocf_start_trace
 
 # pacemaker sets HA_use_logd, some others use HA_LOGD :/
 if ocf_is_true "$HA_use_logd"; then
 	: ${HA_LOGD:=yes}
 fi