[Debian-ha-commits] [cluster-glue] 12/73: Imported Upstream version 1.0.6

Richard Winters devrik-guest at moszumanska.debian.org
Sat Apr 18 20:24:30 UTC 2015


This is an automated email from the git hooks/post-receive script.

devrik-guest pushed a commit to branch master
in repository cluster-glue.

commit d53fb56109fe60a2e0e46ce59788a52ac8ceb3e5
Author: Richard B Winters <rik at mmogp.com>
Date:   Sat Apr 18 07:44:59 2015 -0400

    Imported Upstream version 1.0.6
---
 .hg_archival.txt                     |   2 +-
 .hgtags                              |   1 +
 ChangeLog                            |  19 +++++
 cluster-glue-fedora.spec             |   3 +-
 cluster-glue-suse.spec               |   3 +-
 configure.ac                         |  23 +++---
 doc/stonith/Makefile.am              |   1 +
 doc/stonith/README.rackpdu           |  21 +++++
 hb_report/hb_report.in               |  36 +++++++--
 hb_report/utillib.sh                 |   3 +-
 include/clplumbing/ipc.h             |  51 +++++++++---
 include/glue_config.h.in             |   6 +-
 include/lrm/lrm_api.h                |   4 +
 include/lrm/lrm_msg.h                |   2 +-
 include/stonith/stonith.h            |   1 +
 lib/clplumbing/Makefile.am           |   2 +-
 lib/clplumbing/ipcsocket.c           |  75 ++++++++++++++----
 lib/clplumbing/ocf_ipc.c             |   2 +
 lib/lrm/clientlib.c                  |  10 ++-
 lib/plugins/stonith/external/ibmrsa  |   4 +-
 lib/plugins/stonith/external/rackpdu |  44 +++++++----
 lib/plugins/stonith/external/sbd     |  24 +-----
 lib/plugins/stonith/external/xen0    |   8 +-
 lib/stonith/ha_log.sh                |   7 +-
 lib/stonith/main.c                   |  52 +++++++++++--
 lib/stonith/sbd.c                    |  32 +++++++-
 lib/stonith/stonith.c                |  41 ++++++++++
 logd/ha_logger.c                     |  50 ++++--------
 lrm/admin/Makefile.am                |   8 ++
 lrm/admin/lrmadmin.c                 |  41 +++++-----
 lrm/lrmd/lrmd.c                      | 147 ++++++++++++++++++++---------------
 lrm/lrmd/lrmd.h                      |   7 +-
 lrm/lrmd/lrmd_fdecl.h                |   4 +-
 33 files changed, 500 insertions(+), 234 deletions(-)

diff --git a/.hg_archival.txt b/.hg_archival.txt
index e530f24..8971d18 100644
--- a/.hg_archival.txt
+++ b/.hg_archival.txt
@@ -1,2 +1,2 @@
 repo: e3ffdd7ae81c596b2be7e1e110d2c1255161340e
-node: 3af80b93d9e5d5e441f3f4c3aad16775ea27d2d9
+node: 1c87a0c58c59fc384b93ec11476cefdbb6ddc1e1
diff --git a/.hgtags b/.hgtags
index 5179d8c..0bdbda0 100644
--- a/.hgtags
+++ b/.hgtags
@@ -55,3 +55,4 @@ f6c2cd2593f365f984ce051db61466738ac05dcd Beta-0.4.9f
 2e33ecd820b2673755d1280a259489a026921f63 glue-1.0.3
 761edff8c35ea2cdf3e1bd37d600b06233e61d4f glue-1.0.4-rc1
 3229873980e1028bf05de81f5bafccb3a92b9aa4 glue-1.0.4
+3af80b93d9e5d5e441f3f4c3aad16775ea27d2d9 glue-1.0.5
diff --git a/ChangeLog b/ChangeLog
index 2d22512..9cb84c4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,23 @@
+* Fri Jul  9 2010 Dejan Muhamedagic <dejan at suse.de>
+- stable release 1.0.6
+- clplumbing: Add identity info of the user on the other side of socket
+- ha_logger: log strings longer than 1024
+- lrmd: remove operation history on client unregister (lf#2161)
+- lrmd: don't allow cancelled operations to get back to the repeating op list (lf#2417)
+- lrmd: exclude stonith resources from child count (bnc#612387)
+- lrmd,clientlib: asynchronous resource delete notification (lf#2439)
+- stonith: add -V (version) to stonith
+- stonith: add -E option to get the configuration from the environment
+- stonith: ha_log: feed the message to stdout and not on command line
+- stonith: external/sbd,xen0: fix wrong reference from ha_log to ha_log.sh (deb#585120)
+- stonith: external/sbd: reduce monitoring
+- stonith: external/rackpdu: check the snmpset and snmpwalk exit codes
+- hb_report: create cib.txt after sanitizing the CIB (lf#2415)
+
 * Mon Apr 15 2010 Dejan Muhamedagic <dejan at suse.de>
 - stable release 1.0.5
 - clplumbing: revert changeset 81ad41d14f72 which breaks the ABI
+
 * Mon Apr 12 2010 Dejan Muhamedagic <dejan at suse.de>
 - stable release 1.0.4
 - clplumbing: fix memory leak in cl_msg/lrmd (lf#1841,2389)
@@ -29,9 +46,11 @@
 - hb_report: when creating cts reports get information from the log
 - hb_report: new option -d to keep the directory
 - hb_report: don't give up early when creating backtraces (lf#2350)
+
 * Tue Feb 02 2010 Dejan Muhamedagic <dejan at suse.de>
 - bugfix release 1.0.3
 - lrmd: don't flush operations which don't belong to the requesting client (lf#2161)
+
 * Mon Feb 01 2010 Dejan Muhamedagic <dejan at suse.de> and MANY others
 - stable release 1.0.2
 - clplumbing: fix a potential resource leak in cl_random (bnc#525393)
diff --git a/cluster-glue-fedora.spec b/cluster-glue-fedora.spec
index bdc4f3b..1f16ce1 100644
--- a/cluster-glue-fedora.spec
+++ b/cluster-glue-fedora.spec
@@ -15,7 +15,7 @@
 
 Name:		cluster-glue
 Summary:	Reusable cluster components
-Version:	1.0.5
+Version:	1.0.6
 Release:	1%{?dist}
 License:	GPLv2+ and LGPLv2+
 Url:		http://www.linux-ha.org/wiki/Cluster_Glue
@@ -39,6 +39,7 @@ BuildRequires: automake autoconf libtool pkgconfig which
 BuildRequires: bzip2-devel glib2-devel python-devel libxml2-devel
 BuildRequires: OpenIPMI-devel openssl-devel
 BuildRequires: libxslt docbook-dtds docbook-style-xsl
+BuildRequires: help2man
 
 %if 0%{?fedora} 
 BuildRequires:    libcurl-devel libnet-devel
diff --git a/cluster-glue-suse.spec b/cluster-glue-suse.spec
index f6cec14..140494e 100644
--- a/cluster-glue-suse.spec
+++ b/cluster-glue-suse.spec
@@ -29,7 +29,7 @@
 
 Name:           cluster-glue
 Summary:        Reusable cluster components
-Version:        1.0.5
+Version:        1.0.6
 Release:        1%{?dist}
 License:        GPL v2 or later; LGPL v2.1 or later
 Url:            http://www.linux-ha.org/wiki/Cluster_Glue
@@ -40,6 +40,7 @@ AutoReqProv:    on
 BuildRequires:  automake autoconf libtool e2fsprogs-devel glib2-devel pkgconfig python-devel libxml2-devel
 BuildRequires:  libnet net-snmp-devel OpenIPMI-devel openhpi-devel
 BuildRequires:  libxslt docbook_4 docbook-xsl-stylesheets
+BuildRequires:  help2man
 
 Obsoletes:	heartbeat-common
 Provides:	heartbeat-common
diff --git a/configure.ac b/configure.ac
index 765f9d4..8014ca0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,7 @@ dnl     checks for compiler characteristics
 dnl     checks for library functions
 dnl     checks for system services
 
-AC_INIT(cluster-glue, 1.0.5, linux-ha-dev at lists.linux-ha.org)
+AC_INIT(cluster-glue, 1.0.6, linux-ha-dev at lists.linux-ha.org)
 
 PKG_FEATURES=""
 HB_PKG=heartbeat
@@ -427,19 +427,19 @@ AC_SUBST(LRM_DIR)
 
 AC_PATH_PROGS(HG, hg false)
 AC_MSG_CHECKING(build version)
-BUILD_VERSION=unknown
+GLUE_BUILD_VERSION=unknown
 if test -f $srcdir/.hg_archival.txt; then
-   BUILD_VERSION=`cat $srcdir/.hg_archival.txt | awk '/node:/ { print $2 }'`
+   GLUE_BUILD_VERSION=`cat $srcdir/.hg_archival.txt | awk '/node:/ { print $2 }'`
 elif test -x $HG -a -d .hg; then
-   BUILD_VERSION=`$HG id -itb`
+   GLUE_BUILD_VERSION=`$HG id -itb`
    if test $? != 0; then
-       BUILD_VERSION=unknown
+       GLUE_BUILD_VERSION=unknown
    fi
 fi
 
-AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version)
-AC_MSG_RESULT($BUILD_VERSION)
-AC_SUBST(BUILD_VERSION)
+AC_DEFINE_UNQUOTED(GLUE_BUILD_VERSION, "$GLUE_BUILD_VERSION", Build version)
+AC_MSG_RESULT($GLUE_BUILD_VERSION)
+AC_SUBST(GLUE_BUILD_VERSION)
 
 
 dnl check if there are getpid() inconsistency
@@ -1140,7 +1140,10 @@ CC_ERRORS=""
 CC_EXTRAS=""
 
 if export | fgrep " CFLAGS=" > /dev/null; then
-	export -n CFLAGS || true # We don't want to bomb out if this fails
+	SAVED_CFLAGS="$CFLAGS"
+	unset CFLAGS
+	CFLAGS="$SAVED_CFLAGS"
+	unset SAVED_CFLAGS
 fi
 
 if test "$GCC" != yes; then
@@ -1333,7 +1336,7 @@ dnl *****************
 
 AC_MSG_RESULT([])
 AC_MSG_RESULT([$PACKAGE configuration:])
-AC_MSG_RESULT([  Version                  = ${VERSION} (Build: $BUILD_VERSION)])
+AC_MSG_RESULT([  Version                  = ${VERSION} (Build: $GLUE_BUILD_VERSION)])
 AC_MSG_RESULT([  Features                 =${PKG_FEATURES}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([  Prefix                   = ${prefix}])
diff --git a/doc/stonith/Makefile.am b/doc/stonith/Makefile.am
index 3cb8248..a5b93c6 100644
--- a/doc/stonith/Makefile.am
+++ b/doc/stonith/Makefile.am
@@ -25,6 +25,7 @@ stdoc_DATA 		= README.bladehpi \
 			  README.ibmrsa-telnet \
 			  README.ipmilan \
 			  README.meatware \
+			  README.rackpdu \
 			  README.rcd_serial \
 			  README.riloe \
 			  README.vacm \
diff --git a/doc/stonith/README.rackpdu b/doc/stonith/README.rackpdu
new file mode 100644
index 0000000..69a0f44
--- /dev/null
+++ b/doc/stonith/README.rackpdu
@@ -0,0 +1,21 @@
+APC Rack PDU
+
+The product information pages:
+
+http://www.apcc.com/products/family/index.cfm?id=70
+
+The User's Guide:
+
+http://www.apcmedia.com/salestools/ASTE-6Z6KAV_R1_EN.pdf
+
+Apparently, an existing http or telnet session will make the
+plugin fail.
+
+In case your nodes are equipped with multiple power supplies, the
+PDU supports synchronous operation on multiple outlets on up to
+four Switched Rack PDUs. See the User's Guide for more
+information on how to setup outlet groups.
+
+NB: There has been a report by one user that in case a link
+between two PDUs in the chain is broken, the PDU returns success
+even though it failed. This needs to be verified.
diff --git a/hb_report/hb_report.in b/hb_report/hb_report.in
index 6c7237b..048a20d 100755
--- a/hb_report/hb_report.in
+++ b/hb_report/hb_report.in
@@ -121,19 +121,24 @@ EOF
 	  hb_report -f cts:133 /tmp/ctstest_133
 
 	. WARNING . WARNING . WARNING . WARNING . WARNING . WARNING .
-	  We try to sanitize the CIB and the peinputs files. If you
-	  have more sensitive information, please supply additional
-	  patterns yourself. The logs and the crm_mon, ccm_tool, and
-	  crm_verify output are *not* sanitized.
+
+	  We won't sanitize the CIB and the peinputs files, because
+	  that would make them useless when trying to reproduce the
+	  PE behaviour. You may still choose to obliterate sensitive
+	  information if you use the -s and -p options, but in that
+	  case the support may be lacking as well. The logs and the
+	  crm_mon, ccm_tool, and crm_verify output are *not* sanitized.
+
 	  Additional system logs (/var/log/messages) are collected in
 	  order to have a more complete report. If you don't want that
 	  specify -M.
+
 	  IT IS YOUR RESPONSIBILITY TO PROTECT THE DATA FROM EXPOSURE!
 EOF
 	exit
 }
 version() {
-	echo "@PACKAGE_NAME@: @PACKAGE_VERSION@ (@BUILD_VERSION@)"
+	echo "@PACKAGE_NAME@: @PACKAGE_VERSION@ (@GLUE_BUILD_VERSION@)"
 	exit
 }
 #
@@ -516,7 +521,7 @@ pe2png() {
 	(
 	cd `dirname $1`
 	ptest -D $dotf -x $pef
-	dot -Tpng -o $pngf $dotf >/dev/null 2>&1
+	# dot -Tpng -o $pngf $dotf >/dev/null 2>&1
 	)
 }
 getpeinputs() {
@@ -551,6 +556,20 @@ touch_DC_if_dc() {
 		touch $1/DC
 	fi
 }
+getconfigurations() {
+	local dest=$1
+	for conf in $CONFIGURATIONS; do
+		if [ -f $conf ]; then
+			cp -p $conf $dest
+		elif [ -d $conf ]; then
+			(
+			cd `dirname $conf` &&
+			tar cf - `basename $conf` | (cd $dest && tar xf -)
+			)
+		fi
+	done
+}
+
 
 #
 # some basic system info and stats
@@ -912,7 +931,6 @@ if [ "$SLAVE" = "" ]; then
 			u) SSH_USER="$OPTARG";;
 			l) HA_LOG="$OPTARG";;
 			e) EDITOR="$OPTARG";;
-			s) DO_SANITIZE="1";;
 			p) SANITIZE="$SANITIZE $OPTARG";;
 			s) DO_SANITIZE="1";;
 			L) LOG_PATTERNS="$LOG_PATTERNS $OPTARG";;
@@ -1047,6 +1065,8 @@ PERMISSIONS_F=permissions.txt
 CIB_F=cib.xml
 CIB_TXT_F=cib.txt
 export CRM_MON_F MEMBERSHIP_F CRM_VERIFY_F CIB_F CIB_TXT_F HB_UUID_F PERMISSIONS_F
+CONFIGURATIONS="/etc/drbd.conf /etc/drbd.d"
+export CONFIGURATIONS
 
 # this only on master
 if [ "$SLAVE" = "" ]; then
@@ -1180,8 +1200,10 @@ if [ "$THIS_IS_NODE" ]; then
 	getconfig $DESTDIR/$WE
 	getpeinputs $FROM_TIME $TO_TIME $DESTDIR/$WE
 	getbacktraces $FROM_TIME $TO_TIME $DESTDIR/$WE/$BT_F
+	getconfigurations $DESTDIR/$WE
 	touch_DC_if_dc $DESTDIR/$WE
 	sanitize $DESTDIR/$WE
+	crmconfig $DESTDIR/$WE
 	check_perms > $DESTDIR/$WE/$PERMISSIONS_F 2>&1
 	sys_info > $DESTDIR/$WE/$SYSINFO_F 2>&1
 	dlm_dump > $DESTDIR/$WE/$DLM_DUMP_F 2>&1
diff --git a/hb_report/utillib.sh b/hb_report/utillib.sh
index 96c22ed..96c3c43 100644
--- a/hb_report/utillib.sh
+++ b/hb_report/utillib.sh
@@ -404,9 +404,10 @@ getconfig() {
 		crm_uuid -r > $1/$HB_UUID_F 2>&1
 	[ -f "$1/$CIB_F" ] &&
 		crm_verify -V -x $1/$CIB_F >$1/$CRM_VERIFY_F 2>&1
+}
+crmconfig() {
 	[ -f "$1/$CIB_F" ] && which crm >/dev/null 2>&1 &&
 		CIB_file=$1/$CIB_F crm configure show >$1/$CIB_TXT_F 2>&1
-
 }
 get_crm_nodes() {
 	cibadmin -Ql -o nodes |
diff --git a/include/clplumbing/ipc.h b/include/clplumbing/ipc.h
index bd60bca..5afae2b 100644
--- a/include/clplumbing/ipc.h
+++ b/include/clplumbing/ipc.h
@@ -178,6 +178,18 @@ struct IPC_CHANNEL{
 	int		conntype;
 	
 	char		failreason[MAXFAILREASON];
+
+	/* New members to support Multi-level ACLs for the CIB,
+	 * available since libplumb.so.2.1.0, added at the
+	 * end of the struct to maintain backwards ABI compatibility.
+	 *
+	 * If you don't like to care for library versions,
+	 * create your IPC channels with
+	 *  c = ipc_wait_conn_constructor(IPC_UDS_CRED, ...),
+	 * and these members will be available.
+	 */
+	uid_t		farside_uid;	/* far side uid */
+	gid_t		farside_gid;	/* far side gid */
 };
 
 struct IPC_QUEUE{
@@ -612,9 +624,18 @@ struct IPC_OPS{
  *    the pointer to a new waiting connection or NULL if the connection
  *			can't be created.
  * Note:
- *    current implementation only supports unix domain socket 
- *    whose type is IPC_DOMAIN_SOCKET 
- *
+ *    current implementation supports
+ *    IPC_ANYTYPE:       This is what program code should typically use.
+ *                       Internally it is an alias to IPC_UDS_CRED.
+ *    IPC_UDS_CRED:      Unix Domain Sockets,
+ *                       farside uid + gid credentials is available.
+ *                       Available since libplumb.so.2.1.0.
+ *    IPC_DOMAIN_SOCKET: An other alias to Unix Domain Sockets;
+ *                       internally it is equivalent to both above.
+ *                       Using this explicitly, your code will work
+ *                       even with libplumb.so.2.0.0.
+ *                       Which also means that you MUST NOT use the
+ *                       farside_uid/gid functionality then.
  */
 extern IPC_WaitConnection * ipc_wait_conn_constructor(const char * ch_type
 ,	GHashTable* ch_attrs);
@@ -637,9 +658,8 @@ extern IPC_WaitConnection * ipc_wait_conn_constructor(const char * ch_type
  *	or NULL if the channel can't be created.
  *
  * Note:
- *   current implementation only support unix domain socket 
- *   whose type is IPC_DOMAIN_SOCKET 
- *
+ *    See comments for ipc_wait_conn_constructor above
+ *    for currently implemented ch_type channel types.
  */
 extern IPC_Channel  * ipc_channel_constructor(const char * ch_type
 ,	GHashTable* ch_attrs);
@@ -749,12 +769,19 @@ void	ipc_bufpool_unref(struct ipc_bufpool* pool);
 
 void	set_ipc_time_debug_flag(gboolean flag);
 
-#define	IPC_PATH_ATTR		"path"		/* pathname attribute */
-#define	IPC_DOMAIN_SOCKET	"uds"		/* Unix domain socket */
-#define IPC_MODE_ATTR           "sockmode"      /* socket mode attribute */
-
-#ifdef IPC_DOMAIN_SOCKET
-#	define	IPC_ANYTYPE		IPC_DOMAIN_SOCKET
+/* pathname attribute */
+#define	IPC_PATH_ATTR		"path"
+/* socket mode attribute */
+#define IPC_MODE_ATTR           "sockmode"
+/* Unix domain socket, used by old code.
+ * See also the comment block above ipc_wait_conn_constructor() */
+#define	IPC_DOMAIN_SOCKET	"uds"
+/* Unix domain socket with farside uid + gid credentials.
+ * Available since libplumb.so.2.1.0 */
+#define	IPC_UDS_CRED		"uds_c"
+
+#ifdef IPC_UDS_CRED
+#	define	IPC_ANYTYPE		IPC_UDS_CRED
 #else
 #	error "No IPC types defined(!)"
 #endif
diff --git a/include/glue_config.h.in b/include/glue_config.h.in
index a139da0..f2ff3f8 100644
--- a/include/glue_config.h.in
+++ b/include/glue_config.h.in
@@ -77,9 +77,12 @@
 /* Compiling for Linux platform */
 #undef ON_LINUX
 
-/* Current pacemaker version */
+/* Current glue version */
 #undef GLUE_VERSION
 
+/* Build version */
+#undef GLUE_BUILD_VERSION
+
 /* Location of non-pluing stonith scripts */
 #undef STONITH_EXT_PLUGINDIR
 
@@ -93,4 +96,3 @@
 #undef ST_TEXTDOMAIN
 
 #undef HA_HBCONF_DIR
-
diff --git a/include/lrm/lrm_api.h b/include/lrm/lrm_api.h
index a273aaa..cebff1b 100644
--- a/include/lrm/lrm_api.h
+++ b/include/lrm/lrm_api.h
@@ -149,6 +149,7 @@ typedef struct{
 	unsigned long		t_rcchange; /* last rc change (as age) */
 	unsigned long		exec_time; /* time it took the op to run */
 	unsigned long		queue_time; /* time spent in queue */
+	int			rsc_deleted; /* resource just deleted? */
 }lrm_op_t;
 
 extern const lrm_op_t lrm_zero_op;	/* an all-zeroes lrm_op_t value */
@@ -172,6 +173,9 @@ enum { DEFAULT_FAIL_RC = EXECRA_UNKNOWN_ERROR };
 #define DEFAULT_FAIL_REASON "asynchronous monitor error"
 #define ASYNC_OP_NAME "asyncmon"
 
+/* in addition to HA_OK and HA_FAIL */
+#define	HA_RSCBUSY		2
+
 struct rsc_ops
 {
 /*
diff --git a/include/lrm/lrm_msg.h b/include/lrm/lrm_msg.h
index 5620565..6f671e1 100644
--- a/include/lrm/lrm_msg.h
+++ b/include/lrm/lrm_msg.h
@@ -67,6 +67,7 @@
 #define F_LRM_TARGETRC		"lrm_targetrc"
 #define F_LRM_LASTRC		"lrm_lastrc"
 #define F_LRM_STATUS		"lrm_status"
+#define F_LRM_RSCDELETED		"lrm_rscdeleted"
 #define F_LRM_METADATA		"lrm_metadata"
 #define F_LRM_USERDATA		"lrm_userdata"
 #define F_LRM_DELAY		"lrm_delay"
@@ -114,7 +115,6 @@
 #define MAX_PARAM_LEN 		1024
 
 
-							
 GHashTable* copy_str_table(GHashTable* hash_table);
 GHashTable* merge_str_tables(GHashTable* old, GHashTable* new);
 void free_str_table(GHashTable* hash_table);
diff --git a/include/stonith/stonith.h b/include/stonith/stonith.h
index 3c2f792..7dd58f8 100644
--- a/include/stonith/stonith.h
+++ b/include/stonith/stonith.h
@@ -123,6 +123,7 @@ void	stonith_free_hostlist	(char** hostlist);
 int	stonith_get_status	(Stonith* s);
 int	stonith_req_reset	(Stonith* s, int operation, const char* node);
 
+StonithNVpair* stonith_env_to_NVpair(Stonith* s);
 
 /* Stonith 1 compatibility:  Convert string to an NVpair set */
 StonithNVpair*
diff --git a/lib/clplumbing/Makefile.am b/lib/clplumbing/Makefile.am
index 5fb0a66..b2d71cb 100644
--- a/lib/clplumbing/Makefile.am
+++ b/lib/clplumbing/Makefile.am
@@ -63,7 +63,7 @@ libplumb_la_SOURCES	= 		\
 
 libplumb_la_LIBADD      = $(top_builddir)/replace/libreplace.la \
 			$(top_builddir)/lib/pils/libpils.la
-libplumb_la_LDFLAGS	= -version-info 2:0:0
+libplumb_la_LDFLAGS	= -version-info 3:0:1
 
 libplumbgpl_la_SOURCES	= setproctitle.c
 libplumbgpl_la_LIBADD   = $(top_builddir)/replace/libreplace.la \
diff --git a/lib/clplumbing/ipcsocket.c b/lib/clplumbing/ipcsocket.c
index 5f81b6c..3b9ac32 100644
--- a/lib/clplumbing/ipcsocket.c
+++ b/lib/clplumbing/ipcsocket.c
@@ -707,6 +707,7 @@ socket_accept_connection(struct IPC_WAIT_CONNECTION * wait_conn
 	/* Get client connection. */
 #if HB_IPC_METHOD == HB_IPC_SOCKET
 	peer_addr = g_new(struct sockaddr_un, 1);
+	*peer_addr->sun_path = '\0';
 	sin_size = sizeof(struct sockaddr_un);
 	new_sock = accept(s, (struct sockaddr *)peer_addr, &sin_size);
 #elif HB_IPC_METHOD == HB_IPC_STREAM
@@ -868,7 +869,9 @@ socket_destroy_channel(struct IPC_CHANNEL * ch)
 		struct SOCKET_CH_PRIVATE *priv = (struct SOCKET_CH_PRIVATE *)
 			ch->ch_private;
 		if(priv->peer_addr != NULL) {
-			unlink(priv->peer_addr->sun_path);
+			if (*priv->peer_addr->sun_path) {
+				unlink(priv->peer_addr->sun_path);
+			}
 			g_free((void*)(priv->peer_addr));
 		}
 #endif
@@ -2204,6 +2207,8 @@ channel_new(int sockfd, int conntype, const char *path_name) {
   temp_ch->low_flow_mark = -1;
   temp_ch->conntype = conntype;
   temp_ch->refcount = 0;
+  temp_ch->farside_uid = -1;
+  temp_ch->farside_gid = -1;
 
   return temp_ch;
   
@@ -2341,14 +2346,20 @@ socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
 	}
 	if (auth_info == NULL
 	||	(auth_info->uid == NULL && auth_info->gid == NULL)) {
-		return IPC_OK;    /* no restriction for authentication */
+		ret = IPC_OK;    /* no restriction for authentication */
 	  }
 
 	/* Get the credential information for our peer */
 	conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;
 	if (getsockopt(conn_info->s, SOL_SOCKET, SO_PEERCRED, &cred, &n) != 0
 	||	(size_t)n != sizeof(cred)) {
-		return IPC_FAIL;
+		return ret;
+	}
+
+	ch->farside_uid = cred.uid;
+	ch->farside_gid = cred.gid;
+	if (ret == IPC_OK) {
+		return ret;
 	}
 #if 0
 	cl_log(LOG_DEBUG, "SO_PEERCRED returned [%d, (%ld:%ld)]"
@@ -2419,13 +2430,19 @@ socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
 
 	if (auth_info == NULL
 	||	(auth_info->uid == NULL && auth_info->gid == NULL)) {
-		return IPC_OK;    /* no restriction for authentication */
+		ret = IPC_OK;    /* no restriction for authentication */
 	}
 	conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;
 
 	if (getpeereid(conn_info->s, &euid, &egid) < 0) {
 		cl_perror("getpeereid() failure");
-		return IPC_FAIL;
+		return ret;
+	}
+
+	ch->farside_uid = euid;
+	ch->farside_gid = egid;
+	if (ret == IPC_OK) {
+		return ret;
 	}
 
 	/* Check credentials against authorization information */
@@ -2524,7 +2541,7 @@ socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
 #endif
 
   struct SOCKET_CH_PRIVATE *conn_info;
-  int ret = IPC_OK;
+  int ret = IPC_FAIL;
   char         buf;
   
   /* Compute size without padding */
@@ -2543,7 +2560,7 @@ socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
 
   if (auth_info == NULL
   ||	(auth_info->uid == NULL && auth_info->gid == NULL)) {
-    return IPC_OK;    /* no restriction for authentication */
+    ret = IPC_OK;    /* no restriction for authentication */
   }
   conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;
 
@@ -2566,12 +2583,19 @@ socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
       || cmsg->cmsg_len < CMSGSIZE
       || cmsg->cmsg_type != SCM_CREDS) {
       cl_perror("can't get credential information from peer");
-      return IPC_FAIL;
+      return ret;
     }
 
   /* Avoid alignment issues - just copy it! */
   memcpy(&cred, CMSG_DATA(cmsg), sizeof(cred));
 
+  ch->farside_uid = cred.crEuid;
+  ch->farside_gid = cred.crEgid;
+  if (ret == IPC_OK) {
+      return ret;
+  }
+
+  ret = IPC_OK;
 
   if (	auth_info->uid
   &&	g_hash_table_lookup(auth_info->uid, &(cred.crEuid)) == NULL) {
@@ -2618,7 +2642,7 @@ static int
 socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
 {
 	int len = 0;
-	int ret = IPC_OK;
+	int ret = IPC_FAIL;
 	struct stat stat_buf;
 	struct sockaddr_un *peer_addr = NULL;
 	struct SOCKET_CH_PRIVATE *ch_private = NULL;	
@@ -2636,26 +2660,36 @@ socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
 		
 	} else if (auth_info == NULL
 	    ||	(auth_info->uid == NULL && auth_info->gid == NULL)) {
-		return IPC_OK;    /* no restriction for authentication */
+		ret = IPC_OK;    /* no restriction for authentication */
+
+	}
 
-	} else if(ch_private == NULL) {
+	if(ch_private == NULL) {
 		cl_log(LOG_ERR, "No channel private data available");
-		return IPC_FAIL;
+		return ret;
 		
 	} else if(peer_addr == NULL) {	
 		cl_log(LOG_ERR, "No peer information available");
-		return IPC_FAIL;
+		return ret;
 	}
 	
 	len = SUN_LEN(peer_addr);
 
 	if(len < 1) {
 		cl_log(LOG_ERR, "No peer information available");
-		return IPC_FAIL;
+		return ret;
 	}
 	peer_addr->sun_path[len] = 0;
 	stat(peer_addr->sun_path, &stat_buf);
 
+	ch->farside_uid = stat_buf.st_uid;
+	ch->farside_gid = stat_buf.st_gid;
+	if (ret == IPC_OK) {
+		return ret;
+	}
+
+	ret = IPC_OK;
+
 	if ((auth_info->uid == NULL || g_hash_table_size(auth_info->uid) == 0)
 	    && auth_info->gid != NULL
 	    && g_hash_table_size(auth_info->gid) != 0) {
@@ -2704,6 +2738,9 @@ socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
 
 	conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;
 
+	ch->farside_uid = conn_info->farside_uid;
+	ch->farside_gid = conn_info->farside_gid;
+
 	if (auth_info == NULL
 	  || (auth_info->uid == NULL && auth_info->gid == NULL)) {
 		return IPC_OK;	/* no restriction for authentication */
@@ -2751,12 +2788,18 @@ socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
 
 	if (auth_info == NULL
 	  || (auth_info->uid == NULL && auth_info->gid == NULL)) {
-		return IPC_OK;	/* no restriction for authentication */
+		rc = IPC_OK;	/* no restriction for authentication */
 	}
 
 	if (getpeerucred(conn_info->s, &ucred) < 0) {
 		cl_perror("getpeereid() failure");
-		return IPC_FAIL;
+		return rc;
+	}
+
+	ch->farside_uid = ucred_geteuid(ucred);
+	ch->farside_gid = ucred_getegid(ucred);
+	if (rc == IPC_OK) {
+		return rc;
 	}
 
 	/* Check credentials against authorization information */
diff --git a/lib/clplumbing/ocf_ipc.c b/lib/clplumbing/ocf_ipc.c
index be71af8..679cdbb 100644
--- a/lib/clplumbing/ocf_ipc.c
+++ b/lib/clplumbing/ocf_ipc.c
@@ -62,6 +62,7 @@ struct IPC_WAIT_CONNECTION *
 ipc_wait_conn_constructor(const char * ch_type, GHashTable* ch_attrs)
 {
   if (strcmp(ch_type, "domain_socket") == 0
+  ||	strcmp(ch_type, IPC_UDS_CRED) == 0
   ||	strcmp(ch_type, IPC_ANYTYPE) == 0
   ||	strcmp(ch_type, IPC_DOMAIN_SOCKET) == 0) {
     return socket_wait_conn_new(ch_attrs);
@@ -73,6 +74,7 @@ struct IPC_CHANNEL *
 ipc_channel_constructor(const char * ch_type, GHashTable* ch_attrs)
 {
   if	(strcmp(ch_type, "domain_socket") == 0
+  ||	strcmp(ch_type, IPC_UDS_CRED) == 0
   ||	strcmp(ch_type, IPC_ANYTYPE) == 0
   ||	strcmp(ch_type, IPC_DOMAIN_SOCKET) == 0) {
 
diff --git a/lib/lrm/clientlib.c b/lib/lrm/clientlib.c
index f24469f..3b00883 100644
--- a/lib/lrm/clientlib.c
+++ b/lib/lrm/clientlib.c
@@ -884,6 +884,7 @@ static int
 lrm_delete_rsc (ll_lrm_t* lrm, const char* rsc_id)
 {
 	struct ha_msg* msg = NULL;
+	int rc;
 
 	/* check whether the rsc_id is available */
 	if (NULL == rsc_id || RID_LEN <= strlen(rsc_id))	{
@@ -911,12 +912,13 @@ lrm_delete_rsc (ll_lrm_t* lrm, const char* rsc_id)
 	}
 	ha_msg_del(msg);
 	/* check the response of the msg */
-	if (HA_OK != get_ret_from_ch(ch_cmd)) {
+	rc = get_ret_from_ch(ch_cmd);
+	if (rc != HA_OK && rc != HA_RSCBUSY) {
 		LOG_GOT_FAIL_RET(LOG_ERR, DELRSC);
 		return HA_FAIL;
 	}
 
-	return HA_OK;
+	return rc;
 }
 
 static IPC_Channel*
@@ -1098,7 +1100,7 @@ rsc_flush_ops (lrm_rsc_t* rsc)
 
 	rc = get_ret_from_ch(ch_cmd);
 
-	return rc>0?HA_OK:HA_FAIL;
+	return rc>0?rc:HA_FAIL;
 }
 static gint 
 compare_call_id(gconstpointer a, gconstpointer b)
@@ -1404,6 +1406,8 @@ msg_to_op(struct ha_msg* msg)
 	/* op->params */
 	op->params = ha_msg_value_str_table(msg, F_LRM_PARAM);
 
+	ha_msg_value_int(msg, F_LRM_RSCDELETED, &op->rsc_deleted);
+
 	return op;
 }
 
diff --git a/lib/plugins/stonith/external/ibmrsa b/lib/plugins/stonith/external/ibmrsa
index f7264a6..7408465 100644
--- a/lib/plugins/stonith/external/ibmrsa
+++ b/lib/plugins/stonith/external/ibmrsa
@@ -7,7 +7,7 @@
 # This STONITH module depends on IBMmpcli.
 #
 
-trap 'if [ -n "$outf" ]; then ha_log.sh err "`cat $outf`"; rm -f "$outf"; fi' 0
+trap 'rm -f "$outf"' 0
 outf=`mktemp` || {
 	ha_log.sh err 'mktemp failed'
 	exit 1
@@ -36,7 +36,7 @@ mpcli() {
 	cat
 	) | /opt/IBMmpcli/bin/MPCLI.sh | grep -w $goodstg >/dev/null 2>&1
 	rc=$?
-	grep -w $failstg $outf
+	grep -w $failstg $outf >/dev/null
 	if [ $rc -eq 0 -a $? -eq 1 ]; then
 		return 0
 	else
diff --git a/lib/plugins/stonith/external/rackpdu b/lib/plugins/stonith/external/rackpdu
index a512a23..03188b8 100644
--- a/lib/plugins/stonith/external/rackpdu
+++ b/lib/plugins/stonith/external/rackpdu
@@ -66,12 +66,16 @@ GetOutletNumber() {
 	fi
     else
 	# Get outlet number from device
-    
+ 
 	local outlet_num=1
-	local snmp_result=`snmpwalk -v1 -c $community $pduip $names_oid 2>&1`
+	local snmp_result
+	snmp_result=`snmpwalk -v1 -c $community $pduip $names_oid 2>&1`
+	if [ $? -ne 0 ]; then
+	    ha_log.sh err "snmpwalk $community $pduip $names_oid failed. Result: $snmp_result"
+	    return 0
+	fi
 
 	local names=`echo "$snmp_result" | cut -f2 -d'"' | tr ' ' '_' | tr '\012' ' '`
-
 	for name in $names; do
 	    if [ "$name" != "$nodename" ]; then
 		local outlet_num=`expr $outlet_num + 1`
@@ -95,14 +99,17 @@ SendCommand() {
     local outlet=$?
 
     if [ $outlet -gt 0 ]; then
-        local set_result=`snmpset -v1 -c $community $pduip $oid.$outlet i $command 2>&1`
-        local check_result=`echo "$set_result" | grep "Timeout"`	    
-
-        if [ ! -z "$check_result" ]; then
-    	    ha_log.sh err "Write SNMP value $oid.$outlet=$command. Result: $set_result"
-	fi
-	    
-	return 0
+        local set_result
+        set_result=`snmpset -v1 -c $community $pduip $oid.$outlet i $command 2>&1`
+        if [ $? -ne 0 ]; then
+            ha_log.sh err "Write SNMP to $pduip value $oid.$outlet=$command failed. Result: $set_result"
+            return 1
+        fi
+        if echo "$set_result" | grep -qs "Timeout"; then
+            ha_log.sh err "Write SNMP to $pduip value $oid.$outlet=$command timed out. Result: $set_result"
+            return 1
+        fi
+        return 0
     else
         return 1
     fi
@@ -115,12 +122,15 @@ innode=$2
 case $incommand in
 gethosts)
 	if [ "$hostlist" = "AUTO" ]; then
+	    local snmp_result
 	    snmp_result=`snmpwalk -v1 -c $community $pduip $names_oid 2>&1`
-	    snmp_check=`echo "$snmp_result" | grep "Timeout"`
-
-	    if [ ! -z "$snmp_check" ]; then
-		ha_log.sh err "Cannot read list of nodes from device. Result: $snmp_result"
-		exit 1
+        if [ $? -ne 0 ]; then
+            ha_log.sh err "snmpwalk $community $pduip $names_oid failed. Result: $snmp_result"
+            exit 1
+        fi
+        if echo "$snmp_result" | grep -qs "Timeout"; then
+            ha_log.sh err "snmpwalk $community $pduip $names_oid timed out. Result: $snmp_result"
+            exit 1
 	    else
 		hostlist=`echo "$snmp_result" | cut -f2 -d'"' | tr ' ' '_' | tr '\012' ' '`
 	    fi
@@ -187,7 +197,7 @@ getinfo-devdescr)
 	exit 0
 	;;
 getinfo-devurl)
-	echo "http://www.it-consultant.su/rackpdu"
+	echo "http://www.apcc.com/products/family/index.cfm?id=30"
 	exit 0
 	;;
 getinfo-xml)
diff --git a/lib/plugins/stonith/external/sbd b/lib/plugins/stonith/external/sbd
index 283b5f3..6b4eec1 100644
--- a/lib/plugins/stonith/external/sbd
+++ b/lib/plugins/stonith/external/sbd
@@ -9,11 +9,6 @@
 
 # Main code
 
-is_heartbeat() {
-    which cl_status 2>/dev/null &&
-		cl_status hbstatus >/dev/null 2>&1
-}
-
 case $1 in
 gethosts)
     echo `sbd -d $sbd_device list | cut -f2`
@@ -25,26 +20,9 @@ off|reset)
     ;;
 status)
     if ! sbd -d $sbd_device list >/dev/null 2>&1 ; then
-    	ha_log err "sbd could not list nodes from $sbd_device"
+    	ha_log.sh err "sbd could not list nodes from $sbd_device"
     	exit 1
     fi
-    nodes=$(
-    if is_heartbeat; then
-	crm_node -H -p
-    else
-	crm_node -p
-    fi)
-    if [ -z "$nodes" ]; then
-        # No active nodes; strange, but maybe not running pacemaker?
-	ha_log warn "no active nodes reported by the CRM"
-    	exit 0
-    fi
-    for N in $nodes ; do
-    	if ! sbd -d $sbd_device ping $N >/dev/null 2>&1 ; then
-	    ha_log err "node $N not accessible through $sbd_device"
-	    exit 1
-	fi
-    done
     exit 0
     ;;
 on)
diff --git a/lib/plugins/stonith/external/xen0 b/lib/plugins/stonith/external/xen0
index 97f4ec9..19e6867 100644
--- a/lib/plugins/stonith/external/xen0
+++ b/lib/plugins/stonith/external/xen0
@@ -38,7 +38,7 @@ CheckIfDead() {
 CheckHostList() {
     if [ "x" = "x$hostlist" ]
     then
-        ha_log err "hostlist isn't set"
+        ha_log.sh err "hostlist isn't set"
         exit 1
     fi
 }
@@ -46,7 +46,7 @@ CheckHostList() {
 CheckDom0() {
     if [ "x" = "x$dom0" ]
     then
-        ha_log err "dom0 isn't set"
+        ha_log.sh err "dom0 isn't set"
         exit 1
     fi
 }
@@ -66,7 +66,7 @@ $h
 
         if [ "x" = "x$node" ]
         then
-            ha_log err "Syntax error in host list"
+            ha_log.sh err "Syntax error in host list"
             exit 1
         fi
         
@@ -85,7 +85,7 @@ $h
                  kill_node=`$SSH_COMMAND $dom0 "grep ^[[:space:]]*name $cfg" | cut -f 2 -d '=' |  sed -e 's,",,g'`
                  if [ "x" = "x$kill_node" ]
                  then
-                     ha_log err "Couldn't find a node name to stop"
+                     ha_log.sh err "Couldn't find a node name to stop"
                      exit 1
                  fi
 
diff --git a/lib/stonith/ha_log.sh b/lib/stonith/ha_log.sh
index 2050930..0651712 100755
--- a/lib/stonith/ha_log.sh
+++ b/lib/stonith/ha_log.sh
@@ -23,7 +23,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 # 
 
-# Build version: @BUILD_VERSION@
+# Build version: @GLUE_BUILD_VERSION@
 
 PROG=`basename $0`
 
@@ -79,8 +79,9 @@ ha_log() {
 	fi
 
 	[ "x$HA_LOGD" = "xyes" ] &&
-		ha_logger -t "$HA_LOGTAG" "$msg" &&
-		return 0
+		cat<<EOF | ha_logger -t "$HA_LOGTAG" && return 0
+$msg
+EOF
 
 	if [ -n "$HA_LOGFACILITY" ]; then
 		logger -t "$HA_LOGTAG" -p $HA_LOGFACILITY.$loglevel "$msg"
diff --git a/lib/stonith/main.c b/lib/stonith/main.c
index 08ba408..5709ced 100644
--- a/lib/stonith/main.c
+++ b/lib/stonith/main.c
@@ -31,7 +31,7 @@
 #include <glib.h>
 #include <libxml/entities.h>
 
-#define	OPTIONS	"c:F:p:t:T:snSlLmvhd"
+#define	OPTIONS	"c:F:p:t:T:EsnSlLmvhVd"
 #define	EQUAL	'='
 
 extern char *	optarg;
@@ -61,6 +61,7 @@ static const char META_TEMPLATE[] =
 "</special>\n"
 "</resource-agent>\n";
 
+void version();
 void usage(const char * cmd, int exit_status, const char * devtype);
 void confhelp(const char * cmd, FILE* stream, const char * devtype);
 void print_stonith_meta(Stonith * stonith_obj, const char *rsc_type);
@@ -73,6 +74,13 @@ void print_stonith_meta(Stonith * stonith_obj, const char *rsc_type);
  */
 
 void
+version()
+{
+	printf("stonith: %s (%s)\n", GLUE_VERSION, GLUE_BUILD_VERSION);
+	exit(0);
+}
+
+void
 usage(const char * cmd, int exit_status, const char * devtype)
 {
 	FILE *stream;
@@ -100,6 +108,7 @@ usage(const char * cmd, int exit_status, const char * devtype)
 		"-t stonith-device-type "
 		"{-p stonith-device-parameters | "
 		"-F stonith-device-parameters-file | "
+		"-E | "
 		"name=value...} "
 		"[-c count] "
 		"-lS\n"
@@ -109,6 +118,7 @@ usage(const char * cmd, int exit_status, const char * devtype)
 		"-t stonith-device-type "
 		"{-p stonith-device-parameters | "
 		"-F stonith-device-parameters-file | "
+		"-E | "
 		"name=value...} "
 		"[-c count] "
 		"-T {reset|on|off} nodename\n"
@@ -283,6 +293,7 @@ main(int argc, char** argv)
 	int		listhosts = 0;
 	int		listtypes = 0;
 	int 		listparanames = 0;
+	int 		params_from_env = 0;
 
 	int		c;
 	int		errors = 0;
@@ -329,6 +340,9 @@ main(int argc, char** argv)
 		case 'F':	optfile = optarg;
 				break;
 
+		case 'E':	params_from_env = 1;
+				break;
+
 		case 'h':	help++;
 				break;
 
@@ -373,6 +387,9 @@ main(int argc, char** argv)
 		case 'v':	++verbose;
 				break;
 
+		case 'V':	version();
+				break;
+
 		default:	++errors;
 				break;
 		}
@@ -385,9 +402,10 @@ main(int argc, char** argv)
 		PILpisysSetDebugLevel(debug);
 		setenv("HA_debug","2",0);
 	}
-	if (optfile && parameters) {
+	if ((optfile && parameters) || (optfile && params_from_env)
+			|| (params_from_env && parameters)) {
 		fprintf(stderr
-		,	"Cannot include both -F and -p options\n");
+		,	"Please use just one of -F, -p, and -E options\n");
 		usage(cmdname, 1, NULL);
 	}
 
@@ -411,6 +429,12 @@ main(int argc, char** argv)
 			"style arguments\n");
 			usage(cmdname, 1, NULL);
 		}
+		if (params_from_env)  {
+			fprintf(stderr
+			,	"Cannot use both -E and name=value "
+			"style arguments\n");
+			usage(cmdname, 1, NULL);
+		}
 		if (nvcount >= MAXNVARG) {
 			fprintf(stderr
 			,	"Too many name=value style arguments\n");
@@ -468,7 +492,8 @@ main(int argc, char** argv)
 		stonith_set_debug(s, debug);
 	}
 
-	if (!listparanames && !metadata && optfile == NULL && parameters == NULL && nvcount == 0) {
+	if (!listparanames && !metadata && optfile == NULL &&
+			parameters == NULL && !params_from_env && nvcount == 0) {
 		const char**	names;
 		int		needs_parms = 1;
 
@@ -478,7 +503,7 @@ main(int argc, char** argv)
 
 		if (needs_parms) {
 			fprintf(stderr
-			,	"Must specify either -p option, -F option or "
+			,	"Must specify either -p option, -F option, -E option, or "
 			"name=value style arguments\n");
 			if (s != NULL) {
 				stonith_delete(s); 
@@ -524,6 +549,21 @@ main(int argc, char** argv)
 			stonith_delete(s); s=NULL;
 			exit(S_BADCONFIG);
 		}
+	}else if (params_from_env) {
+		/* Configure Stonith object from the environment */
+		StonithNVpair *		pairs;
+		if ((pairs = stonith_env_to_NVpair(s)) == NULL) {
+			fprintf(stderr
+			,	"Invalid config info for %s device.\n"
+			,	SwitchType);
+			stonith_delete(s); s=NULL;
+			exit(1);
+		}
+		if ((rc = stonith_set_config(s, pairs)) != S_OK) {
+			fprintf(stderr
+			,	"Invalid config info for %s device\n"
+			,	SwitchType);
+		}
 	}else if (parameters) {
 		/* Configure Stonith object from the -p argument */
 		StonithNVpair *		pairs;
@@ -537,7 +577,7 @@ main(int argc, char** argv)
 		}
 		if ((rc = stonith_set_config(s, pairs)) != S_OK) {
 			fprintf(stderr
-			,	"Invalid config info for %s device"
+			,	"Invalid config info for %s device\n"
 			,	SwitchType);
 		}
 	}else{
diff --git a/lib/stonith/sbd.c b/lib/stonith/sbd.c
index f8a4956..b0052b0 100644
--- a/lib/stonith/sbd.c
+++ b/lib/stonith/sbd.c
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <time.h>
 #include <clplumbing/cl_log.h>
 #include <clplumbing/coredumps.h>
 #include <clplumbing/realtime.h>
@@ -43,12 +44,14 @@ static char		sbd_version  = 0x02;
 
 /* Tunable defaults: */
 static unsigned long	timeout_watchdog 	= 5;
+static unsigned long	timeout_watchdog_warn 	= 3;
 static int		timeout_allocate 	= 2;
 static int		timeout_loop	    	= 1;
 static int		timeout_msgwait		= 10;
 
 static int	watchdog_use		= 0;
 static int	go_daemon		= 0;
+static int	debug			= 0;
 static const char *watchdogdev		= "/dev/watchdog";
 static char *	local_uname;
 
@@ -74,11 +77,14 @@ usage(void)
 "-W		Use watchdog (recommended) (watch only)\n"
 "-w <dev>	Specify watchdog device (optional) (watch only)\n"
 "-D		Run as background daemon (optional) (watch only)\n"
+"-v		Enable some verbose debug logging (optional)\n"
 "\n"
 "-1 <N>		Set watchdog timeout to N seconds (optional) (create only)\n"
 "-2 <N>		Set slot allocation timeout to N seconds (optional) (create only)\n"
 "-3 <N>		Set daemon loop timeout to N seconds (optional) (create only)\n"
 "-4 <N>		Set msgwait timeout to N seconds (optional) (create only)\n"
+"-5 <N>		Warn if loop latency exceeds threshold (optional) (watch only)\n"
+"			(default is 3, set to 0 to disable)\n"
 "Commands:\n"
 "create		initialize N slots on <dev> - OVERWRITES DEVICE!\n"
 "list		List all allocated slots on device, and messages.\n"
@@ -764,6 +770,7 @@ daemonize(void)
 	struct sector_mbox_s	*s_mbox = NULL;
 	int			mbox;
 	int			rc = 0;
+	time_t			t0, t1, latency;
 
 	mbox = slot_allocate(local_uname);
 	if (mbox < 0) {
@@ -784,6 +791,9 @@ daemonize(void)
 		watchdog_init();
 	
 	while (1) {
+		t0 = time(NULL);
+		sleep(timeout_loop);
+
 		if (mbox_read(mbox, s_mbox) < 0) {
 			cl_log(LOG_ERR, "mbox read failed.");
 			do_reset();
@@ -817,7 +827,19 @@ daemonize(void)
 			}
 		}
 		watchdog_tickle();
-		sleep(timeout_loop);
+
+		t1 = time(NULL);
+		latency = t1 - t0;
+
+		if (timeout_watchdog_warn 
+				&& (latency > timeout_watchdog_warn)) {
+			cl_log(LOG_WARNING, "Latency: %d exceeded threshold %d",
+				(int)latency, (int)timeout_watchdog_warn);
+		} else if (debug) {
+			cl_log(LOG_INFO, "Latency: %d",
+				(int)latency);
+		}
+
 	}
 
 out:
@@ -883,11 +905,14 @@ main(int argc, char** argv)
 	
 	get_uname();
 
-	while ((c = getopt (argc, argv, "DWhw:d:n:1:2:3:4:")) != -1) {
+	while ((c = getopt (argc, argv, "DWhvw:d:n:1:2:3:4:5:")) != -1) {
 		switch (c) {
 		case 'D':
 			go_daemon = 1;
 			break;
+		case 'v':
+			debug = 1;
+			break;
 		case 'W':
 			watchdog_use = 1;
 			break;
@@ -912,6 +937,9 @@ main(int argc, char** argv)
 		case '4':
 			timeout_msgwait = atoi(optarg);
 			break;
+		case '5':
+			timeout_watchdog_warn = atoi(optarg);
+			break;
 		case 'h':
 			usage();
 			return(0);
diff --git a/lib/stonith/stonith.c b/lib/stonith/stonith.c
index 6975f0f..eb88c78 100644
--- a/lib/stonith/stonith.c
+++ b/lib/stonith/stonith.c
@@ -517,6 +517,47 @@ freeandexit:
 	return NULL;
 }
 
+StonithNVpair*
+stonith_env_to_NVpair(Stonith* s)
+{
+	/* Read the config names values from the environment */
+	const char **	config_names;
+	int		n_names;
+	int		j;
+	StonithNVpair*	ret;
+
+	if ((config_names = stonith_get_confignames(s)) == NULL) {
+		return NULL;
+	}
+	for (n_names=0; config_names[n_names] != NULL; ++n_names) {
+		/* Just count */;
+	}
+	ret = (StonithNVpair*) (MALLOC((n_names+1)*sizeof(StonithNVpair)));
+	if (ret == NULL) {
+		return NULL;
+	}
+	memset(ret, 0, (n_names+1)*sizeof(StonithNVpair));
+	for (j=0; j < n_names; ++j) {
+		char *env_value;
+		if ((ret[j].s_name = STRDUP(config_names[j])) == NULL) {
+			goto freeandexit;
+		}
+		env_value = getenv(config_names[j]);
+		if (env_value) {
+			if ((ret[j].s_value = STRDUP(env_value)) == NULL) {
+				goto freeandexit;
+			}
+		} else {
+			ret[j].s_value = NULL;
+		}
+	}
+	ret[j].s_name = NULL;
+	return ret;
+freeandexit:
+	free_NVpair(ret); ret = NULL;
+	return NULL;
+}
+
 static int NVcur = -1;
 static int NVmax = -1;
 static gboolean NVerr = FALSE;
diff --git a/logd/ha_logger.c b/logd/ha_logger.c
index f0c5126..5e2f9ef 100644
--- a/logd/ha_logger.c
+++ b/logd/ha_logger.c
@@ -46,13 +46,14 @@ usage(void)
 	       "ha_logger [-t tag] [-D <ha-log/ha-debug>] [message]\n");
 	return;
 }
+#define BUFSIZE 1024
 int
 main(int argc, char** argv)
 {
 	int	priority; 
 	char*	entity = NULL;
 	int	c;
-	char	buf[1024];
+	char	buf[BUFSIZE];
 	const char* logtype = "ha-log";
 
 	
@@ -96,49 +97,24 @@ main(int argc, char** argv)
 	}	
 	
 	if (argc > 0){
-		
-		register char *p, *endp;
-		int len;
-		
-		for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) {
-			len = strlen(*argv);
-			if (p + len > endp && p > buf) {
+		register char *p;
+
+		for (p = *argv; *argv; argv++, p = *argv) {
+			while (strlen(p) > BUFSIZE-1) {
+				memcpy(buf, p, BUFSIZE-1);
+				*(buf+BUFSIZE-1) = '\0';
 				if (LogToDaemon(priority,buf,
-						strnlen(buf, 1024),FALSE) ==HA_OK){
-					continue;
-				}else{
+						BUFSIZE,FALSE) != HA_OK){
 					return EXIT_FAIL;
 				}
-				/* NOTREACHED */
-				/* p = buf; */
+				p += BUFSIZE-1;
 			}
-			if (len > sizeof(buf) - 1) {
-				if (LogToDaemon(priority,*argv,
-						strnlen(*argv, 1024),FALSE) ==HA_OK){
-					argv++;
-					continue;
-				}else{
-					return EXIT_FAIL;
-				}
-				
-			} else {
-				if (p != buf){
-					*p++ = ' ';
-				}
-				memcpy(p, *argv++, len);
-				*(p += len) = '\0';
-			}
-		}
-		if (p != buf) {
-			if (LogToDaemon(priority,buf,
-					strnlen(buf, 1024),FALSE) ==HA_OK){
-				return EXIT_OK;
-			}else{
+			if (LogToDaemon(priority,p,
+					strnlen(p, BUFSIZE),FALSE) != HA_OK){
 				return EXIT_FAIL;
 			}
 		}
-		
-
+		return EXIT_OK;
 	}else {
 		while (fgets(buf, sizeof(buf), stdin) != NULL) {
 			/* glibc is buggy and adds an additional newline,
diff --git a/lrm/admin/Makefile.am b/lrm/admin/Makefile.am
index c82f781..c503ccf 100644
--- a/lrm/admin/Makefile.am
+++ b/lrm/admin/Makefile.am
@@ -29,3 +29,11 @@ lrmadmin_SOURCES  	= 	lrmadmin.c
 lrmadmin_LDFLAGS 	= 	$(COMMONLIBS)
 lrmadmin_LDADD = $(top_builddir)/lib/$(LRM_DIR)/liblrm.la
 lrmadmin_DEPENDENCIES = $(top_builddir)/lib/$(LRM_DIR)/liblrm.la
+
+if BUILD_HELP
+man8_MANS =	$(sbin_PROGRAMS:%=%.8)
+%.8:	%
+	echo Creating $@
+	chmod a+x $<
+	help2man --output $@ --no-info --section 8 --name "Part of the Linux-HA project" $(top_builddir)/lrm/admin/$<
+endif
diff --git a/lrm/admin/lrmadmin.c b/lrm/admin/lrmadmin.c
index f9c354d..c2f4aff 100644
--- a/lrm/admin/lrmadmin.c
+++ b/lrm/admin/lrmadmin.c
@@ -47,7 +47,7 @@
 #include <clplumbing/GSource.h>
 #include <clplumbing/Gmain_timeout.h>
 
-static const char *optstring = "A:D:X:dE:F:dg:p:M:O:P:c:S:LI:CT:n:h";
+static const char *optstring = "A:D:X:dE:F:dg:p:M:O:P:c:S:LI:CT:n:hv";
 
 #ifdef HAVE_GETOPT_H
 static struct option long_options[] = {
@@ -68,6 +68,7 @@ static struct option long_options[] = {
 	{"set_lrmd_param",	1, NULL, 'p'},
 	{"get_lrmd_param",	1, NULL, 'g'},
 	{"help",		0, NULL, 'h'},
+	{"version",		0, NULL, 'v'},
 	{NULL,			0, NULL, 0}
 };
 #endif /* HAVE_GETOPT_H */
@@ -139,23 +140,24 @@ static int call_id = 0;
 static int TIMEOUT = -1; /* the unit is ms */
 
 static const char *simple_help_screen =
-"lrmadmin {-d|--deamon}\n"
-"         {-A|--add} <rscid> <raclass> <ratype> <provider|NULL> [<rsc_params_list>]\n"
-"         {-D|--delete} <rscid>\n"
-"         {-F|--flush} <rscid>\n"
-"         {-X|--fail} <rscid> [<fail_rc> [<fail_reason>]]\n"
-"         {-E|--execute} <rscid> <operator> <timeout> <interval> <target_rc|EVERYTIME|CHANGED> [<operator_parameters_list>]\n"
-"         {-S|--state} <rscid> [-n <fake_name>]\n"
-"         {-L|--listall}\n"
-"         {-I|--information} <rsc_id>\n"
-"         {-C|--raclass_supported}\n"
-"         {-T|--ratype_supported} <raclass>\n"
-"         {-O|--all metadata of this class} <raclass>\n"
-"         {-M|--metadata} <raclass> <ratype> <provider|NULL>\n"
-"         {-P|--provider} <raclass> <ratype>\n"
-"         {-p|--set_lrmd_param} <name> <value>\n"
-"         {-g|--get_lrmd_param} <name>\n"
-"         {-h|--help}\n";
+"lrmadmin -d,--deamon\n"
+"         -A,--add <rscid> <raclass> <ratype> <provider|NULL> [<rsc_params_list>]\n"
+"         -D,--delete <rscid>\n"
+"         -F,--flush <rscid>\n"
+"         -X,--fail <rscid> [<fail_rc> [<fail_reason>]]\n"
+"         -E,--execute <rscid> <operator> <timeout> <interval> <target_rc|EVERYTIME|CHANGED> [<operator_parameters_list>]\n"
+"         -S,--state <rscid> [-n <fake_name>]\n"
+"         -L,--listall\n"
+"         -I,--information <rsc_id>\n"
+"         -C,--raclass_supported\n"
+"         -T,--ratype_supported <raclass>\n"
+"         -O,--all metadata of this class <raclass>\n"
+"         -M,--metadata <raclass> <ratype> <provider|NULL>\n"
+"         -P,--provider <raclass> <ratype>\n"
+"         -p,--set_lrmd_param <name> <value>\n"
+"         -g,--get_lrmd_param <name>\n"
+"         -v,--version\n"
+"         -h,--help\n";
 
 #define OPTION_OBSCURE_CHECK \
 				if ( lrmadmin_cmd != NULL_OP ) { \
@@ -339,6 +341,9 @@ int main(int argc, char **argv)
 				}
 				break;
 
+			case 'v':
+			    printf("%s\n",GLUE_VERSION);
+			    return 0;
 			case 'h':
 				OPTION_OBSCURE_CHECK 
 				printf("%s",simple_help_screen);
diff --git a/lrm/lrmd/lrmd.c b/lrm/lrmd/lrmd.c
index 690933e..75bae81 100644
--- a/lrm/lrmd/lrmd.c
+++ b/lrm/lrmd/lrmd.c
@@ -87,8 +87,6 @@ struct msg_map
 #define NO_MSG 1
 #define send_msg_now(p) \
 	(p->reply_time==REPLY_NOW)
-/* magic number, must be different from other return codes! */
-#define POSTPONED 32
 
 struct msg_map msg_maps[] = {
 	{REGISTER,	REPLY_NOW,	on_msg_register},
@@ -267,16 +265,14 @@ lrmd_op_destroy(lrmd_op_t* op)
 		,	__FUNCTION__, op->exec_pid, small_op_info(op));	
 		return;
 	}
+	lrmd_debug2(LOG_DEBUG, "%s: free the %s with address %p"
+		  ,__FUNCTION__, op_info(op), op);
 	ha_msg_del(op->msg);
 	op->msg = NULL;
 	if( op->rsc_id ) {
 		free(op->rsc_id);
 		op->rsc_id = NULL;
 	}
-	if( op->app_name ) {
-		free(op->app_name);
-		op->app_name = NULL;
-	}
 	op->exec_pid = 0;
 	if ( op->rapop != NULL ) {
 		op->rapop->lrmd_op = NULL;
@@ -287,9 +283,6 @@ lrmd_op_destroy(lrmd_op_t* op)
 	if( op->repeat_timeout_tag ) {
 		Gmain_timeout_remove(op->repeat_timeout_tag);
 	}
-
-	lrmd_debug3(LOG_DEBUG, "%s: free the op whose address is %p"
-		  ,__FUNCTION__, op);
 	free(op);
 }
 
@@ -343,7 +336,6 @@ lrmd_op_copy(const lrmd_op_t* op)
 	ret->rapop = NULL;
 	ret->msg = ha_msg_copy(op->msg);
 	ret->rsc_id = strdup(op->rsc_id);
-	ret->app_name = strdup(op->app_name);
 	ret->rapop = NULL;
 	ret->first_line_ra_stdout[0] = EOS;
 	ret->repeat_timeout_tag = 0;
@@ -353,6 +345,8 @@ lrmd_op_copy(const lrmd_op_t* op)
  	ret->t_done = op->t_done;
  	ret->t_rcchange = op->t_rcchange;
 	ret->is_copy = TRUE;
+	ret->is_cancelled = FALSE;
+	ret->weight = op->weight;
 	return ret;
 }
 
@@ -427,11 +421,12 @@ lrmd_op_dump(const lrmd_op_t* op, const char * text)
 	ha_msg_value_int(op->msg, F_LRM_TARGETRC, &target_rc);
 	lrmd_debug(LOG_DEBUG
 	,	"%s: lrmd_op: %s status: %s, target_rc=%s, client pid %d call_id"
-	": %d, child pid: %d (%s) %s"
+	": %d, child pid: %d (%s) %s %s"
 	,	text,	op_info(op), op_status_to_str(op_status)
 	,	op_target_rc_to_str(target_rc)
 	,	op->client_id, op->call_id, op->exec_pid, pidstat
-	,	(op->is_copy ? "copy" : "original"));
+	,	(op->is_copy ? "copy" : "original")
+	,	(op->is_cancelled ? "cancelled" : ""));
 	lrmd_debug(LOG_DEBUG
 	,	"%s: lrmd_op2: rt_tag: %d, interval: %d, delay: %d"
 	,	text,  op->repeat_timeout_tag
@@ -1462,12 +1457,9 @@ static void
 remove_repeat_op_from_client(gpointer key, gpointer value, gpointer user_data)
 {
 	lrmd_rsc_t* rsc = (lrmd_rsc_t*)value;
-	char *app_name = (char *)user_data;
+	pid_t pid = GPOINTER_TO_UINT(user_data); /* pointer cast as int */
 
-	(void)flush_all(&(rsc->repeat_op_list),app_name);
-	if( flush_all(&(rsc->op_list),app_name) ) {
-		set_rsc_flushing_ops(rsc); /* resource busy */
-	}
+	(void)flush_all(&(rsc->repeat_op_list),pid);
 }
 
 /* Remove all direct pointer references to 'client' before destroying it */
@@ -1483,12 +1475,13 @@ unregister_client(lrmd_client_t* client)
 		,	client->app_name, client->pid);
 		return HA_FAIL;
 	}
-	/* Remove from clients */
-	g_hash_table_remove(clients, (gpointer)&client->pid);
 
 	/* Search all resources for repeating ops this client owns */
 	g_hash_table_foreach(resources
-	,	remove_repeat_op_from_client, client->app_name);
+	,	remove_repeat_op_from_client, GUINT_TO_POINTER(client->pid));
+
+	/* Remove from clients */
+	g_hash_table_remove(clients, (gpointer)&client->pid);
 
 	lrmd_debug(LOG_DEBUG, "%s: client %s [pid:%d] is unregistered"
 	, 	__FUNCTION__
@@ -1988,11 +1981,12 @@ on_msg_del_rsc(lrmd_client_t* client, struct ha_msg* msg)
 		return -1;
 	}
 	LRMAUDIT();
-	(void)flush_all(&(rsc->repeat_op_list),NULL);
-	if( flush_all(&(rsc->op_list),NULL) ) {
+	(void)flush_all(&(rsc->repeat_op_list),0);
+	if( flush_all(&(rsc->op_list),0) ) {
 		set_rsc_removal_pending(rsc);
+		lrmd_log(LOG_INFO, "resource %s busy, removal pending", rsc->id);
 		LRMAUDIT();
-		return HA_OK; /* resource is busy, delay removal */
+		return HA_RSCBUSY; /* resource is busy, removal delayed */
 	}
 	lrmd_rsc_destroy(rsc);
 	LRMAUDIT();
@@ -2181,7 +2175,7 @@ cancel_op(GList** listp,int cancel_op_id)
 			,"%s: %s cancelled"
 			, __FUNCTION__, op_info(op));
 			rc = flush_op(op);
-			if( rc != POSTPONED && rc != HA_FAIL ) {
+			if( rc != HA_RSCBUSY && rc != HA_FAIL ) {
 				notify_client(op); /* send notification now */
 				*listp = g_list_remove(*listp, op);
 				remove_op_history(op);
@@ -2221,20 +2215,23 @@ on_msg_cancel_op(lrmd_client_t* client, struct ha_msg* msg)
 
 	if( cancel_op(&(rsc->repeat_op_list), cancel_op_id) != HA_OK ) {
 		op_cancelled = cancel_op(&(rsc->op_list), cancel_op_id);
-		if(op_cancelled == POSTPONED) {
-			op_cancelled = HA_OK;
-		}
 	}
 	if( op_cancelled == HA_FAIL ) {
 		lrmd_log(LOG_INFO, "%s: no operation with id %d",
 			__FUNCTION__, cancel_op_id);
+	} else if( op_cancelled == HA_RSCBUSY ) {
+		lrmd_log(LOG_INFO, "%s: operation %d running, cancel pending",
+			__FUNCTION__, cancel_op_id);
+	} else {
+		lrmd_debug(LOG_DEBUG, "%s: operation %d cancelled",
+			__FUNCTION__, cancel_op_id);
 	}
 	LRMAUDIT();
 	return op_cancelled;
 }
 
 static gboolean
-flush_all(GList** listp, char *app_name)
+flush_all(GList** listp, int client_pid)
 {
 	GList* node = NULL;
 	lrmd_op_t* op = NULL;
@@ -2243,14 +2240,14 @@ flush_all(GList** listp, char *app_name)
 	node = g_list_first(*listp);
 	while( node ) {
 		op = (lrmd_op_t*)node->data;
-		if (app_name && strcmp(op->app_name,app_name)) {
+		if (client_pid && op->client_id != client_pid) {
 			node = g_list_next(node);
 			continue; /* not the client's operation */
 		}
-		if( flush_op(op) == POSTPONED ) {
+		if( flush_op(op) == HA_RSCBUSY ) {
 			rsc_busy = TRUE;
 			node = g_list_next(node);
-		} else if (!app_name || !strcmp(op->app_name,app_name)) {
+		} else if (!client_pid || op->client_id == client_pid) {
 			node = *listp = g_list_remove(*listp, op);
 			remove_op_history(op);
 			lrmd_op_destroy(op);
@@ -2287,6 +2284,9 @@ on_msg_flush_all(lrmd_client_t* client, struct ha_msg* msg)
 	(void)flush_all(&(rsc->repeat_op_list),0);
 	if( flush_all(&(rsc->op_list),0) ) {
 		set_rsc_flushing_ops(rsc); /* resource busy */
+		lrmd_log(LOG_INFO, "resource %s busy, all flush pending", rsc->id);
+		LRMAUDIT();
+		return HA_RSCBUSY;
 	}
 	LRMAUDIT();
 	return HA_OK;
@@ -2345,10 +2345,10 @@ on_msg_perform_op(lrmd_client_t* client, struct ha_msg* msg)
 	}
 	op->call_id = call_id;
 	op->client_id = client->pid;
-	op->app_name = strdup(client->app_name);
 	op->rsc_id = strdup(rsc->id);
 	op->interval = interval;
 	op->delay = delay;
+	op->weight = no_child_count(rsc) ? 0 : 1;
 
 	op->msg = ha_msg_copy(msg);
 
@@ -2573,6 +2573,9 @@ replace_last_op(lrmd_client_t* client, lrmd_rsc_t* rsc, lrmd_op_t* op)
 		return;
 	client_last_op = g_hash_table_lookup(rsc->last_op_table, client->app_name);
 	if (!client_last_op) {
+		lrmd_debug2(LOG_DEBUG
+		, "%s: new last op table for client %s"
+		, __FUNCTION__, client->app_name);
 		client_last_op = g_hash_table_new_full(	g_str_hash
 		, 	g_str_equal, free, NULL);
 		g_hash_table_insert(rsc->last_op_table
@@ -2588,14 +2591,20 @@ replace_last_op(lrmd_client_t* client, lrmd_rsc_t* rsc, lrmd_op_t* op)
 			, __FUNCTION__, __LINE__);
 	}
 	if (old_op) {
+		lrmd_debug2(LOG_DEBUG
+		, "%s: replace last op %s for client %s"
+		, __FUNCTION__, op_hash_key, client->app_name);
 		g_hash_table_replace(client_last_op,op_hash_key,(gpointer)new_op);
 		lrmd_op_destroy(old_op);
 	} else {
+		lrmd_debug2(LOG_DEBUG
+		, "%s: add last op %s for client %s"
+		, __FUNCTION__, op_hash_key, client->app_name);
 		g_hash_table_insert(client_last_op,op_hash_key,(gpointer)new_op);
 	}
 }
 
-static void
+static int
 record_op_completion(lrmd_rsc_t* rsc, lrmd_op_t* op)
 {
 	lrmd_client_t* client;
@@ -2608,21 +2617,21 @@ record_op_completion(lrmd_rsc_t* rsc, lrmd_op_t* op)
 	if (!(rsc->last_op_done = lrmd_op_copy(op))) {
 		lrmd_log(LOG_ERR, "%s:%d out of memory" 
 			, __FUNCTION__, __LINE__);
+		return 1;
 	}
 	rsc->last_op_done->repeat_timeout_tag = (guint)0;
 
-	client = lookup_client_by_name(op->app_name);
+	client = lookup_client(op->client_id);
 	if (!client) {
 		lrmd_log(LOG_INFO, "%s: cannot record %s: the client is gone"
 		,	__FUNCTION__, small_op_info(op)); 
 		LRMAUDIT();
-		return;
+		return 1;
 	}
 	/* insert (or replace) the new op in last_op_table for the client */
 	replace_last_op(client,rsc,op);
-	if (op->interval) /* copy op to the repeat list */
-		to_repeatlist(rsc,op);
 	LRMAUDIT();
+	return 0;
 }
 
 static void
@@ -2649,7 +2658,7 @@ to_repeatlist(lrmd_rsc_t* rsc, lrmd_op_t* op)
 static void 
 remove_op_history(lrmd_op_t* op)
 {
-	lrmd_client_t* client = lookup_client_by_name(op->app_name);
+	lrmd_client_t* client = lookup_client(op->client_id);
 	lrmd_rsc_t* rsc = NULL;
 	char *op_id, *last_op_id;
 	lrmd_op_t* old_op = NULL;
@@ -2659,10 +2668,14 @@ remove_op_history(lrmd_op_t* op)
 	if( !(rsc = lookup_rsc(op->rsc_id)) ) {
 		return;
 	}
+	lrmd_debug2(LOG_DEBUG, "%s: remove history of the op %s"
+		  ,__FUNCTION__, op_info(op));
 	mk_op_id(op,op_id);
 	if (rsc->last_op_done != NULL ) {
 		mk_op_id(rsc->last_op_done,last_op_id);
 		if( !strcmp(op_id,last_op_id) ) {
+			lrmd_debug2(LOG_DEBUG, "%s: remove history of the last op done %s"
+				  ,__FUNCTION__, op_info(rsc->last_op_done));
 			lrmd_op_destroy(rsc->last_op_done);
 			rsc->last_op_done = NULL;
 		}
@@ -2671,9 +2684,13 @@ remove_op_history(lrmd_op_t* op)
 	if( client &&
 		(client_last_op = g_hash_table_lookup(rsc->last_op_table
 			, 			client->app_name)) ) {
+		lrmd_debug2(LOG_DEBUG, "%s: found client %s in the last op table"
+			  ,__FUNCTION__, client->app_name);
 		old_op = g_hash_table_lookup(client_last_op, op_id);
 		if (old_op) {
 			g_hash_table_remove(client_last_op,	op_id);
+			lrmd_debug2(LOG_DEBUG, "%s: remove history of the client's last %s"
+				  ,__FUNCTION__, op_info(old_op));
 			lrmd_op_destroy(old_op);
 		}
 	}
@@ -2757,23 +2774,33 @@ on_op_done(lrmd_rsc_t* rsc, lrmd_op_t* op)
 	, 	"%s:%s is removed from op list"
 	,	__FUNCTION__, op_info(op));
 
-	if (op_status != LRM_OP_CANCELLED) {
-		record_op_completion(rsc,op); /*record the outcome of the op */
+	if (!op->is_cancelled) {
+		if( !record_op_completion(rsc,op) ) { /*record the outcome of the op */
+			if (op->interval) /* copy op to the repeat list */
+				to_repeatlist(rsc,op);
+		}
 	} else {
 		remove_op_history(op);
 	}
 
+	if (rsc_removal_pending(rsc)) {
+		if (HA_OK != ha_msg_add_int(op->msg,F_LRM_RSCDELETED,1)) {
+			LOG_FAILED_TO_ADD_FIELD(F_LRM_RSCDELETED);
+		}
+	}
 	if (op_status != LRM_OP_DONE
 		|| (op_rc == -1)
 		|| (op_rc == target_rc)
 		|| (target_rc == EVERYTIME)
 		|| ((target_rc == CHANGED) && rc_changed)
+		|| rsc_removal_pending(rsc)
 	) {
 		notify_client(op);
 	}
 	lrmd_op_destroy(op);
 	if( !rsc->op_list ) {
 		if( rsc_removal_pending(rsc) ) {
+			lrmd_log(LOG_INFO, "late removal of resource %s", rsc->id);
 			lrmd_rsc_destroy(rsc);
 			rc = -1; /* let the caller know that the rsc is gone */
 		} else {
@@ -2813,10 +2840,11 @@ flush_op(lrmd_op_t* op)
 		}
 		return HA_OK;
 	} else {
+		op->is_cancelled = TRUE; /* mark the op as cancelled */
 		lrmd_log(LOG_INFO, "%s: process for %s still "
 			"running, flush delayed"
 			,__FUNCTION__,small_op_info(op));
-		return POSTPONED;
+		return HA_RSCBUSY;
 	}
 }
 
@@ -2869,6 +2897,11 @@ perform_op(lrmd_rsc_t* rsc)
 	while (NULL != node) {
 		op = node->data;
 		if (-1 != op->exec_pid)	{
+			if (!g_list_next(node)) {
+				/* this is the only operation, no need to do
+				 * anything further */
+				break;
+			}
 			lrmd_log(LOG_INFO, "%s:%d: %s for rsc is already running."
 			, __FUNCTION__, __LINE__, op_info(op));
 			if( rsc->delay_timeout > 0 ) {
@@ -2886,11 +2919,11 @@ perform_op(lrmd_rsc_t* rsc)
 			}
 			break;
 		}
-		if (child_count >= max_child_count) {
+		if (op->weight && child_count >= max_child_count) {
 			if ((int)rsc->delay_timeout > 0) {
 				lrmd_log(LOG_INFO
-				,	"%s:%d: operations on resource %s already delayed"
-				, __FUNCTION__, __LINE__, lrm_str(rsc->id));
+				,	"%s:%d: max_child_count (%d) reached and operations on resource %s already delayed"
+				, __FUNCTION__, __LINE__, max_child_count, lrm_str(rsc->id));
 			} else {
 				lrmd_debug(LOG_NOTICE
 				, 	"max_child_count (%d) reached, postponing "
@@ -3060,7 +3093,7 @@ perform_ra_op(lrmd_op_t* op)
 			return HA_FAIL;
 
 		default:	/* Parent */
-			child_count++;
+			child_count += op->weight;
 			NewTrackedProc(pid, 1
 			,	debug_level ?
 				((op->interval && !is_logmsg_due(op)) ? PT_LOGNORMAL : PT_LOGVERBOSE) : PT_LOGNONE
@@ -3193,14 +3226,17 @@ on_ra_proc_finished(ProcTrack* p, int status, int signo, int exitcode
 	int op_status;
 
 	LRMAUDIT();
-	if (--child_count < 0) {
+
+	CHECK_ALLOCATED(p, "ProcTrack p", );
+	op = proctrack_data(p);
+
+	child_count -= op->weight;
+	if (child_count < 0) {
 		lrmd_log(LOG_ERR, "%s:%d: child count is less than zero: %d"
 			, __FUNCTION__, __LINE__, child_count);
 		child_count = 0;
 	}
 
-	CHECK_ALLOCATED(p, "ProcTrack p", );
-	op = proctrack_data(p);
 	lrmd_debug2(LOG_DEBUG, "on_ra_proc_finished: accessing the op whose "
 		  "address is %p", op);
 	CHECK_ALLOCATED(op, "op", );
@@ -3225,19 +3261,6 @@ on_ra_proc_finished(ProcTrack* p, int status, int signo, int exitcode
 		return;
 	}
 
-	if (HA_OK == ha_msg_value_int(op->msg, F_LRM_OPSTATUS, &op_status)
-	&& (op_status_t)op_status == LRM_OP_CANCELLED ) {
-		lrmd_debug(LOG_DEBUG, "on_ra_proc_finished: "
-			"%s cancelled.", op_info(op));
-		on_op_done(rsc,op);
-		reset_proctrack_data(p);
-		if (debug_level >= 2) {	
-			dump_data_for_debug();
-		}
-		LRMAUDIT();
-		return;
-	}
-
 	RAExec = g_hash_table_lookup(RAExecFuncs,rsc->class);
 	if (NULL == RAExec) {
 		lrmd_log(LOG_ERR,"on_ra_proc_finished: can not find RAExec for"
@@ -3501,7 +3524,7 @@ send_msg(struct ha_msg* msg, lrmd_client_t* client)
 void
 notify_client(lrmd_op_t* op)
 {
-	lrmd_client_t* client = lookup_client_by_name(op->app_name);
+	lrmd_client_t* client = lookup_client(op->client_id);
 
 	if (client) {
 		/* send the result to client */
diff --git a/lrm/lrmd/lrmd.h b/lrm/lrmd/lrmd.h
index cd43106..17cc6bf 100644
--- a/lrm/lrmd/lrmd.h
+++ b/lrm/lrmd/lrmd.h
@@ -168,6 +168,9 @@ typedef struct ra_pipe_op  ra_pipe_op_t;
 		(unsigned long)LOGMSG_INTERVAL)
 #define probe_str(op,op_type) \
 	((op && !op->interval && !strcmp(op_type,"monitor")) ? "probe" : op_type)
+/* exclude stonith class from child count */
+#define no_child_count(rsc) \
+	(strcmp((rsc)->class,"stonith") == 0)
 
 struct lrmd_rsc
 {
@@ -183,7 +186,6 @@ struct lrmd_rsc
 	GHashTable*	last_op_table;	/* Last operation of each type	*/
 	lrmd_op_t*	last_op_done;	/* The last finished op of the resource */
 	guint		delay_timeout;  /* The delay value of op_list execution */
-	GList*		requestors;	/* a list of client pids to send replies to */
 	int			state;  /* status of the resource */
 };
 
@@ -192,12 +194,13 @@ struct lrmd_op
 	char*			rsc_id;
 	gboolean		is_copy;
 	pid_t			client_id;
-	char*		app_name;
 	int			call_id;
 	int			exec_pid;
 	guint			repeat_timeout_tag;
 	int			interval;
 	int			delay;
+	gboolean		is_cancelled;
+	int			weight;
 	int			copyparams;
 	struct ha_msg*		msg;
 	ra_pipe_op_t *		rapop;
diff --git a/lrm/lrmd/lrmd_fdecl.h b/lrm/lrmd/lrmd_fdecl.h
index a4c8a4c..d7f9a7e 100644
--- a/lrm/lrmd/lrmd_fdecl.h
+++ b/lrm/lrmd/lrmd_fdecl.h
@@ -73,14 +73,14 @@ static gboolean free_str_op_pair(gpointer key
 static lrmd_op_t* lrmd_op_copy(const lrmd_op_t* op);
 static void send_last_op(gpointer key, gpointer value, gpointer user_data);
 static void replace_last_op(lrmd_client_t* client, lrmd_rsc_t* rsc, lrmd_op_t* op);
-static void record_op_completion(lrmd_rsc_t* rsc, lrmd_op_t* op);
+static int record_op_completion(lrmd_rsc_t* rsc, lrmd_op_t* op);
 static void to_repeatlist(lrmd_rsc_t* rsc, lrmd_op_t* op);
 static void remove_op_history(lrmd_op_t* op);
 static void hash_to_str(GHashTable * , GString *);
 static void hash_to_str_foreach(gpointer key, gpointer value, gpointer userdata);
 static void warning_on_active_rsc(gpointer key, gpointer value, gpointer user_data);
 static void check_queue_duration(lrmd_op_t* op);
-static gboolean flush_all(GList** listp, char *app_name);
+static gboolean flush_all(GList** listp, int client_pid);
 static gboolean cancel_op(GList** listp,int cancel_op_id);
 static int prepare_failmsg(struct ha_msg* msg,
 			int fail_rc, const char *fail_reason);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-ha/cluster-glue.git



More information about the Debian-HA-Commits mailing list