diff --git a/attrd/legacy.c b/attrd/legacy.c
index 98276b4404..40c2af68a6 100644
--- a/attrd/legacy.c
+++ b/attrd/legacy.c
@@ -1,893 +1,893 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  * 
  * This software 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
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc.h>
 #include <crm/common/ipcs.h>
 #include <crm/cluster/internal.h>
 #include <crm/common/mainloop.h>
 
 #include <crm/common/xml.h>
 
 #include <crm/attrd.h>
 
 #define OPTARGS	"hV"
 #if SUPPORT_HEARTBEAT
 ll_cluster_t *attrd_cluster_conn;
 #endif
 
 GMainLoop *mainloop = NULL;
 char *attrd_uname = NULL;
 char *attrd_uuid = NULL;
 gboolean need_shutdown = FALSE;
 
 GHashTable *attr_hash = NULL;
 cib_t *cib_conn = NULL;
 
 typedef struct attr_hash_entry_s {
     char *uuid;
     char *id;
     char *set;
     char *section;
 
     char *value;
     char *stored_value;
 
     int timeout;
     char *dampen;
     guint timer_id;
 
     char *user;
 
 } attr_hash_entry_t;
 
 void attrd_local_callback(xmlNode * msg);
 gboolean attrd_timer_callback(void *user_data);
 gboolean attrd_trigger_update(attr_hash_entry_t * hash_entry);
 void attrd_perform_update(attr_hash_entry_t * hash_entry);
 
 static void
 free_hash_entry(gpointer data)
 {
     attr_hash_entry_t *entry = data;
 
     if (entry == NULL) {
         return;
     }
     free(entry->id);
     free(entry->set);
     free(entry->dampen);
     free(entry->section);
     free(entry->uuid);
     free(entry->value);
     free(entry->stored_value);
     free(entry->user);
     free(entry);
 }
 
 static int32_t
 attrd_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 {
     crm_trace("Connection %p", c);
     if (need_shutdown) {
         crm_info("Ignoring new client [%d] during shutdown", crm_ipcs_client_pid(c));
         return -EPERM;
     }
 
     if (crm_client_new(c, uid, gid) == NULL) {
         return -EIO;
     }
     return 0;
 }
 
 static void
 attrd_ipc_created(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p", c);
 }
 
 /* Exit code means? */
 static int32_t
 attrd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
 {
     uint32_t id = 0;
     uint32_t flags = 0;
     crm_client_t *client = crm_client_get(c);
     xmlNode *msg = crm_ipcs_recv(client, data, size, &id, &flags);
 
     crm_ipcs_send_ack(client, id, flags, "ack", __FUNCTION__, __LINE__);
     if (msg == NULL) {
         crm_debug("No msg from %d (%p)", crm_ipcs_client_pid(c), c);
         return 0;
     }
 #if ENABLE_ACL
     determine_request_user(client->user, msg, F_ATTRD_USER);
 #endif
 
     crm_trace("Processing msg from %d (%p)", crm_ipcs_client_pid(c), c);
-    crm_log_xml_trace(msg, __PRETTY_FUNCTION__);
+    crm_log_xml_trace(msg, __FUNCTION__);
 
     attrd_local_callback(msg);
 
     free_xml(msg);
     return 0;
 }
 
 /* Error code means? */
 static int32_t
 attrd_ipc_closed(qb_ipcs_connection_t * c)
 {
     crm_client_t *client = crm_client_get(c);
 
     if (client == NULL) {
         return 0;
     }
 
     crm_trace("Connection %p", c);
     crm_client_destroy(client);
     return 0;
 }
 
 static void
 attrd_ipc_destroy(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p", c);
     attrd_ipc_closed(c);
 }
 
 struct qb_ipcs_service_handlers ipc_callbacks = {
     .connection_accept = attrd_ipc_accept,
     .connection_created = attrd_ipc_created,
     .msg_process = attrd_ipc_dispatch,
     .connection_closed = attrd_ipc_closed,
     .connection_destroyed = attrd_ipc_destroy
 };
 
 static void
 attrd_shutdown(int nsig)
 {
     need_shutdown = TRUE;
     crm_info("Exiting");
     if (mainloop != NULL && g_main_is_running(mainloop)) {
         g_main_quit(mainloop);
     } else {
         crm_exit(pcmk_ok);
     }
 }
 
 static void
 usage(const char *cmd, int exit_status)
 {
     FILE *stream;
 
     stream = exit_status ? stderr : stdout;
 
     fprintf(stream, "usage: %s [-srkh] [-c configure file]\n", cmd);
 /* 	fprintf(stream, "\t-d\tsets debug level\n"); */
 /* 	fprintf(stream, "\t-s\tgets daemon status\n"); */
 /* 	fprintf(stream, "\t-r\trestarts daemon\n"); */
 /* 	fprintf(stream, "\t-k\tstops daemon\n"); */
 /* 	fprintf(stream, "\t-h\thelp message\n"); */
     fflush(stream);
 
     crm_exit(exit_status);
 }
 
 static void
 stop_attrd_timer(attr_hash_entry_t * hash_entry)
 {
     if (hash_entry != NULL && hash_entry->timer_id != 0) {
         crm_trace("Stopping %s timer", hash_entry->id);
         g_source_remove(hash_entry->timer_id);
         hash_entry->timer_id = 0;
     }
 }
 
 static void
 log_hash_entry(int level, attr_hash_entry_t * entry, const char *text)
 {
     do_crm_log(level, "%s: Set: %s, Name: %s, Value: %s, Timeout: %s",
                text, entry->section, entry->id, entry->value, entry->dampen);
 }
 
 static attr_hash_entry_t *
 find_hash_entry(xmlNode * msg)
 {
     const char *value = NULL;
     const char *attr = crm_element_value(msg, F_ATTRD_ATTRIBUTE);
     attr_hash_entry_t *hash_entry = NULL;
 
     if (attr == NULL) {
         crm_info("Ignoring message with no attribute name");
         return NULL;
     }
 
     hash_entry = g_hash_table_lookup(attr_hash, attr);
 
     if (hash_entry == NULL) {
         /* create one and add it */
         crm_info("Creating hash entry for %s", attr);
         hash_entry = calloc(1, sizeof(attr_hash_entry_t));
         hash_entry->id = strdup(attr);
 
         g_hash_table_insert(attr_hash, hash_entry->id, hash_entry);
         hash_entry = g_hash_table_lookup(attr_hash, attr);
         CRM_CHECK(hash_entry != NULL, return NULL);
     }
 
     value = crm_element_value(msg, F_ATTRD_SET);
     if (value != NULL) {
         free(hash_entry->set);
         hash_entry->set = strdup(value);
         crm_debug("\t%s->set: %s", attr, value);
     }
 
     value = crm_element_value(msg, F_ATTRD_SECTION);
     if (value == NULL) {
         value = XML_CIB_TAG_STATUS;
     }
     free(hash_entry->section);
     hash_entry->section = strdup(value);
     crm_trace("\t%s->section: %s", attr, value);
 
     value = crm_element_value(msg, F_ATTRD_DAMPEN);
     if (value != NULL) {
         free(hash_entry->dampen);
         hash_entry->dampen = strdup(value);
 
         hash_entry->timeout = crm_get_msec(value);
         crm_trace("\t%s->timeout: %s", attr, value);
     }
 #if ENABLE_ACL
     free(hash_entry->user);
 
     value = crm_element_value(msg, F_ATTRD_USER);
     if (value != NULL) {
         hash_entry->user = strdup(value);
         crm_trace("\t%s->user: %s", attr, value);
     }
 #endif
 
     log_hash_entry(LOG_DEBUG_2, hash_entry, "Found (and updated) entry:");
     return hash_entry;
 }
 
 #if SUPPORT_HEARTBEAT
 static void
 attrd_ha_connection_destroy(gpointer user_data)
 {
     crm_trace("Invoked");
     if (need_shutdown) {
         /* we signed out, so this is expected */
         crm_info("Heartbeat disconnection complete");
         return;
     }
 
     crm_crit("Lost connection to heartbeat service!");
     if (mainloop != NULL && g_main_is_running(mainloop)) {
         g_main_quit(mainloop);
         return;
     }
     crm_exit(pcmk_ok);
 }
 
 static void
 attrd_ha_callback(HA_Message * msg, void *private_data)
 {
     attr_hash_entry_t *hash_entry = NULL;
     xmlNode *xml = convert_ha_message(NULL, msg, __FUNCTION__);
     const char *from = crm_element_value(xml, F_ORIG);
     const char *op = crm_element_value(xml, F_ATTRD_TASK);
     const char *host = crm_element_value(xml, F_ATTRD_HOST);
     const char *ignore = crm_element_value(xml, F_ATTRD_IGNORE_LOCALLY);
 
     if (host != NULL && safe_str_eq(host, attrd_uname)) {
         crm_info("Update relayed from %s", from);
         attrd_local_callback(xml);
 
     } else if (ignore == NULL || safe_str_neq(from, attrd_uname)) {
         crm_info("%s message from %s", op, from);
         hash_entry = find_hash_entry(xml);
         stop_attrd_timer(hash_entry);
         attrd_perform_update(hash_entry);
     }
     free_xml(xml);
 }
 
 #endif
 
 #if SUPPORT_COROSYNC
 static void
 attrd_cs_dispatch(cpg_handle_t handle,
                  const struct cpg_name *groupName,
                  uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
 {
     uint32_t kind = 0;
     xmlNode *xml = NULL;
     const char *from = NULL;
     char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from);
 
     if(data == NULL) {
         return;
     }
     if (kind == crm_class_cluster) {
         xml = string2xml(data);
         if (xml == NULL) {
             crm_err("Bad message received: '%.120s'", data);
         }
     }
 
     if (xml != NULL) {
         attr_hash_entry_t *hash_entry = NULL;
         const char *op = crm_element_value(xml, F_ATTRD_TASK);
         const char *host = crm_element_value(xml, F_ATTRD_HOST);
         const char *ignore = crm_element_value(xml, F_ATTRD_IGNORE_LOCALLY);
 
         /* crm_xml_add_int(xml, F_SEQ, wrapper->id); */
         crm_xml_add(xml, F_ORIG, from);
 
         if (host != NULL && safe_str_eq(host, attrd_uname)) {
             crm_notice("Update relayed from %s", from);
             attrd_local_callback(xml);
 
         } else if (ignore == NULL || safe_str_neq(from, attrd_uname)) {
             crm_trace("%s message from %s", op, from);
             hash_entry = find_hash_entry(xml);
             stop_attrd_timer(hash_entry);
             attrd_perform_update(hash_entry);
         }
 
         free_xml(xml);
     }
 
     free(data);
 }
 
 static void
 attrd_cs_destroy(gpointer unused)
 {
     if (need_shutdown) {
         /* we signed out, so this is expected */
         crm_info("Corosync disconnection complete");
         return;
     }
 
     crm_crit("Lost connection to Corosync service!");
     if (mainloop != NULL && g_main_is_running(mainloop)) {
         g_main_quit(mainloop);
         return;
     }
     crm_exit(EINVAL);
 }
 #endif
 
 static void
 attrd_cib_connection_destroy(gpointer user_data)
 {
     cib_t *conn = user_data;
 
     conn->cmds->signoff(conn);  /* Ensure IPC is cleaned up */
 
     if (need_shutdown) {
         crm_info("Connection to the CIB terminated...");
 
     } else {
         /* eventually this will trigger a reconnect, not a shutdown */
         crm_err("Connection to the CIB terminated...");
         crm_exit(ENOTCONN);
     }
 
     return;
 }
 
 static void
 update_for_hash_entry(gpointer key, gpointer value, gpointer user_data)
 {
     attr_hash_entry_t *entry = value;
 
     if (entry->value != NULL || entry->stored_value != NULL) {
         attrd_timer_callback(value);
     }
 }
 
 static void
 local_update_for_hash_entry(gpointer key, gpointer value, gpointer user_data)
 {
     attr_hash_entry_t *entry = value;
 
     if (entry->timer_id == 0) {
         crm_trace("Performing local-only update after replace for %s", entry->id);
         attrd_perform_update(entry);
         /* } else {
          *     just let the timer expire and attrd_timer_callback() will do the right thing
          */
     }
 }
 
 static void
 do_cib_replaced(const char *event, xmlNode * msg)
 {
     crm_info("Updating all attributes after %s event", event);
     g_hash_table_foreach(attr_hash, local_update_for_hash_entry, NULL);
 }
 
 static gboolean
 cib_connect(void *user_data)
 {
     static int attempts = 1;
     static int max_retry = 20;
     gboolean was_err = FALSE;
     static cib_t *local_conn = NULL;
 
     if (local_conn == NULL) {
         local_conn = cib_new();
     }
 
     if (was_err == FALSE) {
         int rc = -ENOTCONN;
 
         if (attempts < max_retry) {
             crm_debug("CIB signon attempt %d", attempts);
             rc = local_conn->cmds->signon(local_conn, T_ATTRD, cib_command);
         }
 
         if (rc != pcmk_ok && attempts > max_retry) {
             crm_err("Signon to CIB failed: %s", pcmk_strerror(rc));
             was_err = TRUE;
 
         } else if (rc != pcmk_ok) {
             attempts++;
             return TRUE;
         }
     }
 
     crm_info("Connected to the CIB after %d signon attempts", attempts);
 
     if (was_err == FALSE) {
         int rc = local_conn->cmds->set_connection_dnotify(local_conn, attrd_cib_connection_destroy);
 
         if (rc != pcmk_ok) {
             crm_err("Could not set dnotify callback");
             was_err = TRUE;
         }
     }
 
     if (was_err == FALSE) {
         if (pcmk_ok !=
             local_conn->cmds->add_notify_callback(local_conn, T_CIB_REPLACE_NOTIFY,
                                                   do_cib_replaced)) {
             crm_err("Could not set CIB notification callback");
             was_err = TRUE;
         }
     }
 
     if (was_err) {
         crm_err("Aborting startup");
         crm_exit(DAEMON_RESPAWN_STOP);
     }
 
     cib_conn = local_conn;
 
     crm_info("Sending full refresh now that we're connected to the cib");
     g_hash_table_foreach(attr_hash, local_update_for_hash_entry, NULL);
 
     return FALSE;
 }
 
 int
 main(int argc, char **argv)
 {
     int flag = 0;
     int argerr = 0;
     crm_cluster_t cluster;
     gboolean was_err = FALSE;
     qb_ipcs_connection_t *c = NULL;
     qb_ipcs_service_t *ipcs = NULL;
 
     crm_log_init(T_ATTRD, LOG_NOTICE, TRUE, FALSE, argc, argv, FALSE);
     mainloop_add_signal(SIGTERM, attrd_shutdown);
 
     while ((flag = getopt(argc, argv, OPTARGS)) != EOF) {
         switch (flag) {
             case 'V':
                 crm_bump_log_level(argc, argv);
                 break;
             case 'h':          /* Help message */
                 usage(T_ATTRD, EX_OK);
                 break;
             default:
                 ++argerr;
                 break;
         }
     }
 
     if (optind > argc) {
         ++argerr;
     }
 
     if (argerr) {
         usage(T_ATTRD, EX_USAGE);
     }
 
     attr_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_hash_entry);
 
     crm_info("Starting up");
 
     if (was_err == FALSE) {
 
 #if SUPPORT_COROSYNC
         if (is_openais_cluster()) {
             cluster.destroy = attrd_cs_destroy;
             cluster.cpg.cpg_deliver_fn = attrd_cs_dispatch;
             cluster.cpg.cpg_confchg_fn = pcmk_cpg_membership;
         }
 #endif
 
 #if SUPPORT_HEARTBEAT
         if (is_heartbeat_cluster()) {
             cluster.hb_conn = NULL;
             cluster.hb_dispatch = attrd_ha_callback;
             cluster.destroy = attrd_ha_connection_destroy;
         }
 #endif
 
         if (FALSE == crm_cluster_connect(&cluster)) {
             crm_err("HA Signon failed");
             was_err = TRUE;
         }
 
         attrd_uname = cluster.uname;
         attrd_uuid = cluster.uuid;
 #if SUPPORT_HEARTBEAT
         attrd_cluster_conn = cluster.hb_conn;
 #endif
     }
 
     crm_info("Cluster connection active");
 
     if (was_err == FALSE) {
         attrd_ipc_server_init(&ipcs, &ipc_callbacks);
     }
 
     crm_info("Accepting attribute updates");
 
     mainloop = g_main_new(FALSE);
 
     if (0 == g_timeout_add_full(G_PRIORITY_LOW + 1, 5000, cib_connect, NULL, NULL)) {
         crm_info("Adding timer failed");
         was_err = TRUE;
     }
 
     if (was_err) {
         crm_err("Aborting startup");
         return 100;
     }
 
     crm_notice("Starting mainloop...");
     g_main_run(mainloop);
     crm_notice("Exiting...");
 
 #if SUPPORT_HEARTBEAT
     if (is_heartbeat_cluster()) {
         attrd_cluster_conn->llc_ops->signoff(attrd_cluster_conn, TRUE);
         attrd_cluster_conn->llc_ops->delete(attrd_cluster_conn);
     }
 #endif
 
     c = qb_ipcs_connection_first_get(ipcs);
     while (c != NULL) {
         qb_ipcs_connection_t *last = c;
 
         c = qb_ipcs_connection_next_get(ipcs, last);
 
         /* There really shouldn't be anyone connected at this point */
         crm_notice("Disconnecting client %p, pid=%d...", last, crm_ipcs_client_pid(last));
         qb_ipcs_disconnect(last);
         qb_ipcs_connection_unref(last);
     }
 
     qb_ipcs_destroy(ipcs);
 
     if (cib_conn) {
         cib_conn->cmds->signoff(cib_conn);
         cib_delete(cib_conn);
     }
 
     g_hash_table_destroy(attr_hash);
     free(attrd_uuid);
 
     return crm_exit(pcmk_ok);
 }
 
 struct attrd_callback_s {
     char *attr;
     char *value;
 };
 
 static void
 attrd_cib_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
 {
     attr_hash_entry_t *hash_entry = NULL;
     struct attrd_callback_s *data = user_data;
 
     if (data->value == NULL && rc == -ENXIO) {
         rc = pcmk_ok;
 
     } else if (call_id < 0) {
         crm_warn("Update %s=%s failed: %s", data->attr, data->value, pcmk_strerror(call_id));
         goto cleanup;
     }
 
     switch (rc) {
         case pcmk_ok:
             crm_debug("Update %d for %s=%s passed", call_id, data->attr, data->value);
             hash_entry = g_hash_table_lookup(attr_hash, data->attr);
 
             if (hash_entry) {
                 free(hash_entry->stored_value);
                 hash_entry->stored_value = NULL;
                 if (data->value != NULL) {
                     hash_entry->stored_value = strdup(data->value);
                 }
             }
             break;
         case -pcmk_err_diff_failed:    /* When an attr changes while the CIB is syncing */
         case -ETIME:           /* When an attr changes while there is a DC election */
         case -ENXIO:           /* When an attr changes while the CIB is syncing a
                                  *   newer config from a node that just came up
                                  */
             crm_warn("Update %d for %s=%s failed: %s",
                      call_id, data->attr, data->value, pcmk_strerror(rc));
             break;
         default:
             crm_err("Update %d for %s=%s failed: %s",
                     call_id, data->attr, data->value, pcmk_strerror(rc));
     }
   cleanup:
     free(data->value);
     free(data->attr);
     free(data);
 }
 
 void
 attrd_perform_update(attr_hash_entry_t * hash_entry)
 {
     int rc = pcmk_ok;
     struct attrd_callback_s *data = NULL;
     const char *user_name = NULL;
 
     if (hash_entry == NULL) {
         return;
 
     } else if (cib_conn == NULL) {
         crm_info("Delaying operation %s=%s: cib not connected", hash_entry->id,
                  crm_str(hash_entry->value));
         return;
 
     }
 #if ENABLE_ACL
     if (hash_entry->user) {
         user_name = hash_entry->user;
         crm_trace("Performing request from user '%s'", hash_entry->user);
     }
 #endif
 
     if (hash_entry->value == NULL) {
         /* delete the attr */
         rc = delete_attr_delegate(cib_conn, cib_none, hash_entry->section, attrd_uuid, NULL,
                                   hash_entry->set, hash_entry->uuid, hash_entry->id, NULL, FALSE,
                                   user_name);
 
         if (rc >= 0 && hash_entry->stored_value) {
             crm_notice("Sent delete %d: node=%s, attr=%s, id=%s, set=%s, section=%s",
                        rc, attrd_uuid, hash_entry->id,
                        hash_entry->uuid ? hash_entry->uuid : "<n/a>", hash_entry->set,
                        hash_entry->section);
 
         } else if (rc < 0 && rc != -ENXIO) {
             crm_notice
                 ("Delete operation failed: node=%s, attr=%s, id=%s, set=%s, section=%s: %s (%d)",
                  attrd_uuid, hash_entry->id, hash_entry->uuid ? hash_entry->uuid : "<n/a>",
                  hash_entry->set, hash_entry->section, pcmk_strerror(rc), rc);
 
         } else {
             crm_trace("Sent delete %d: node=%s, attr=%s, id=%s, set=%s, section=%s",
                       rc, attrd_uuid, hash_entry->id,
                       hash_entry->uuid ? hash_entry->uuid : "<n/a>", hash_entry->set,
                       hash_entry->section);
         }
 
     } else {
         /* send update */
         rc = update_attr_delegate(cib_conn, cib_none, hash_entry->section,
                                   attrd_uuid, NULL, hash_entry->set, hash_entry->uuid,
                                   hash_entry->id, hash_entry->value, FALSE, user_name);
         if (rc < 0) {
             crm_notice("Sent update %s=%s failed: %s", hash_entry->id, hash_entry->value,
                        pcmk_strerror(rc));
         }
         if (safe_str_neq(hash_entry->value, hash_entry->stored_value) || rc < 0) {
             crm_notice("Sent update %d: %s=%s", rc, hash_entry->id, hash_entry->value);
         } else {
             crm_trace("Sent update %d: %s=%s", rc, hash_entry->id, hash_entry->value);
         }
     }
 
     data = calloc(1, sizeof(struct attrd_callback_s));
     data->attr = strdup(hash_entry->id);
     if (hash_entry->value != NULL) {
         data->value = strdup(hash_entry->value);
     }
     cib_conn->cmds->register_callback(cib_conn, rc, 120, FALSE, data, "attrd_cib_callback",
                                       attrd_cib_callback);
     return;
 }
 
 void
 attrd_local_callback(xmlNode * msg)
 {
     static int plus_plus_len = 5;
     attr_hash_entry_t *hash_entry = NULL;
     const char *from = crm_element_value(msg, F_ORIG);
     const char *op = crm_element_value(msg, F_ATTRD_TASK);
     const char *attr = crm_element_value(msg, F_ATTRD_ATTRIBUTE);
     const char *value = crm_element_value(msg, F_ATTRD_VALUE);
     const char *host = crm_element_value(msg, F_ATTRD_HOST);
 
     if (safe_str_eq(op, "refresh")) {
         crm_notice("Sending full refresh (origin=%s)", from);
         g_hash_table_foreach(attr_hash, update_for_hash_entry, NULL);
         return;
     }
 
     if (host != NULL && safe_str_neq(host, attrd_uname)) {
         send_cluster_message(crm_get_peer(0, host), crm_msg_attrd, msg, FALSE);
         return;
     }
 
     crm_debug("%s message from %s: %s=%s", op, from, attr, crm_str(value));
     hash_entry = find_hash_entry(msg);
     if (hash_entry == NULL) {
         return;
     }
 
     if (hash_entry->uuid == NULL) {
         const char *key = crm_element_value(msg, F_ATTRD_KEY);
 
         if (key) {
             hash_entry->uuid = strdup(key);
         }
     }
 
     crm_debug("Supplied: %s, Current: %s, Stored: %s",
               value, hash_entry->value, hash_entry->stored_value);
 
     if (safe_str_eq(value, hash_entry->value)
         && safe_str_eq(value, hash_entry->stored_value)) {
         crm_trace("Ignoring non-change");
         return;
 
     } else if (value) {
         int offset = 1;
         int int_value = 0;
         int value_len = strlen(value);
 
         if (value_len < (plus_plus_len + 2)
             || value[plus_plus_len] != '+'
             || (value[plus_plus_len + 1] != '+' && value[plus_plus_len + 1] != '=')) {
             goto set_unexpanded;
         }
 
         int_value = char2score(hash_entry->value);
         if (value[plus_plus_len + 1] != '+') {
             const char *offset_s = value + (plus_plus_len + 2);
 
             offset = char2score(offset_s);
         }
         int_value += offset;
 
         if (int_value > INFINITY) {
             int_value = INFINITY;
         }
 
         crm_info("Expanded %s=%s to %d", attr, value, int_value);
         crm_xml_add_int(msg, F_ATTRD_VALUE, int_value);
         value = crm_element_value(msg, F_ATTRD_VALUE);
     }
 
   set_unexpanded:
     if (safe_str_eq(value, hash_entry->value) && hash_entry->timer_id) {
         /* We're already waiting to set this value */
         return;
     }
 
     free(hash_entry->value);
     hash_entry->value = NULL;
     if (value != NULL) {
         hash_entry->value = strdup(value);
         crm_debug("New value of %s is %s", attr, value);
     }
 
     stop_attrd_timer(hash_entry);
 
     if (hash_entry->timeout > 0) {
         hash_entry->timer_id = g_timeout_add(hash_entry->timeout, attrd_timer_callback, hash_entry);
     } else {
         attrd_trigger_update(hash_entry);
     }
 
     return;
 }
 
 gboolean
 attrd_timer_callback(void *user_data)
 {
     stop_attrd_timer(user_data);
     attrd_trigger_update(user_data);
     return TRUE;                /* Always return true, removed cleanly by stop_attrd_timer() */
 }
 
 gboolean
 attrd_trigger_update(attr_hash_entry_t * hash_entry)
 {
     xmlNode *msg = NULL;
 
     /* send HA message to everyone */
     crm_notice("Sending flush op to all hosts for: %s (%s)",
                hash_entry->id, crm_str(hash_entry->value));
     log_hash_entry(LOG_DEBUG_2, hash_entry, "Sending flush op to all hosts for:");
 
     msg = create_xml_node(NULL, __FUNCTION__);
     crm_xml_add(msg, F_TYPE, T_ATTRD);
     crm_xml_add(msg, F_ORIG, attrd_uname);
     crm_xml_add(msg, F_ATTRD_TASK, "flush");
     crm_xml_add(msg, F_ATTRD_ATTRIBUTE, hash_entry->id);
     crm_xml_add(msg, F_ATTRD_SET, hash_entry->set);
     crm_xml_add(msg, F_ATTRD_SECTION, hash_entry->section);
     crm_xml_add(msg, F_ATTRD_DAMPEN, hash_entry->dampen);
     crm_xml_add(msg, F_ATTRD_VALUE, hash_entry->value);
 #if ENABLE_ACL
     if (hash_entry->user) {
         crm_xml_add(msg, F_ATTRD_USER, hash_entry->user);
     }
 #endif
 
     if (hash_entry->timeout <= 0) {
         crm_xml_add(msg, F_ATTRD_IGNORE_LOCALLY, hash_entry->value);
         attrd_perform_update(hash_entry);
     }
 
     send_cluster_message(NULL, crm_msg_attrd, msg, FALSE);
     free_xml(msg);
 
     return TRUE;
 }
diff --git a/attrd/main.c b/attrd/main.c
index 771618b770..c12866344d 100644
--- a/attrd/main.c
+++ b/attrd/main.c
@@ -1,361 +1,361 @@
 /*
  * Copyright (C) 2013 Andrew Beekhof <andrew@beekhof.net>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This software 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
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc.h>
 #include <crm/common/ipcs.h>
 #include <crm/cluster/internal.h>
 #include <crm/cluster/election.h>
 #include <crm/common/mainloop.h>
 
 #include <crm/common/xml.h>
 
 #include <crm/attrd.h>
 #include <internal.h>
 
 cib_t *the_cib = NULL;
 GMainLoop *mloop = NULL;
 bool shutting_down = FALSE;
 crm_cluster_t *attrd_cluster = NULL;
 election_t *writer = NULL;
 int attrd_error = pcmk_ok;
 
 static void
 attrd_shutdown(int nsig) {
     shutting_down = TRUE;
     crm_info("Shutting down");
 
     if (mloop != NULL && g_main_is_running(mloop)) {
         g_main_quit(mloop);
     } else {
         crm_exit(pcmk_ok);
     }
 }
 
 static void
 attrd_cpg_dispatch(cpg_handle_t handle,
                  const struct cpg_name *groupName,
                  uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
 {
     uint32_t kind = 0;
     xmlNode *xml = NULL;
     const char *from = NULL;
     char *data = pcmk_message_common_cs(handle, nodeid, pid, msg, &kind, &from);
 
     if(data == NULL) {
         return;
     }
 
     if (kind == crm_class_cluster) {
         xml = string2xml(data);
     }
 
     if (xml == NULL) {
         crm_err("Bad message of class %d received from %s[%u]: '%.120s'", kind, from, nodeid, data);
     } else {
         crm_node_t *peer = crm_get_peer(nodeid, from);
 
         attrd_peer_message(peer, xml);
     }
 
     free_xml(xml);
     free(data);
 }
 
 static void
 attrd_cpg_destroy(gpointer unused)
 {
     if (shutting_down) {
         crm_info("Corosync disconnection complete");
 
     } else {
         crm_crit("Lost connection to Corosync service!");
         attrd_error = ECONNRESET;
         attrd_shutdown(0);
     }
 }
 
 static void
 attrd_cib_replaced_cb(const char *event, xmlNode * msg)
 {
     crm_notice("Updating all attributes after %s event", event);
     if(election_state(writer) == election_won) {
         write_attributes(TRUE, FALSE);
     }
 }
 
 static void
 attrd_cib_destroy_cb(gpointer user_data)
 {
     cib_t *conn = user_data;
 
     conn->cmds->signoff(conn);  /* Ensure IPC is cleaned up */
 
     if (shutting_down) {
         crm_info("Connection disconnection complete");
 
     } else {
         /* eventually this should trigger a reconnect, not a shutdown */
         crm_err("Lost connection to CIB service!");
         attrd_error = ECONNRESET;
         attrd_shutdown(0);
     }
 
     return;
 }
 
 static cib_t *
 attrd_cib_connect(int max_retry)
 {
     int rc = -ENOTCONN;
     static int attempts = 0;
     cib_t *connection = cib_new();
 
     if(connection == NULL) {
         return NULL;
     }
 
     do {
         if(attempts > 0) {
             sleep(attempts);
         }
 
         attempts++;
         crm_debug("CIB signon attempt %d", attempts);
         rc = connection->cmds->signon(connection, T_ATTRD, cib_command);
 
     } while(rc != pcmk_ok && attempts < max_retry);
 
     if (rc != pcmk_ok) {
         crm_err("Signon to CIB failed: %s (%d)", pcmk_strerror(rc), rc);
         goto cleanup;
     }
 
     crm_info("Connected to the CIB after %d attempts", attempts);
 
     rc = connection->cmds->set_connection_dnotify(connection, attrd_cib_destroy_cb);
     if (rc != pcmk_ok) {
         crm_err("Could not set disconnection callback");
         goto cleanup;
     }
 
     rc = connection->cmds->add_notify_callback(connection, T_CIB_REPLACE_NOTIFY, attrd_cib_replaced_cb);
     if(rc != pcmk_ok) {
         crm_err("Could not set CIB notification callback");
         goto cleanup;
     }
 
     return connection;
 
   cleanup:
     connection->cmds->signoff(connection);
     cib_delete(connection);
     return NULL;
 }
 
 static int32_t
 attrd_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 {
     crm_trace("Connection %p", c);
     if (shutting_down) {
         crm_info("Ignoring new client [%d] during shutdown", crm_ipcs_client_pid(c));
         return -EPERM;
     }
 
     if (crm_client_new(c, uid, gid) == NULL) {
         return -EIO;
     }
     return 0;
 }
 
 static void
 attrd_ipc_created(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p", c);
 }
 
 static int32_t
 attrd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
 {
     uint32_t id = 0;
     uint32_t flags = 0;
     crm_client_t *client = crm_client_get(c);
     xmlNode *xml = crm_ipcs_recv(client, data, size, &id, &flags);
 
     crm_ipcs_send_ack(client, id, flags, "ack", __FUNCTION__, __LINE__);
     if (xml == NULL) {
         crm_debug("No msg from %d (%p)", crm_ipcs_client_pid(c), c);
         return 0;
     }
 #if ENABLE_ACL
     determine_request_user(client->user, xml, F_ATTRD_USER);
 #endif
 
     crm_trace("Processing msg from %d (%p)", crm_ipcs_client_pid(c), c);
-    crm_log_xml_trace(xml, __PRETTY_FUNCTION__);
+    crm_log_xml_trace(xml, __FUNCTION__);
 
     attrd_client_message(client, xml);
 
     free_xml(xml);
     return 0;
 }
 
 /* Error code means? */
 static int32_t
 attrd_ipc_closed(qb_ipcs_connection_t * c)
 {
     crm_client_t *client = crm_client_get(c);
     if (client == NULL) {
         return 0;
     }
 
     crm_trace("Connection %p", c);
     crm_client_destroy(client);
     return 0;
 }
 
 static void
 attrd_ipc_destroy(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p", c);
     attrd_ipc_closed(c);
 }
 
 struct qb_ipcs_service_handlers ipc_callbacks = {
     .connection_accept = attrd_ipc_accept,
     .connection_created = attrd_ipc_created,
     .msg_process = attrd_ipc_dispatch,
     .connection_closed = attrd_ipc_closed,
     .connection_destroyed = attrd_ipc_destroy
 };
 
 /* *INDENT-OFF* */
 static struct crm_option long_options[] = {
     /* Top-level Options */
     {"help",    0, 0, '?', "\tThis text"},
     {"verbose", 0, 0, 'V', "\tIncrease debug output"},
 
     {0, 0, 0, 0}
 };
 /* *INDENT-ON* */
 
 int
 main(int argc, char **argv)
 {
     int rc = pcmk_ok;
     int flag = 0;
     int index = 0;
     int argerr = 0;
     qb_ipcs_service_t *ipcs = NULL;
 
     mloop = g_main_new(FALSE);
     crm_log_init(T_ATTRD, LOG_NOTICE, TRUE, FALSE, argc, argv, FALSE);
     crm_set_options(NULL, "[options]", long_options,
                     "Daemon for aggregating and atomically storing node attribute updates into the CIB");
 
     mainloop_add_signal(SIGTERM, attrd_shutdown);
 
      while (1) {
         flag = crm_get_option(argc, argv, &index);
         if (flag == -1)
             break;
 
         switch (flag) {
             case 'V':
                 crm_bump_log_level(argc, argv);
                 break;
             case 'h':          /* Help message */
                 crm_help(flag, EX_OK);
                 break;
             default:
                 ++argerr;
                 break;
         }
     }
 
     if (optind > argc) {
         ++argerr;
     }
 
     if (argerr) {
         crm_help('?', EX_USAGE);
     }
 
     crm_info("Starting up");
     attributes = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_attribute);
 
     attrd_cluster = malloc(sizeof(crm_cluster_t));
 
     attrd_cluster->destroy = attrd_cpg_destroy;
     attrd_cluster->cpg.cpg_deliver_fn = attrd_cpg_dispatch;
     attrd_cluster->cpg.cpg_confchg_fn = pcmk_cpg_membership;
 
     crm_set_status_callback(attrd_peer_change_cb);
 
     if (crm_cluster_connect(attrd_cluster) == FALSE) {
         crm_err("Cluster connection failed");
         rc = DAEMON_RESPAWN_STOP;
         goto done;
     }
     crm_info("Cluster connection active");
 
     writer = election_init(T_ATTRD, attrd_cluster->uname, 120000, attrd_election_cb);
     attrd_ipc_server_init(&ipcs, &ipc_callbacks);
     crm_info("Accepting attribute updates");
 
     the_cib = attrd_cib_connect(10);
     if (the_cib == NULL) {
         rc = DAEMON_RESPAWN_STOP;
         goto done;
     }
 
     crm_info("CIB connection active");
     g_main_run(mloop);
 
   done:
     crm_notice("Cleaning up before exit");
 
     election_fini(writer);
     crm_client_disconnect_all(ipcs);
     qb_ipcs_destroy(ipcs);
     g_hash_table_destroy(attributes);
 
     if (the_cib) {
         the_cib->cmds->signoff(the_cib);
         cib_delete(the_cib);
     }
 
     if(attrd_error) {
         return crm_exit(attrd_error);
     }
     return crm_exit(rc);
 }
diff --git a/fencing/test.c b/fencing/test.c
index 995d405d68..931a089c2f 100644
--- a/fencing/test.c
+++ b/fencing/test.c
@@ -1,662 +1,662 @@
 /* 
  * Copyright (C) 2009 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  * 
  * This software 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
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <sys/utsname.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc.h>
 #include <crm/cluster/internal.h>
 
 #include <crm/stonith-ng.h>
 #include <crm/fencing/internal.h>
 #include <crm/common/xml.h>
 
 #include <crm/common/mainloop.h>
 
 GMainLoop *mainloop = NULL;
 crm_trigger_t *trig = NULL;
 int mainloop_iter = 0;
 int callback_rc = 0;
 typedef void (*mainloop_test_iteration_cb) (int check_event);
 
 #define MAINLOOP_DEFAULT_TIMEOUT 2
 
 #define mainloop_test_done(pass) \
     if (pass) { \
-        crm_info("SUCCESS - %s", __PRETTY_FUNCTION__); \
+        crm_info("SUCCESS - %s", __FUNCTION__); \
         mainloop_iter++;   \
         mainloop_set_trigger(trig);  \
     } else { \
-        crm_err("FAILURE = %s async_callback %d", __PRETTY_FUNCTION__, callback_rc); \
+        crm_err("FAILURE = %s async_callback %d", __FUNCTION__, callback_rc); \
         crm_exit(pcmk_err_generic); \
     } \
     callback_rc = 0; \
 
 
 /* *INDENT-OFF* */
 enum test_modes {
     /* class dev test using a very specific environment */
     test_standard = 0,
     /* watch notifications only */
     test_passive,
     /* sanity test stonith client api using fence_dummy */
     test_api_sanity,
     /* sanity test mainloop code with async respones. */
     test_api_mainloop,
 };
 
 static struct crm_option long_options[] = {
     {"verbose",     0, 0, 'V'},
     {"version",     0, 0, '$'},
     {"help",        0, 0, '?'},
     {"passive",     0, 0, 'p'},
     {"api_test",    0, 0, 't'},
     {"mainloop_api_test",    0, 0, 'm'},
 
     {0, 0, 0, 0}
 };
 /* *INDENT-ON* */
 
 stonith_t *st = NULL;
 struct pollfd pollfd;
 int st_opts = st_opt_sync_call;
 int expected_notifications = 0;
 int verbose = 0;
 
 static void
 dispatch_helper(int timeout)
 {
     int rc;
 
     crm_debug("Looking for notification");
     pollfd.events = POLLIN;
     while (true) {
         rc = poll(&pollfd, 1, timeout); /* wait 10 minutes, -1 forever */
         if (rc > 0) {
             if (!stonith_dispatch(st)) {
                 break;
             }
         } else {
             break;
         }
     }
 }
 
 static void
 st_callback(stonith_t * st, stonith_event_t * e)
 {
     if (st->state == stonith_disconnected) {
         crm_exit(ENOTCONN);
     }
 
     crm_notice("Operation %s requested by %s %s for peer %s.  %s reported: %s (ref=%s)",
                e->operation, e->origin, e->result == pcmk_ok ? "completed" : "failed",
                e->target, e->executioner ? e->executioner : "<none>",
                pcmk_strerror(e->result), e->id);
 
     if (expected_notifications) {
         expected_notifications--;
     }
 }
 
 static void
 st_global_callback(stonith_t * stonith, stonith_callback_data_t * data)
 {
     crm_notice("Call id %d completed with rc %d", data->call_id, data->rc);
 }
 
 static void
 passive_test(void)
 {
     int rc = 0;
 
     rc = st->cmds->connect(st, crm_system_name, &pollfd.fd);
     crm_debug("Connect: %d", rc);
 
     st->cmds->register_notification(st, T_STONITH_NOTIFY_DISCONNECT, st_callback);
     st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, st_callback);
     st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback);
     st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback);
     st->cmds->register_callback(st, 0, 120, st_opt_timeout_updates, NULL, "st_global_callback",
                                 st_global_callback);
 
     dispatch_helper(600 * 1000);
 }
 
 #define single_test(cmd, str, num_notifications, expected_rc) \
 { \
     int rc = 0; \
     rc = cmd; \
     expected_notifications = 0;  \
     if (num_notifications) { \
         expected_notifications = num_notifications; \
         dispatch_helper(500);  \
     } \
     if (rc != expected_rc) { \
         crm_err("FAILURE - expected rc %d != %d(%s) for cmd - %s\n", expected_rc, rc, pcmk_strerror(rc), str); \
         crm_exit(pcmk_err_generic); \
     } else if (expected_notifications) { \
         crm_err("FAILURE - expected %d notifications, got only %d for cmd - %s\n", \
             num_notifications, num_notifications - expected_notifications, str); \
         crm_exit(pcmk_err_generic); \
     } else { \
         if (verbose) {                   \
             crm_info("SUCCESS - %s: %d", str, rc);    \
         } else {   \
             crm_debug("SUCCESS - %s: %d", str, rc);    \
         }                          \
     } \
 }\
 
 static void
 run_fence_failure_test(void)
 {
     stonith_key_value_t *params = NULL;
 
     params = stonith_key_value_add(params, "pcmk_host_map", "false_1_node1=1,2 false_1_node2=3,4");
     params = stonith_key_value_add(params, "mode", "fail");
 
     single_test(st->
                 cmds->register_device(st, st_opts, "test-id1", "stonith-ng", "fence_dummy", params),
                 "Register device1 for failure test", 1, 0);
 
     single_test(st->cmds->fence(st, st_opts, "false_1_node2", "off", 3, 0),
                 "Fence failure results off", 1, -201);
 
     single_test(st->cmds->fence(st, st_opts, "false_1_node2", "reboot", 3, 0),
                 "Fence failure results reboot", 1, -201);
 
     single_test(st->cmds->remove_device(st, st_opts, "test-id1"),
                 "Remove device1 for failure test", 1, 0);
 
     stonith_key_value_freeall(params, 1, 1);
 }
 
 static void
 run_fence_failure_rollover_test(void)
 {
     stonith_key_value_t *params = NULL;
 
     params = stonith_key_value_add(params, "pcmk_host_map", "false_1_node1=1,2 false_1_node2=3,4");
     params = stonith_key_value_add(params, "mode", "fail");
 
     single_test(st->
                 cmds->register_device(st, st_opts, "test-id1", "stonith-ng", "fence_dummy", params),
                 "Register device1 for rollover test", 1, 0);
     stonith_key_value_freeall(params, 1, 1);
     params = NULL;
     params = stonith_key_value_add(params, "pcmk_host_map", "false_1_node1=1,2 false_1_node2=3,4");
     params = stonith_key_value_add(params, "mode", "pass");
 
     single_test(st->
                 cmds->register_device(st, st_opts, "test-id2", "stonith-ng", "fence_dummy", params),
                 "Register device2 for rollover test", 1, 0);
 
     single_test(st->cmds->fence(st, st_opts, "false_1_node2", "off", 3, 0),
                 "Fence rollover results off", 1, 0);
 
     single_test(st->cmds->fence(st, st_opts, "false_1_node2", "on", 3, 0),
                 "Fence rollover results on", 1, 0);
 
     single_test(st->cmds->remove_device(st, st_opts, "test-id1"),
                 "Remove device1 for rollover tests", 1, 0);
 
     single_test(st->cmds->remove_device(st, st_opts, "test-id2"),
                 "Remove device2 for rollover tests", 1, 0);
 
     stonith_key_value_freeall(params, 1, 1);
 }
 
 static void
 run_standard_test(void)
 {
     stonith_key_value_t *params = NULL;
 
     params = stonith_key_value_add(params, "pcmk_host_map", "false_1_node1=1,2 false_1_node2=3,4");
     params = stonith_key_value_add(params, "mode", "pass");
 
     single_test(st->
                 cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_dummy", params),
                 "Register", 1, 0);
 
     single_test(st->cmds->list(st, st_opts, "test-id", NULL, 1), "list", 1, 0);
 
     single_test(st->cmds->monitor(st, st_opts, "test-id", 1), "Monitor", 1, 0);
 
     single_test(st->cmds->status(st, st_opts, "test-id", "false_1_node2", 1),
                 "Status false_1_node2", 1, 0);
 
     single_test(st->cmds->status(st, st_opts, "test-id", "false_1_node1", 1),
                 "Status false_1_node1", 1, 0);
 
     single_test(st->cmds->fence(st, st_opts, "unknown-host", "off", 1, 0),
                 "Fence unknown-host (expected failure)", 0, -19);
 
     single_test(st->cmds->fence(st, st_opts, "false_1_node1", "off", 1, 0),
                 "Fence false_1_node1", 1, 0);
 
     single_test(st->cmds->fence(st, st_opts, "false_1_node1", "on", 1, 0),
                 "Unfence false_1_node1", 1, 0);
 
     single_test(st->cmds->remove_device(st, st_opts, "test-id"), "Remove test-id", 1, 0);
 
     stonith_key_value_freeall(params, 1, 1);
 }
 
 static void
 sanity_tests(void)
 {
     int rc = 0;
 
     rc = st->cmds->connect(st, crm_system_name, &pollfd.fd);
     crm_debug("Connect: %d", rc);
 
     st->cmds->register_notification(st, T_STONITH_NOTIFY_DISCONNECT, st_callback);
     st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, st_callback);
     st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback);
     st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback);
     st->cmds->register_callback(st, 0, 120, st_opt_timeout_updates, NULL, "st_global_callback",
                                 st_global_callback);
 
     crm_info("Starting API Sanity Tests");
     run_standard_test();
     run_fence_failure_test();
     run_fence_failure_rollover_test();
     crm_info("Sanity Tests Passed");
 }
 
 static void
 standard_dev_test(void)
 {
     int rc = 0;
     char *tmp = NULL;
     stonith_key_value_t *params = NULL;
 
     rc = st->cmds->connect(st, crm_system_name, &pollfd.fd);
     crm_debug("Connect: %d", rc);
 
     params = stonith_key_value_add(params, "pcmk_host_map", "some-host=pcmk-7 true_1_node1=3,4");
 
     rc = st->cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_xvm", params);
     crm_debug("Register: %d", rc);
 
     rc = st->cmds->list(st, st_opts, "test-id", &tmp, 10);
     crm_debug("List: %d output: %s\n", rc, tmp ? tmp : "<none>");
 
     rc = st->cmds->monitor(st, st_opts, "test-id", 10);
     crm_debug("Monitor: %d", rc);
 
     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node2", 10);
     crm_debug("Status false_1_node2: %d", rc);
 
     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node1", 10);
     crm_debug("Status false_1_node1: %d", rc);
 
     rc = st->cmds->fence(st, st_opts, "unknown-host", "off", 60, 0);
     crm_debug("Fence unknown-host: %d", rc);
 
     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node1", 10);
     crm_debug("Status false_1_node1: %d", rc);
 
     rc = st->cmds->fence(st, st_opts, "false_1_node1", "off", 60, 0);
     crm_debug("Fence false_1_node1: %d", rc);
 
     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node1", 10);
     crm_debug("Status false_1_node1: %d", rc);
 
     rc = st->cmds->fence(st, st_opts, "false_1_node1", "on", 10, 0);
     crm_debug("Unfence false_1_node1: %d", rc);
 
     rc = st->cmds->status(st, st_opts, "test-id", "false_1_node1", 10);
     crm_debug("Status false_1_node1: %d", rc);
 
     rc = st->cmds->fence(st, st_opts, "some-host", "off", 10, 0);
     crm_debug("Fence alias: %d", rc);
 
     rc = st->cmds->status(st, st_opts, "test-id", "some-host", 10);
     crm_debug("Status alias: %d", rc);
 
     rc = st->cmds->fence(st, st_opts, "false_1_node1", "on", 10, 0);
     crm_debug("Unfence false_1_node1: %d", rc);
 
     rc = st->cmds->remove_device(st, st_opts, "test-id");
     crm_debug("Remove test-id: %d", rc);
 
     stonith_key_value_freeall(params, 1, 1);
 }
 
 static void
  iterate_mainloop_tests(gboolean event_ready);
 
 static void
 mainloop_callback(stonith_t * stonith, stonith_callback_data_t * data)
 {
     callback_rc = data->rc;
     iterate_mainloop_tests(TRUE);
 }
 
 static int
 register_callback_helper(int callid)
 {
     return st->cmds->register_callback(st,
                                        callid,
                                        MAINLOOP_DEFAULT_TIMEOUT,
                                        st_opt_timeout_updates, NULL, "callback", mainloop_callback);
 }
 
 static void
 test_async_fence_pass(int check_event)
 {
     int rc = 0;
 
     if (check_event) {
         if (callback_rc != 0) {
             mainloop_test_done(FALSE);
         } else {
             mainloop_test_done(TRUE);
         }
         return;
     }
 
     rc = st->cmds->fence(st, 0, "true_1_node1", "off", MAINLOOP_DEFAULT_TIMEOUT, 0);
     if (rc < 0) {
         crm_err("fence failed with rc %d", rc);
         mainloop_test_done(FALSE);
     }
     register_callback_helper(rc);
     /* wait for event */
 }
 
 #define CUSTOM_TIMEOUT_ADDITION 10
 static void
 test_async_fence_custom_timeout(int check_event)
 {
     int rc = 0;
     static time_t begin = 0;
 
     if (check_event) {
         uint32_t diff = (time(NULL) - begin);
 
         if (callback_rc != -ETIME) {
             mainloop_test_done(FALSE);
         } else if (diff < CUSTOM_TIMEOUT_ADDITION + MAINLOOP_DEFAULT_TIMEOUT) {
             crm_err
                 ("Custom timeout test failed, callback expiration should be updated to %d, actual timeout was %d",
                  CUSTOM_TIMEOUT_ADDITION + MAINLOOP_DEFAULT_TIMEOUT, diff);
             mainloop_test_done(FALSE);
         } else {
             mainloop_test_done(TRUE);
         }
         return;
     }
     begin = time(NULL);
 
     rc = st->cmds->fence(st, 0, "custom_timeout_node1", "off", MAINLOOP_DEFAULT_TIMEOUT, 0);
     if (rc < 0) {
         crm_err("fence failed with rc %d", rc);
         mainloop_test_done(FALSE);
     }
     register_callback_helper(rc);
     /* wait for event */
 }
 
 static void
 test_async_fence_timeout(int check_event)
 {
     int rc = 0;
 
     if (check_event) {
         if (callback_rc != -ENODEV) {
             mainloop_test_done(FALSE);
         } else {
             mainloop_test_done(TRUE);
         }
         return;
     }
 
     rc = st->cmds->fence(st, 0, "false_1_node2", "off", MAINLOOP_DEFAULT_TIMEOUT, 0);
     if (rc < 0) {
         crm_err("fence failed with rc %d", rc);
         mainloop_test_done(FALSE);
     }
     register_callback_helper(rc);
     /* wait for event */
 }
 
 static void
 test_async_monitor(int check_event)
 {
     int rc = 0;
 
     if (check_event) {
         if (callback_rc) {
             mainloop_test_done(FALSE);
         } else {
             mainloop_test_done(TRUE);
         }
         return;
     }
 
     rc = st->cmds->monitor(st, 0, "false_1", MAINLOOP_DEFAULT_TIMEOUT);
     if (rc < 0) {
         crm_err("monitor failed with rc %d", rc);
         mainloop_test_done(FALSE);
     }
 
     register_callback_helper(rc);
     /* wait for event */
 }
 
 static void
 test_register_async_devices(int check_event)
 {
     char buf[16] = { 0, };
     stonith_key_value_t *params = NULL;
 
     params = stonith_key_value_add(params, "pcmk_host_map", "false_1_node1=1,2");
     params = stonith_key_value_add(params, "mode", "fail");
     st->cmds->register_device(st, st_opts, "false_1", "stonith-ng", "fence_dummy", params);
     stonith_key_value_freeall(params, 1, 1);
 
     params = NULL;
     params = stonith_key_value_add(params, "pcmk_host_map", "true_1_node1=1,2");
     params = stonith_key_value_add(params, "mode", "pass");
     st->cmds->register_device(st, st_opts, "true_1", "stonith-ng", "fence_dummy", params);
     stonith_key_value_freeall(params, 1, 1);
 
     params = NULL;
     params = stonith_key_value_add(params, "pcmk_host_map", "custom_timeout_node1=1,2");
     params = stonith_key_value_add(params, "mode", "fail");
     params = stonith_key_value_add(params, "delay", "1000");
     snprintf(buf, sizeof(buf) - 1, "%d", MAINLOOP_DEFAULT_TIMEOUT + CUSTOM_TIMEOUT_ADDITION);
     params = stonith_key_value_add(params, "pcmk_off_timeout", buf);
     st->cmds->register_device(st, st_opts, "false_custom_timeout", "stonith-ng", "fence_dummy",
                               params);
     stonith_key_value_freeall(params, 1, 1);
 
     mainloop_test_done(TRUE);
 }
 
 static void
 try_mainloop_connect(int check_event)
 {
     int tries = 10;
     int i = 0;
     int rc = 0;
 
     for (i = 0; i < tries; i++) {
         rc = st->cmds->connect(st, crm_system_name, NULL);
 
         if (!rc) {
             crm_info("stonith client connection established");
             mainloop_test_done(TRUE);
             return;
         } else {
             crm_info("stonith client connection failed");
         }
         sleep(1);
     }
 
     crm_err("API CONNECTION FAILURE\n");
     mainloop_test_done(FALSE);
 }
 
 static void
 iterate_mainloop_tests(gboolean event_ready)
 {
     static mainloop_test_iteration_cb callbacks[] = {
         try_mainloop_connect,
         test_register_async_devices,
         test_async_monitor,
         test_async_fence_pass,
         test_async_fence_timeout,
         test_async_fence_custom_timeout,
     };
 
     if (mainloop_iter == (sizeof(callbacks) / sizeof(mainloop_test_iteration_cb))) {
         /* all tests ran, everything passed */
         crm_info("ALL MAINLOOP TESTS PASSED!");
         crm_exit(pcmk_ok);
     }
 
     callbacks[mainloop_iter] (event_ready);
 }
 
 static gboolean
 trigger_iterate_mainloop_tests(gpointer user_data)
 {
     iterate_mainloop_tests(FALSE);
     return TRUE;
 }
 
 static void
 test_shutdown(int nsig)
 {
     int rc = 0;
 
     if (st) {
         rc = st->cmds->disconnect(st);
         crm_info("Disconnect: %d", rc);
 
         crm_debug("Destroy");
         stonith_api_delete(st);
     }
 
     if (rc) {
         crm_exit(pcmk_err_generic);
     }
 }
 
 static void
 mainloop_tests(void)
 {
     trig = mainloop_add_trigger(G_PRIORITY_HIGH, trigger_iterate_mainloop_tests, NULL);
     mainloop_set_trigger(trig);
     mainloop_add_signal(SIGTERM, test_shutdown);
 
     crm_info("Starting");
     mainloop = g_main_new(FALSE);
     g_main_run(mainloop);
 }
 
 int
 main(int argc, char **argv)
 {
     int argerr = 0;
     int flag;
     int option_index = 0;
 
     enum test_modes mode = test_standard;
 
     crm_set_options(NULL, "mode [options]", long_options,
                     "Provides a summary of cluster's current state."
                     "\n\nOutputs varying levels of detail in a number of different formats.\n");
 
     while (1) {
         flag = crm_get_option(argc, argv, &option_index);
         if (flag == -1) {
             break;
         }
 
         switch (flag) {
             case 'V':
                 verbose = 1;
                 break;
             case '$':
             case '?':
                 crm_help(flag, EX_OK);
                 break;
             case 'p':
                 mode = test_passive;
                 break;
             case 't':
                 mode = test_api_sanity;
                 break;
             case 'm':
                 mode = test_api_mainloop;
                 break;
             default:
                 ++argerr;
                 break;
         }
     }
 
     crm_log_init("stonith-test", LOG_INFO, TRUE, verbose ? TRUE : FALSE, argc, argv, FALSE);
 
     if (optind > argc) {
         ++argerr;
     }
 
     if (argerr) {
         crm_help('?', EX_USAGE);
     }
 
     crm_debug("Create");
     st = stonith_api_new();
 
     switch (mode) {
         case test_standard:
             standard_dev_test();
             break;
         case test_passive:
             passive_test();
             break;
         case test_api_sanity:
             sanity_tests();
             break;
         case test_api_mainloop:
             mainloop_tests();
             break;
     }
 
     test_shutdown(0);
     return 0;
 }
diff --git a/include/crm/common/logging.h b/include/crm/common/logging.h
index a3f308a0f6..fc9824aa23 100644
--- a/include/crm/common/logging.h
+++ b/include/crm/common/logging.h
@@ -1,196 +1,196 @@
 /*
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This software 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
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 /**
  * \file
  * \brief Wrappers for and extensions to libqb logging
  * \ingroup core
  */
 
 #ifndef CRM_LOGGING__H
 #  define CRM_LOGGING__H
 #  include <qb/qblog.h>
 #  ifndef LOG_TRACE
 #    define LOG_TRACE    LOG_DEBUG+1
 #  endif
 #  define LOG_DEBUG_2  LOG_TRACE
 #  define LOG_DEBUG_3  LOG_TRACE
 #  define LOG_DEBUG_4  LOG_TRACE
 #  define LOG_DEBUG_5  LOG_TRACE
 #  define LOG_DEBUG_6  LOG_TRACE
 
 extern unsigned int crm_log_level;
 extern gboolean crm_config_error;
 extern gboolean crm_config_warning;
 extern unsigned int crm_trace_nonlog;
 
 enum xml_log_options
 {
     xml_log_option_filtered   = 0x001,
     xml_log_option_formatted  = 0x002,
     xml_log_option_diff_plus  = 0x010,
     xml_log_option_diff_minus = 0x020,
     xml_log_option_diff_short = 0x040,
     xml_log_option_diff_all   = 0x100,
 };
 
 void crm_enable_blackbox(int nsig);
 void crm_disable_blackbox(int nsig);
 void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite);
 
 void crm_update_callsites(void);
 
 void crm_log_deinit(void);
 
 gboolean crm_log_cli_init(const char *entity);
 
 gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon,
                       gboolean to_stderr, int argc, char **argv, gboolean quiet);
 
 void crm_log_args(int argc, char **argv);
 void crm_log_output_fn(const char *file, const char *function, int line, int level,
                        const char *prefix, const char *output);
 #  define crm_log_output(level, prefix, output) crm_log_output_fn(__FILE__, __FUNCTION__, __LINE__, level, prefix, output)
 
 gboolean crm_add_logfile(const char *filename);
 
 void crm_bump_log_level(int argc, char **argv);
 
 void crm_enable_stderr(int enable);
 
 gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags);
 
 void log_data_element(int log_level, const char *file, const char *function, int line,
                       const char *prefix, xmlNode * data, int depth, gboolean formatted);
 
 /* returns the old value */
 unsigned int set_crm_log_level(unsigned int level);
 
 unsigned int get_crm_log_level(void);
 
 /*
  * Throughout the macros below, note the leading, pre-comma, space in the
  * various ' , ##args' occurences to aid portability across versions of 'gcc'.
  *	http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html#Variadic-Macros
  */
 #if defined(__clang__)
 #    define CRM_TRACE_INIT_DATA(name)
 #  else
 #    define CRM_TRACE_INIT_DATA(name) QB_LOG_INIT_DATA(name)
 #endif
 
 #  define do_crm_log(level, fmt, args...) qb_log_from_external_source( __func__, __FILE__, fmt, level, __LINE__, 0, ##args)
 
 /* level /MUST/ be a constant or compilation will fail */
 #  define do_crm_log_unlikely(level, fmt, args...) do {               \
         static struct qb_log_callsite *trace_cs = NULL;                 \
         if(trace_cs == NULL) {                                          \
             trace_cs = qb_log_callsite_get(__func__, __FILE__, fmt, level, __LINE__, 0); \
         }                                                               \
         if (crm_is_callsite_active(trace_cs, level, 0)) {            \
             qb_log_from_external_source(                                \
                 __func__, __FILE__, fmt, level, __LINE__, 0,  ##args);  \
         }                                                               \
     } while(0)
 
 #  define CRM_LOG_ASSERT(expr) do {					\
         if(__unlikely((expr) == FALSE)) {				\
             static struct qb_log_callsite *core_cs = NULL;              \
             if(core_cs == NULL) {                                       \
                 core_cs = qb_log_callsite_get(__func__, __FILE__, "log-assert", LOG_TRACE, __LINE__, 0); \
             }                                                           \
-            crm_abort(__FILE__, __PRETTY_FUNCTION__, __LINE__, #expr,   \
+            crm_abort(__FILE__, __FUNCTION__, __LINE__, #expr,   \
                       core_cs?core_cs->targets:FALSE, TRUE);            \
         }                                                               \
     } while(0)
 
 #  define CRM_CHECK(expr, failure_action) do {				\
 	if(__unlikely((expr) == FALSE)) {				\
             static struct qb_log_callsite *core_cs = NULL;              \
             if(core_cs == NULL) {                                       \
                 core_cs = qb_log_callsite_get(__func__, __FILE__, "check-assert", LOG_TRACE, __LINE__, 0); \
             }                                                           \
-	    crm_abort(__FILE__, __PRETTY_FUNCTION__, __LINE__, #expr,	\
+	    crm_abort(__FILE__, __FUNCTION__, __LINE__, #expr,	\
 		      core_cs?core_cs->targets:FALSE, TRUE);            \
 	    failure_action;						\
 	}								\
     } while(0)
 
 #  define do_crm_log_xml(level, text, xml) do {                       \
         static struct qb_log_callsite *xml_cs = NULL;                   \
         if(xml_cs == NULL) {                                            \
             xml_cs = qb_log_callsite_get(__func__, __FILE__, "xml-blob", level, __LINE__, 0); \
         }                                                               \
         if (crm_is_callsite_active(xml_cs, level, 0)) {                  \
-            log_data_element(level, __FILE__, __PRETTY_FUNCTION__, __LINE__, text, xml, 1, xml_log_option_formatted); \
+            log_data_element(level, __FILE__, __FUNCTION__, __LINE__, text, xml, 1, xml_log_option_formatted); \
         }                                                               \
     } while(0)
 
 #  define do_crm_log_alias(level, file, function, line, fmt, args...) do { \
 	qb_log_from_external_source(function, file, fmt, level, line, 0,  ##args); \
     } while(0)
 
-#  define do_crm_log_always(level, fmt, args...) qb_log(level, "%s: " fmt, __PRETTY_FUNCTION__ , ##args)
+#  define do_crm_log_always(level, fmt, args...) qb_log(level, "%s: " fmt, __FUNCTION__ , ##args)
 
 #  define crm_perror(level, fmt, args...) do {				\
 	const char *err = strerror(errno);				\
 	fprintf(stderr, fmt ": %s (%d)\n", ##args, err, errno);		\
 	do_crm_log(level, fmt ": %s (%d)", ##args, err, errno);		\
     } while(0)
 
 #  define crm_log_tag(level, tag, fmt, args...)    do {               \
         static struct qb_log_callsite *trace_tag_cs = NULL;                 \
         int converted_tag = g_quark_try_string(tag);                   \
         if(trace_tag_cs == NULL) {                                          \
             trace_tag_cs = qb_log_callsite_get(__func__, __FILE__, fmt, level, __LINE__, converted_tag); \
         }                                                               \
         if (crm_is_callsite_active(trace_tag_cs, level, converted_tag)) {               \
             qb_log_from_external_source( __func__, __FILE__, fmt, level, __LINE__, converted_tag, ##args); \
         }                                                               \
       } while(0)
 
 #  define crm_crit(fmt, args...)    qb_logt(LOG_CRIT,    0, fmt , ##args)
 #  define crm_err(fmt, args...)     qb_logt(LOG_ERR,     0, fmt , ##args)
 #  define crm_warn(fmt, args...)    qb_logt(LOG_WARNING, 0, fmt , ##args)
 #  define crm_notice(fmt, args...)  qb_logt(LOG_NOTICE,  0, fmt , ##args)
 #  define crm_info(fmt, args...)    qb_logt(LOG_INFO,    0, fmt , ##args)
 
 #  define crm_debug(fmt, args...)   do_crm_log_unlikely(LOG_DEBUG, fmt , ##args)
 #  define crm_trace(fmt, args...)   do_crm_log_unlikely(LOG_TRACE, fmt , ##args)
 
 #  define crm_log_xml_crit(xml, text)    do_crm_log_xml(LOG_CRIT,    text, xml)
 #  define crm_log_xml_err(xml, text)     do_crm_log_xml(LOG_ERR,     text, xml)
 #  define crm_log_xml_warn(xml, text)    do_crm_log_xml(LOG_WARNING, text, xml)
 #  define crm_log_xml_notice(xml, text)  do_crm_log_xml(LOG_NOTICE,  text, xml)
 #  define crm_log_xml_info(xml, text)    do_crm_log_xml(LOG_INFO,    text, xml)
 #  define crm_log_xml_debug(xml, text)   do_crm_log_xml(LOG_DEBUG,   text, xml)
 #  define crm_log_xml_trace(xml, text)   do_crm_log_xml(LOG_TRACE,   text, xml)
 
 #  define crm_log_xml_explicit(xml, text)  do {                 \
         static struct qb_log_callsite *digest_cs = NULL;        \
         digest_cs = qb_log_callsite_get(                        \
             __func__, __FILE__, text, LOG_TRACE, __LINE__,      \
             crm_trace_nonlog);                                  \
         if (digest_cs && digest_cs->targets) {                  \
             do_crm_log_xml(LOG_TRACE,   text, xml);             \
         }                                                       \
     } while(0)
 
 #  define crm_str(x)    (const char*)(x?x:"<null>")
 
 #endif
diff --git a/include/crm/error.h b/include/crm/error.h
index 1613d66e28..2d14065db0 100644
--- a/include/crm/error.h
+++ b/include/crm/error.h
@@ -1,59 +1,59 @@
 /*
  * Copyright (C) 2012 Andrew Beekhof <andrew@beekhof.net>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This software 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
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #ifndef CRM_ERROR__H
 #  define CRM_ERROR__H
 #  include <crm_config.h>
 #  include <assert.h>
 
 /**
  * \file
  * \brief Error codes and asserts
  * \ingroup core
  */
 
 /*
   System error codes
   - /usr/include/asm-generic/errno.h
   - /usr/include/asm-generic/errno-base.h
 */
 
 #  define CRM_ASSERT(expr) do {						\
 	if(__unlikely((expr) == FALSE)) {				\
-	    crm_abort(__FILE__, __PRETTY_FUNCTION__, __LINE__, #expr, TRUE, FALSE); \
+	    crm_abort(__FILE__, __FUNCTION__, __LINE__, #expr, TRUE, FALSE); \
 	}								\
     } while(0)
 
 #  define pcmk_ok                       0
 #  define PCMK_ERROR_OFFSET             190    /* Replacements on non-linux systems, see include/portability.h */
 #  define PCMK_CUSTOM_OFFSET            200    /* Purely custom codes */
 #  define pcmk_err_generic              201
 #  define pcmk_err_no_quorum            202
 #  define pcmk_err_dtd_validation       203
 #  define pcmk_err_transform_failed     204
 #  define pcmk_err_old_data             205
 #  define pcmk_err_diff_failed          206
 #  define pcmk_err_diff_resync          207
 #  define pcmk_err_cib_modified         208
 #  define pcmk_err_cib_backup           209
 #  define pcmk_err_cib_save             210
 
 const char *pcmk_strerror(int rc);
 const char *pcmk_errorname(int rc);
 const char *bz2_strerror(int rc);
 
 #endif
diff --git a/include/crm_internal.h b/include/crm_internal.h
index ddcb0cada5..97d545304c 100644
--- a/include/crm_internal.h
+++ b/include/crm_internal.h
@@ -1,336 +1,336 @@
 /* crm_internal.h */
 
 /*
  * Copyright (C) 2006 - 2008
  *     Andrew Beekhof <andrew@beekhof.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
  * This program 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 General Public License for more details.
  *
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #ifndef CRM_INTERNAL__H
 #  define CRM_INTERNAL__H
 
 #  include <config.h>
 #  include <portability.h>
 
 #  include <glib.h>
 #  include <stdbool.h>
 #  include <libxml/tree.h>
 
 #  include <crm/lrmd.h>
 #  include <crm/common/logging.h>
 #  include <crm/common/ipcs.h>
 
 /* Dynamic loading of libraries */
 void *find_library_function(void **handle, const char *lib, const char *fn, int fatal);
 void *convert_const_pointer(const void *ptr);
 
 /* For ACLs */
 char *uid2username(uid_t uid);
 void determine_request_user(const char *user, xmlNode * request, const char *field);
 
 #  if ENABLE_ACL
 #    include <string.h>
 static inline gboolean
 is_privileged(const char *user)
 {
     if (user == NULL) {
         return FALSE;
     } else if (strcmp(user, CRM_DAEMON_USER) == 0) {
         return TRUE;
     } else if (strcmp(user, "root") == 0) {
         return TRUE;
     }
     return FALSE;
 }
 #  endif
 
 /* CLI option processing*/
 #  ifdef HAVE_GETOPT_H
 #    include <getopt.h>
 #  else
 #    define no_argument 0
 #    define required_argument 1
 #  endif
 
 #  define pcmk_option_default	0x00000
 #  define pcmk_option_hidden	0x00001
 #  define pcmk_option_paragraph	0x00002
 #  define pcmk_option_example	0x00004
 
 struct crm_option {
     /* Fields from 'struct option' in getopt.h */
     /* name of long option */
     const char *name;
     /*
      * one of no_argument, required_argument, and optional_argument:
      * whether option takes an argument
      */
     int has_arg;
     /* if not NULL, set *flag to val when option found */
     int *flag;
     /* if flag not NULL, value to set *flag to; else return value */
     int val;
 
     /* Custom fields */
     const char *desc;
     long flags;
 };
 
 void crm_set_options(const char *short_options, const char *usage, struct crm_option *long_options,
                      const char *app_desc);
 int crm_get_option(int argc, char **argv, int *index);
 int crm_get_option_long(int argc, char **argv, int *index, const char **longname);
 void crm_help(char cmd, int exit_code);
 
 /* Cluster Option Processing */
 typedef struct pe_cluster_option_s {
     const char *name;
     const char *alt_name;
     const char *type;
     const char *values;
     const char *default_value;
 
      gboolean(*is_valid) (const char *);
 
     const char *description_short;
     const char *description_long;
 
 } pe_cluster_option;
 
 const char *cluster_option(GHashTable * options, gboolean(*validate) (const char *),
                            const char *name, const char *old_name, const char *def_value);
 
 const char *get_cluster_pref(GHashTable * options, pe_cluster_option * option_list, int len,
                              const char *name);
 
 void config_metadata(const char *name, const char *version, const char *desc_short,
                      const char *desc_long, pe_cluster_option * option_list, int len);
 
 void verify_all_options(GHashTable * options, pe_cluster_option * option_list, int len);
 gboolean check_time(const char *value);
 gboolean check_timer(const char *value);
 gboolean check_boolean(const char *value);
 gboolean check_number(const char *value);
 gboolean check_utilization(const char *value);
 
 /* Shared PE/crmd functionality */
 void filter_action_parameters(xmlNode * param_set, const char *version);
 void filter_reload_parameters(xmlNode * param_set, const char *restart_string);
 
 /* Resource operation updates */
 xmlNode *create_operation_update(xmlNode * parent, lrmd_event_data_t * event,
                                  const char *caller_version, int target_rc, const char *origin,
                                  int level);
 
 /* char2score */
 extern int node_score_red;
 extern int node_score_green;
 extern int node_score_yellow;
 extern int node_score_infinity;
 
 /* Assorted convenience functions */
 static inline int
 crm_strlen_zero(const char *s)
 {
     return !s || *s == '\0';
 }
 
 char *add_list_element(char *list, const char *value);
 char *generate_series_filename(const char *directory, const char *series, int sequence,
                                gboolean bzip);
 int get_last_sequence(const char *directory, const char *series);
 void write_last_sequence(const char *directory, const char *series, int sequence, int max);
 
 int crm_pid_active(long pid);
 void crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile);
 gboolean crm_is_writable(const char *dir, const char *file, const char *user, const char *group,
                          gboolean need_both);
 
 char *generate_op_key(const char *rsc_id, const char *op_type, int interval);
 char *generate_notify_key(const char *rsc_id, const char *notify_type, const char *op_type);
 char *generate_transition_magic_v202(const char *transition_key, int op_status);
 char *generate_transition_magic(const char *transition_key, int op_status, int op_rc);
 char *generate_transition_key(int action, int transition_id, int target_rc, const char *node);
 
 static inline long long
 crm_clear_bit(const char *function, const char *target, long long word, long long bit)
 {
     long long rc = (word & ~bit);
 
     if (rc == word) {
         /* Unchanged */
     } else if (target) {
         crm_trace("Bit 0x%.8llx for %s cleared by %s", bit, target, function);
     } else {
         crm_trace("Bit 0x%.8llx cleared by %s", bit, function);
     }
 
     return rc;
 }
 
 static inline long long
 crm_set_bit(const char *function, const char *target, long long word, long long bit)
 {
     long long rc = (word | bit);
 
     if (rc == word) {
         /* Unchanged */
     } else if (target) {
         crm_trace("Bit 0x%.8llx for %s set by %s", bit, target, function);
     } else {
         crm_trace("Bit 0x%.8llx set by %s", bit, function);
     }
 
     return rc;
 }
 
-#  define set_bit(word, bit) word = crm_set_bit(__PRETTY_FUNCTION__, NULL, word, bit)
-#  define clear_bit(word, bit) word = crm_clear_bit(__PRETTY_FUNCTION__, NULL, word, bit)
+#  define set_bit(word, bit) word = crm_set_bit(__FUNCTION__, NULL, word, bit)
+#  define clear_bit(word, bit) word = crm_clear_bit(__FUNCTION__, NULL, word, bit)
 
 void g_hash_destroy_str(gpointer data);
 
 long long crm_int_helper(const char *text, char **end_text);
 char *crm_concat(const char *prefix, const char *suffix, char join);
 char *generate_hash_key(const char *crm_msg_reference, const char *sys);
 
 bool crm_compress_string(const char *data, int length, int max, char **result,
                          unsigned int *result_len);
 
 /*! remote tcp/tls helper functions */
 typedef struct crm_remote_s crm_remote_t;
 
 int crm_remote_send(crm_remote_t * remote, xmlNode * msg);
 int crm_remote_ready(crm_remote_t * remote, int total_timeout /*ms */ );
 gboolean crm_remote_recv(crm_remote_t * remote, int total_timeout /*ms */ , int *disconnected);
 xmlNode *crm_remote_parse_buffer(crm_remote_t * remote);
 int crm_remote_tcp_connect(const char *host, int port);
 int crm_remote_tcp_connect_async(const char *host, int port, int timeout,       /*ms */
                                  void *userdata, void (*callback) (void *userdata, int sock));
 
 #  ifdef HAVE_GNUTLS_GNUTLS_H
 /*!
  * \internal
  * \brief Initiate the client handshake after establishing the tcp socket.
  * \note This is a blocking function, it will block until the entire handshake
  *       is complete or until the timeout period is reached.
  * \retval 0 success
  * \retval negative, failure
  */
 int crm_initiate_client_tls_handshake(crm_remote_t * remote, int timeout_ms);
 
 /*!
  * \internal
  * \brief Create client or server session for anon DH encryption credentials
  * \param sock, the socket the session will use for transport
  * \param type, GNUTLS_SERVER or GNUTLS_CLIENT
  * \param credentials, gnutls_anon_server_credentials_t or gnutls_anon_client_credentials_t
  *
  * \retval gnutls_session_t * on success
  * \retval NULL on failure
  */
 void *crm_create_anon_tls_session(int sock, int type, void *credentials);
 
 /*!
  * \internal
  * \brief Create client or server session for PSK credentials
  * \param sock, the socket the session will use for transport
  * \param type, GNUTLS_SERVER or GNUTLS_CLIENT
  * \param credentials, gnutls_psk_server_credentials_t or gnutls_osk_client_credentials_t
  *
  * \retval gnutls_session_t * on success
  * \retval NULL on failure
  */
 void *create_psk_tls_session(int csock, int type, void *credentials);
 #  endif
 
 #  define REMOTE_MSG_TERMINATOR "\r\n\r\n"
 
 const char *daemon_option(const char *option);
 void set_daemon_option(const char *option, const char *value);
 gboolean daemon_option_enabled(const char *daemon, const char *option);
 void strip_text_nodes(xmlNode * xml);
 
 #  define crm_config_err(fmt...) { crm_config_error = TRUE; crm_err(fmt); }
 #  define crm_config_warn(fmt...) { crm_config_warning = TRUE; crm_warn(fmt); }
 
 #  define attrd_channel		T_ATTRD
 #  define F_ATTRD_KEY		"attr_key"
 #  define F_ATTRD_ATTRIBUTE	"attr_name"
 #  define F_ATTRD_TASK		"task"
 #  define F_ATTRD_VALUE		"attr_value"
 #  define F_ATTRD_SET		"attr_set"
 #  define F_ATTRD_IS_REMOTE	"attr_is_remote"
 #  define F_ATTRD_SECTION	"attr_section"
 #  define F_ATTRD_DAMPEN	"attr_dampening"
 #  define F_ATTRD_IGNORE_LOCALLY "attr_ignore_locally"
 #  define F_ATTRD_HOST		"attr_host"
 #  define F_ATTRD_HOST_ID	"attr_host_id"
 #  define F_ATTRD_USER		"attr_user"
 #  define F_ATTRD_WRITER	"attr_writer"
 #  define F_ATTRD_VERSION	"attr_version"
 
 #  if SUPPORT_COROSYNC
 #    if CS_USES_LIBQB
 #      include <qb/qbipc_common.h>
 #      include <corosync/corotypes.h>
 typedef struct qb_ipc_request_header cs_ipc_header_request_t;
 typedef struct qb_ipc_response_header cs_ipc_header_response_t;
 #    else
 #      include <corosync/corodefs.h>
 #      include <corosync/coroipcc.h>
 #      include <corosync/coroipc_types.h>
 static inline int
 qb_to_cs_error(int a)
 {
     return a;
 }
 
 typedef coroipc_request_header_t cs_ipc_header_request_t;
 typedef coroipc_response_header_t cs_ipc_header_response_t;
 #    endif
 #  else
 typedef struct {
     int size __attribute__ ((aligned(8)));
     int id __attribute__ ((aligned(8)));
 } __attribute__ ((aligned(8))) cs_ipc_header_request_t;
 
 typedef struct {
     int size __attribute__ ((aligned(8)));
     int id __attribute__ ((aligned(8)));
     int error __attribute__ ((aligned(8)));
 } __attribute__ ((aligned(8))) cs_ipc_header_response_t;
 
 #  endif
 
 void
 attrd_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb);
 void
 stonith_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb);
 
 qb_ipcs_service_t *
 crmd_ipc_server_init(struct qb_ipcs_service_handlers *cb);
 
 void cib_ipc_servers_init(qb_ipcs_service_t **ipcs_ro,
         qb_ipcs_service_t **ipcs_rw,
         qb_ipcs_service_t **ipcs_shm,
         struct qb_ipcs_service_handlers *ro_cb,
         struct qb_ipcs_service_handlers *rw_cb);
 
 void cib_ipc_servers_destroy(qb_ipcs_service_t *ipcs_ro,
         qb_ipcs_service_t *ipcs_rw,
         qb_ipcs_service_t *ipcs_shm);
 
 #endif                          /* CRM_INTERNAL__H */
diff --git a/lib/ais/plugin.c b/lib/ais/plugin.c
index b86753171e..3d4f369a1a 100644
--- a/lib/ais/plugin.c
+++ b/lib/ais/plugin.c
@@ -1,1803 +1,1803 @@
 /*
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  *
  * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USAA
  */
 
 #include <crm_internal.h>
 #include <crm/cluster/internal.h>
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
 
 #include <corosync/totem/totempg.h>
 #include <corosync/engine/objdb.h>
 #include <corosync/engine/config.h>
 
 #include <config.h>
 #include "plugin.h"
 #include "utils.h"
 
 #include <glib.h>
 
 #include <sys/resource.h>
 #include <sys/utsname.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <pthread.h>
 #include <bzlib.h>
 #include <pwd.h>
 
 struct corosync_api_v1 *pcmk_api = NULL;
 
 uint32_t plugin_has_votes = 0;
 uint32_t plugin_expected_votes = 2;
 
 int use_mgmtd = 0;
 int plugin_log_level = LOG_DEBUG;
 char *local_uname = NULL;
 int local_uname_len = 0;
 char *local_cname = NULL;
 int local_cname_len = 0;
 uint32_t local_nodeid = 0;
 char *ipc_channel_name = NULL;
 static uint64_t local_born_on = 0;
 
 uint64_t membership_seq = 0;
 pthread_t pcmk_wait_thread;
 
 gboolean use_mcp = FALSE;
 gboolean wait_active = TRUE;
 gboolean have_reliable_membership_id = FALSE;
 GHashTable *ipc_client_list = NULL;
 GHashTable *membership_list = NULL;
 GHashTable *membership_notify_list = NULL;
 
 #define MAX_RESPAWN		100
 #define LOOPBACK_ID		16777343
 #define crm_flag_none		0x00000000
 #define crm_flag_members	0x00000001
 
 struct crm_identify_msg_s {
     cs_ipc_header_request_t header __attribute__ ((aligned(8)));
     uint32_t id;
     uint32_t pid;
     int32_t votes;
     uint32_t processes;
     char uname[256];
     char version[256];
     uint64_t born_on;
 } __attribute__ ((packed));
 
 /* *INDENT-OFF* */
 static crm_child_t pcmk_children[] = {
     { 0, crm_proc_none,     crm_flag_none,    0, 0, FALSE, "none",     NULL,		NULL,			   NULL, NULL },
     { 0, crm_proc_plugin,      crm_flag_none,    0, 0, FALSE, "ais",      NULL,		NULL,			   NULL, NULL },
     { 0, crm_proc_lrmd,     crm_flag_none,    3, 0, TRUE,  "lrmd",     NULL,		CRM_DAEMON_DIR"/lrmd",     NULL, NULL },
     { 0, crm_proc_cib,      crm_flag_members, 1, 0, TRUE,  "cib",      CRM_DAEMON_USER, CRM_DAEMON_DIR"/cib",      NULL, NULL },
     { 0, crm_proc_crmd,     crm_flag_members, 6, 0, TRUE,  "crmd",     CRM_DAEMON_USER, CRM_DAEMON_DIR"/crmd",     NULL, NULL },
     { 0, crm_proc_attrd,    crm_flag_none,    4, 0, TRUE,  "attrd",    CRM_DAEMON_USER, CRM_DAEMON_DIR"/attrd",    NULL, NULL },
     { 0, crm_proc_stonithd, crm_flag_none,    0, 0, TRUE,  "stonithd", NULL,		"/bin/false",		   NULL, NULL },
     { 0, crm_proc_pe,       crm_flag_none,    5, 0, TRUE,  "pengine",  CRM_DAEMON_USER, CRM_DAEMON_DIR"/pengine",  NULL, NULL },
     { 0, crm_proc_mgmtd,    crm_flag_none,    7, 0, TRUE,  "mgmtd",    NULL,		HB_DAEMON_DIR"/mgmtd",     NULL, NULL },
     { 0, crm_proc_stonith_ng, crm_flag_members, 2, 0, TRUE,  "stonith-ng", NULL,		CRM_DAEMON_DIR"/stonithd", NULL, NULL },
 };
 /* *INDENT-ON* */
 
 void send_cluster_id(void);
 int send_plugin_msg_raw(const AIS_Message * ais_msg);
 char *pcmk_generate_membership_data(void);
 gboolean check_message_sanity(const AIS_Message * msg, const char *data);
 
 typedef const void ais_void_ptr;
 int pcmk_shutdown(void);
 void pcmk_peer_update(enum totem_configuration_type configuration_type,
                       const unsigned int *member_list, size_t member_list_entries,
                       const unsigned int *left_list, size_t left_list_entries,
                       const unsigned int *joined_list, size_t joined_list_entries,
                       const struct memb_ring_id *ring_id);
 
 int pcmk_startup(struct corosync_api_v1 *corosync_api);
 int pcmk_config_init(struct corosync_api_v1 *corosync_api);
 
 int pcmk_ipc_exit(void *conn);
 int pcmk_ipc_connect(void *conn);
 void pcmk_ipc(void *conn, ais_void_ptr * msg);
 
 void pcmk_exec_dump(void);
 void pcmk_cluster_swab(void *msg);
 void pcmk_cluster_callback(ais_void_ptr * message, unsigned int nodeid);
 
 void pcmk_nodeid(void *conn, ais_void_ptr * msg);
 void pcmk_nodes(void *conn, ais_void_ptr * msg);
 void pcmk_notify(void *conn, ais_void_ptr * msg);
 void pcmk_remove_member(void *conn, ais_void_ptr * msg);
 void pcmk_quorum(void *conn, ais_void_ptr * msg);
 
 void pcmk_cluster_id_swab(void *msg);
 void pcmk_cluster_id_callback(ais_void_ptr * message, unsigned int nodeid);
 void ais_remove_peer(char *node_id);
 void ais_remove_peer_by_name(const char *node_name);
 
 static uint32_t
 get_process_list(void)
 {
     int lpc = 0;
     uint32_t procs = crm_proc_plugin;
 
     if (use_mcp) {
         return 0;
     }
 
     for (lpc = 0; lpc < SIZEOF(pcmk_children); lpc++) {
         if (pcmk_children[lpc].pid != 0) {
             procs |= pcmk_children[lpc].flag;
         }
     }
     return procs;
 }
 
 static struct corosync_lib_handler pcmk_lib_service[] = {
     {                           /* 0 - crm_class_cluster */
      .lib_handler_fn = pcmk_ipc,
      .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
      },
     {                           /* 1 - crm_class_members */
      .lib_handler_fn = pcmk_nodes,
      .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
      },
     {                           /* 2 - crm_class_notify */
      .lib_handler_fn = pcmk_notify,
      .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
      },
     {                           /* 3 - crm_class_nodeid */
      .lib_handler_fn = pcmk_nodeid,
      .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
      },
     {                           /* 4 - crm_class_rmpeer */
      .lib_handler_fn = pcmk_remove_member,
      .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
      },
     {                           /* 5 - crm_class_quorum */
      .lib_handler_fn = pcmk_quorum,
      .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
      },
 };
 
 static struct corosync_exec_handler pcmk_exec_service[] = {
     {                           /* 0 */
      .exec_handler_fn = pcmk_cluster_callback,
      .exec_endian_convert_fn = pcmk_cluster_swab},
     {                           /* 1 */
      .exec_handler_fn = pcmk_cluster_id_callback,
      .exec_endian_convert_fn = pcmk_cluster_id_swab}
 };
 
 /*
  * Exports the interface for the service
  */
 /* *INDENT-OFF* */
 struct corosync_service_engine pcmk_service_handler = {
     .name			= (char *)"Pacemaker Cluster Manager "PACKAGE_VERSION,
     .id				= PCMK_SERVICE_ID,
     .private_data_size		= 0,
     .flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
     .allow_inquorate		= CS_LIB_ALLOW_INQUORATE,
     .lib_init_fn		= pcmk_ipc_connect,
     .lib_exit_fn		= pcmk_ipc_exit,
     .exec_init_fn		= pcmk_startup,
     .exec_exit_fn		= pcmk_shutdown,
     .config_init_fn		= pcmk_config_init,
     .priority			= 50,
     .lib_engine			= pcmk_lib_service,
     .lib_engine_count		= sizeof (pcmk_lib_service) / sizeof (struct corosync_lib_handler),
     .exec_engine		= pcmk_exec_service,
     .exec_engine_count		= sizeof (pcmk_exec_service) / sizeof (struct corosync_exec_handler),
     .confchg_fn			= pcmk_peer_update,
     .exec_dump_fn		= pcmk_exec_dump,
 /* 	void (*sync_init) (void); */
 /* 	int (*sync_process) (void); */
 /* 	void (*sync_activate) (void); */
 /* 	void (*sync_abort) (void); */
 };
 
 
 /*
  * Dynamic Loader definition
  */
 struct corosync_service_engine *pcmk_get_handler_ver0 (void);
 
 struct corosync_service_engine_iface_ver0 pcmk_service_handler_iface = {
     .corosync_get_service_engine_ver0 = pcmk_get_handler_ver0
 };
 
 static struct lcr_iface openais_pcmk_ver0[2] = {
     {
 	.name				= "pacemaker",
 	.version			= 0,
 	.versions_replace		= 0,
 	.versions_replace_count		= 0,
 	.dependencies			= 0,
 	.dependency_count		= 0,
 	.constructor			= NULL,
 	.destructor			= NULL,
 	.interfaces			= NULL
     },
     {
 	.name				= "pacemaker",
 	.version			= 1,
 	.versions_replace		= 0,
 	.versions_replace_count		= 0,
 	.dependencies			= 0,
 	.dependency_count		= 0,
 	.constructor			= NULL,
 	.destructor			= NULL,
 	.interfaces			= NULL
     }
 };
 
 static struct lcr_comp pcmk_comp_ver0 = {
     .iface_count			= 2,
     .ifaces				= openais_pcmk_ver0
 };
 /* *INDENT-ON* */
 
 struct corosync_service_engine *
 pcmk_get_handler_ver0(void)
 {
     return (&pcmk_service_handler);
 }
 
 __attribute__ ((constructor))
 static void
 register_this_component(void)
 {
     lcr_interfaces_set(&openais_pcmk_ver0[0], &pcmk_service_handler_iface);
     lcr_interfaces_set(&openais_pcmk_ver0[1], &pcmk_service_handler_iface);
 
     lcr_component_register(&pcmk_comp_ver0);
 }
 
 static int
 plugin_has_quorum(void)
 {
     if ((plugin_expected_votes >> 1) < plugin_has_votes) {
         return 1;
     }
     return 0;
 }
 
 static void
 update_expected_votes(int value)
 {
     if (value < plugin_has_votes) {
         /* Never drop below the number of connected nodes */
         ais_info("Cannot update expected quorum votes %d -> %d:"
                  " value cannot be less that the current number of votes",
                  plugin_expected_votes, value);
 
     } else if (plugin_expected_votes != value) {
         ais_info("Expected quorum votes %d -> %d", plugin_expected_votes, value);
         plugin_expected_votes = value;
     }
 }
 
 /* Create our own local copy of the config so we can navigate it */
 static void
 process_ais_conf(void)
 {
     char *value = NULL;
     gboolean any_log = FALSE;
     hdb_handle_t top_handle = 0;
     hdb_handle_t local_handle = 0;
 
     ais_info("Reading configure");
     top_handle = config_find_init(pcmk_api, "logging");
     local_handle = config_find_next(pcmk_api, "logging", top_handle);
 
     get_config_opt(pcmk_api, local_handle, "debug", &value, "on");
     if (ais_get_boolean(value)) {
         plugin_log_level = LOG_DEBUG;
         pcmk_env.debug = "1";
 
     } else {
         plugin_log_level = LOG_INFO;
         pcmk_env.debug = "0";
     }
 
     get_config_opt(pcmk_api, local_handle, "to_logfile", &value, "off");
     if (ais_get_boolean(value)) {
         get_config_opt(pcmk_api, local_handle, "logfile", &value, NULL);
 
         if (value == NULL) {
             ais_err("Logging to a file requested but no log file specified");
 
         } else {
             uid_t pcmk_uid = geteuid();
             uid_t pcmk_gid = getegid();
 
             FILE *logfile = fopen(value, "a");
 
             if (logfile) {
                 int ignore = 0;
                 int logfd = fileno(logfile);
 
                 pcmk_env.logfile = value;
 
                 /* Ensure the file has the correct permissions */
                 ignore = fchown(logfd, pcmk_uid, pcmk_gid);
                 ignore = fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
 
                 if (ignore < 0) {
                     fprintf(logfile, "Could not set r/w permissions for uid=%d, gid=%d on %s\n",
                             pcmk_uid, pcmk_gid, value);
 
                 } else {
                     fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n",
                             pcmk_uid, pcmk_gid, value);
                 }
                 fflush(logfile);
                 fsync(logfd);
                 fclose(logfile);
                 any_log = TRUE;
 
             } else {
                 ais_err("Couldn't create logfile: %s", value);
             }
         }
     }
 
     get_config_opt(pcmk_api, local_handle, "to_syslog", &value, "on");
     if (any_log && ais_get_boolean(value) == FALSE) {
         ais_info("User configured file based logging and explicitly disabled syslog.");
         value = "none";
 
     } else {
         if (ais_get_boolean(value) == FALSE) {
             ais_err
                 ("Please enable some sort of logging, either 'to_file: on' or  'to_syslog: on'.");
             ais_err("If you use file logging, be sure to also define a value for 'logfile'");
         }
         get_config_opt(pcmk_api, local_handle, "syslog_facility", &value, "daemon");
     }
     pcmk_env.syslog = value;
 
     config_find_done(pcmk_api, local_handle);
 
     top_handle = config_find_init(pcmk_api, "quorum");
     local_handle = config_find_next(pcmk_api, "quorum", top_handle);
     get_config_opt(pcmk_api, local_handle, "provider", &value, NULL);
     if (value && ais_str_eq("quorum_cman", value)) {
         pcmk_env.quorum = "cman";
     } else {
         pcmk_env.quorum = "pcmk";
     }
 
     top_handle = config_find_init(pcmk_api, "service");
     local_handle = config_find_next(pcmk_api, "service", top_handle);
     while (local_handle) {
         value = NULL;
         pcmk_api->object_key_get(local_handle, "name", strlen("name"), (void **)&value, NULL);
         if (ais_str_eq("pacemaker", value)) {
             break;
         }
         local_handle = config_find_next(pcmk_api, "service", top_handle);
     }
 
     get_config_opt(pcmk_api, local_handle, "ver", &value, "0");
     if (ais_str_eq(value, "1")) {
         ais_info("Enabling MCP mode: Use the Pacemaker init script to complete Pacemaker startup");
         use_mcp = TRUE;
     }
 
     get_config_opt(pcmk_api, local_handle, "clustername", &local_cname, "pcmk");
     local_cname_len = strlen(local_cname);
 
     get_config_opt(pcmk_api, local_handle, "use_logd", &value, "no");
     pcmk_env.use_logd = value;
 
     get_config_opt(pcmk_api, local_handle, "use_mgmtd", &value, "no");
     if (ais_get_boolean(value) == FALSE) {
         int lpc = 0;
 
         for (; lpc < SIZEOF(pcmk_children); lpc++) {
             if (crm_proc_mgmtd & pcmk_children[lpc].flag) {
                 /* Disable mgmtd startup */
                 pcmk_children[lpc].start_seq = 0;
                 break;
             }
         }
     }
 
     config_find_done(pcmk_api, local_handle);
 }
 
 int
 pcmk_config_init(struct corosync_api_v1 *unused)
 {
     return 0;
 }
 
 static void *
 pcmk_wait_dispatch(void *arg)
 {
     struct timespec waitsleep = {
         .tv_sec = 1,
         .tv_nsec = 0
     };
 
     while (wait_active) {
         int lpc = 0;
 
         for (; lpc < SIZEOF(pcmk_children); lpc++) {
             if (pcmk_children[lpc].pid > 0) {
                 int status;
                 pid_t pid = wait4(pcmk_children[lpc].pid, &status, WNOHANG, NULL);
 
                 if (pid == 0) {
                     continue;
 
                 } else if (pid < 0) {
                     ais_perror("Call to wait4(%s) failed", pcmk_children[lpc].name);
                     continue;
                 }
 
                 /* cleanup */
                 pcmk_children[lpc].pid = 0;
                 pcmk_children[lpc].conn = NULL;
                 pcmk_children[lpc].async_conn = NULL;
 
                 if (WIFSIGNALED(status)) {
                     int sig = WTERMSIG(status);
 
                     ais_err("Child process %s terminated with signal %d"
                             " (pid=%d, core=%s)",
                             pcmk_children[lpc].name, sig, pid,
                             WCOREDUMP(status) ? "true" : "false");
 
                 } else if (WIFEXITED(status)) {
                     int rc = WEXITSTATUS(status);
 
                     do_ais_log(rc == 0 ? LOG_NOTICE : LOG_ERR,
                                "Child process %s exited (pid=%d, rc=%d)", pcmk_children[lpc].name,
                                pid, rc);
 
                     if (rc == 100) {
                         ais_notice("Child process %s no longer wishes"
                                    " to be respawned", pcmk_children[lpc].name);
                         pcmk_children[lpc].respawn = FALSE;
                     }
                 }
 
                 /* Broadcast the fact that one of our processes died
                  *
                  * Try to get some logging of the cause out first though
                  * because we're probably about to get fenced
                  *
                  * Potentially do this only if respawn_count > N
                  * to allow for local recovery
                  */
                 send_cluster_id();
 
                 pcmk_children[lpc].respawn_count += 1;
                 if (pcmk_children[lpc].respawn_count > MAX_RESPAWN) {
                     ais_err("Child respawn count exceeded by %s", pcmk_children[lpc].name);
                     pcmk_children[lpc].respawn = FALSE;
                 }
                 if (pcmk_children[lpc].respawn) {
                     ais_notice("Respawning failed child process: %s", pcmk_children[lpc].name);
                     spawn_child(&(pcmk_children[lpc]));
                 }
                 send_cluster_id();
             }
         }
         sched_yield();
         nanosleep(&waitsleep, 0);
     }
     return 0;
 }
 
 static uint32_t
 pcmk_update_nodeid(void)
 {
     int last = local_nodeid;
 
     local_nodeid = pcmk_api->totem_nodeid_get();
 
     if (last != local_nodeid) {
         if (last == 0) {
             ais_info("Local node id: %u", local_nodeid);
 
         } else {
             char *last_s = NULL;
 
             ais_malloc0(last_s, 32);
             ais_warn("Detected local node id change: %u -> %u", last, local_nodeid);
             snprintf(last_s, 31, "%u", last);
             ais_remove_peer(last_s);
             ais_free(last_s);
         }
         update_member(local_nodeid, 0, 0, 1, 0, local_uname, CRM_NODE_MEMBER, NULL);
     }
 
     return local_nodeid;
 }
 
 static void
 build_path(const char *path_c, mode_t mode)
 {
     int offset = 1, len = 0;
     char *path = ais_strdup(path_c);
 
     AIS_CHECK(path != NULL, return);
     for (len = strlen(path); offset < len; offset++) {
         if (path[offset] == '/') {
             path[offset] = 0;
             if (mkdir(path, mode) < 0 && errno != EEXIST) {
                 ais_perror("Could not create directory '%s'", path);
                 break;
             }
             path[offset] = '/';
         }
     }
     if (mkdir(path, mode) < 0 && errno != EEXIST) {
         ais_perror("Could not create directory '%s'", path);
     }
     ais_free(path);
 }
 
 int
 pcmk_startup(struct corosync_api_v1 *init_with)
 {
     int rc = 0;
     int lpc = 0;
     int start_seq = 1;
     struct utsname us;
     struct rlimit cores;
     static int max = SIZEOF(pcmk_children);
 
     uid_t pcmk_uid = 0;
     gid_t pcmk_gid = 0;
 
     uid_t root_uid = -1;
     uid_t cs_uid = geteuid();
 
     pcmk_user_lookup("root", &root_uid, NULL);
 
     pcmk_api = init_with;
 
     pcmk_env.debug = "0";
     pcmk_env.logfile = NULL;
     pcmk_env.use_logd = "false";
     pcmk_env.syslog = "daemon";
 
     if (cs_uid != root_uid) {
         ais_err("Corosync must be configured to start as 'root',"
                 " otherwise Pacemaker cannot manage services."
                 "  Expected %d got %d", root_uid, cs_uid);
         return -1;
     }
 
     process_ais_conf();
 
     membership_list = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, destroy_ais_node);
     membership_notify_list = g_hash_table_new(g_direct_hash, g_direct_equal);
     ipc_client_list = g_hash_table_new(g_direct_hash, g_direct_equal);
 
     ais_info("CRM: Initialized");
-    log_printf(LOG_INFO, "Logging: Initialized %s\n", __PRETTY_FUNCTION__);
+    log_printf(LOG_INFO, "Logging: Initialized %s\n", __FUNCTION__);
 
     rc = getrlimit(RLIMIT_CORE, &cores);
     if (rc < 0) {
         ais_perror("Cannot determine current maximum core size.");
     } else {
         if (cores.rlim_max == 0 && geteuid() == 0) {
             cores.rlim_max = RLIM_INFINITY;
         } else {
             ais_info("Maximum core file size is: %lu", cores.rlim_max);
         }
         cores.rlim_cur = cores.rlim_max;
 
         rc = setrlimit(RLIMIT_CORE, &cores);
         if (rc < 0) {
             ais_perror("Core file generation will remain disabled."
                        " Core files are an important diagnositic tool,"
                        " please consider enabling them by default.");
         }
 #if 0
         /* system() is not thread-safe, can't call from here
          * Actually, its a pretty hacky way to try and achieve this anyway
          */
         if (system("echo 1 > /proc/sys/kernel/core_uses_pid") != 0) {
             ais_perror("Could not enable /proc/sys/kernel/core_uses_pid");
         }
 #endif
     }
 
     if (pcmk_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) < 0) {
         ais_err("Cluster user %s does not exist, aborting Pacemaker startup", CRM_DAEMON_USER);
         return TRUE;
     }
 
     rc = mkdir(CRM_STATE_DIR, 0750);
     rc = chown(CRM_STATE_DIR, pcmk_uid, pcmk_gid);
 
     /* Used by stonithd */
     build_path(HA_STATE_DIR "/heartbeat", 0755);
 
     /* Used by RAs - Leave owned by root */
     build_path(CRM_RSCTMP_DIR, 0755);
 
     rc = uname(&us);
     AIS_ASSERT(rc == 0);
     local_uname = ais_strdup(us.nodename);
     local_uname_len = strlen(local_uname);
 
     ais_info("Service: %d", PCMK_SERVICE_ID);
     ais_info("Local hostname: %s", local_uname);
     pcmk_update_nodeid();
 
     if (use_mcp == FALSE) {
         pthread_create(&pcmk_wait_thread, NULL, pcmk_wait_dispatch, NULL);
         for (start_seq = 1; start_seq < max; start_seq++) {
             /* dont start anything with start_seq < 1 */
             for (lpc = 0; lpc < max; lpc++) {
                 if (start_seq == pcmk_children[lpc].start_seq) {
                     spawn_child(&(pcmk_children[lpc]));
                 }
             }
         }
     }
     return 0;
 }
 
 /*
   static void ais_print_node(const char *prefix, struct totem_ip_address *host)
   {
   int len = 0;
   char *buffer = NULL;
 
   ais_malloc0(buffer, INET6_ADDRSTRLEN+1);
 
   inet_ntop(host->family, host->addr, buffer, INET6_ADDRSTRLEN);
 
   len = strlen(buffer);
   ais_info("%s: %.*s", prefix, len, buffer);
   ais_free(buffer);
   }
 */
 
 #if 0
 /* copied here for reference from exec/totempg.c */
 char *
 totempg_ifaces_print(unsigned int nodeid)
 {
     static char iface_string[256 * INTERFACE_MAX];
     char one_iface[64];
     struct totem_ip_address interfaces[INTERFACE_MAX];
     char **status;
     unsigned int iface_count;
     unsigned int i;
     int res;
 
     iface_string[0] = '\0';
 
     res = totempg_ifaces_get(nodeid, interfaces, &status, &iface_count);
     if (res == -1) {
         return ("no interface found for nodeid");
     }
 
     for (i = 0; i < iface_count; i++) {
         sprintf(one_iface, "r(%d) ip(%s), ", i, totemip_print(&interfaces[i]));
         strcat(iface_string, one_iface);
     }
     return (iface_string);
 }
 #endif
 
 static void
 ais_mark_unseen_peer_dead(gpointer key, gpointer value, gpointer user_data)
 {
     int *changed = user_data;
     crm_node_t *node = value;
 
     if (node->last_seen != membership_seq && ais_str_eq(CRM_NODE_LOST, node->state) == FALSE) {
         ais_info("Node %s was not seen in the previous transition", node->uname);
         *changed += update_member(node->id, 0, membership_seq, node->votes,
                                   node->processes, node->uname, CRM_NODE_LOST, NULL);
     }
 }
 
 void
 pcmk_peer_update(enum totem_configuration_type configuration_type,
                  const unsigned int *member_list, size_t member_list_entries,
                  const unsigned int *left_list, size_t left_list_entries,
                  const unsigned int *joined_list, size_t joined_list_entries,
                  const struct memb_ring_id *ring_id)
 {
     int lpc = 0;
     int changed = 0;
     int do_update = 0;
 
     AIS_ASSERT(ring_id != NULL);
     switch (configuration_type) {
         case TOTEM_CONFIGURATION_REGULAR:
             do_update = 1;
             break;
         case TOTEM_CONFIGURATION_TRANSITIONAL:
             break;
     }
 
     membership_seq = ring_id->seq;
     ais_notice("%s membership event on ring %lld: memb=%ld, new=%ld, lost=%ld",
                do_update ? "Stable" : "Transitional", ring_id->seq,
                (long)member_list_entries, (long)joined_list_entries, (long)left_list_entries);
 
     if (do_update == 0) {
         for (lpc = 0; lpc < joined_list_entries; lpc++) {
             const char *prefix = "new: ";
             uint32_t nodeid = joined_list[lpc];
 
             ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
         }
         for (lpc = 0; lpc < member_list_entries; lpc++) {
             const char *prefix = "memb:";
             uint32_t nodeid = member_list[lpc];
 
             ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
         }
         for (lpc = 0; lpc < left_list_entries; lpc++) {
             const char *prefix = "lost:";
             uint32_t nodeid = left_list[lpc];
 
             ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
         }
         return;
     }
 
     for (lpc = 0; lpc < joined_list_entries; lpc++) {
         const char *prefix = "NEW: ";
         uint32_t nodeid = joined_list[lpc];
         crm_node_t *node = NULL;
 
         changed += update_member(nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_MEMBER, NULL);
 
         ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
 
         node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(nodeid));
         if (node->addr == NULL) {
             const char *addr = totempg_ifaces_print(nodeid);
 
             node->addr = ais_strdup(addr);
             ais_debug("Node %u has address %s", nodeid, node->addr);
         }
     }
 
     for (lpc = 0; lpc < member_list_entries; lpc++) {
         const char *prefix = "MEMB:";
         uint32_t nodeid = member_list[lpc];
 
         changed += update_member(nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_MEMBER, NULL);
 
         ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
     }
 
     for (lpc = 0; lpc < left_list_entries; lpc++) {
         const char *prefix = "LOST:";
         uint32_t nodeid = left_list[lpc];
 
         changed += update_member(nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_LOST, NULL);
         ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
     }
 
     if (changed && joined_list_entries == 0 && left_list_entries == 0) {
         ais_err("Something strange happened: %d", changed);
         changed = 0;
     }
 
     ais_trace("Reaping unseen nodes...");
     g_hash_table_foreach(membership_list, ais_mark_unseen_peer_dead, &changed);
 
     if (member_list_entries > 1) {
         /* Used to set born-on in send_cluster_id())
          * We need to wait until we have at least one peer since first
          * membership id is based on the one before we stopped and isn't reliable
          */
         have_reliable_membership_id = TRUE;
     }
 
     if (changed) {
         ais_debug("%d nodes changed", changed);
         pcmk_update_nodeid();
         send_member_notification();
     }
 
     send_cluster_id();
 }
 
 int
 pcmk_ipc_exit(void *conn)
 {
     int lpc = 0;
     const char *client = NULL;
     void *async_conn = conn;
 
     for (; lpc < SIZEOF(pcmk_children); lpc++) {
         if (pcmk_children[lpc].conn == conn) {
             if (wait_active == FALSE) {
                 /* Make sure the shutdown loop exits */
                 pcmk_children[lpc].pid = 0;
             }
             pcmk_children[lpc].conn = NULL;
             pcmk_children[lpc].async_conn = NULL;
             client = pcmk_children[lpc].name;
             break;
         }
     }
 
     g_hash_table_remove(membership_notify_list, async_conn);
     g_hash_table_remove(ipc_client_list, async_conn);
 
     if (client) {
         do_ais_log(LOG_INFO, "Client %s (conn=%p, async-conn=%p) left", client, conn, async_conn);
     } else {
         do_ais_log((LOG_DEBUG + 1), "Client %s (conn=%p, async-conn=%p) left",
                    "unknown-transient", conn, async_conn);
     }
 
     return (0);
 }
 
 int
 pcmk_ipc_connect(void *conn)
 {
     /* Corosync hasn't finished setting up the connection at this point
      * Sending messages now messes up the protocol!
      */
     return (0);
 }
 
 /*
  * Executive message handlers
  */
 void
 pcmk_cluster_swab(void *msg)
 {
     AIS_Message *ais_msg = msg;
 
     ais_trace("Performing endian conversion...");
     ais_msg->id = swab32(ais_msg->id);
     ais_msg->size = swab32(ais_msg->size);
     ais_msg->is_compressed = swab32(ais_msg->is_compressed);
     ais_msg->compressed_size = swab32(ais_msg->compressed_size);
 
     ais_msg->host.id = swab32(ais_msg->host.id);
     ais_msg->host.pid = swab32(ais_msg->host.pid);
     ais_msg->host.type = swab32(ais_msg->host.type);
     ais_msg->host.size = swab32(ais_msg->host.size);
     ais_msg->host.local = swab32(ais_msg->host.local);
 
     ais_msg->sender.id = swab32(ais_msg->sender.id);
     ais_msg->sender.pid = swab32(ais_msg->sender.pid);
     ais_msg->sender.type = swab32(ais_msg->sender.type);
     ais_msg->sender.size = swab32(ais_msg->sender.size);
     ais_msg->sender.local = swab32(ais_msg->sender.local);
 
     ais_msg->header.size = swab32(ais_msg->header.size);
     ais_msg->header.id = swab32(ais_msg->header.id);
     ais_msg->header.error = swab32(ais_msg->header.error);
 }
 
 void
 pcmk_cluster_callback(ais_void_ptr * message, unsigned int nodeid)
 {
     const AIS_Message *ais_msg = message;
 
     ais_trace("Message from node %u (%s)", nodeid, nodeid == local_nodeid ? "local" : "remote");
 /*  Shouldn't be required...
     update_member(
  	ais_msg->sender.id, membership_seq, -1, 0, ais_msg->sender.uname, NULL);
 */
 
     if (ais_msg->host.size == 0 || ais_str_eq(ais_msg->host.uname, local_uname)) {
         route_ais_message(ais_msg, FALSE);
 
     } else {
         ais_trace("Discarding Msg[%d] (dest=%s:%s, from=%s:%s)",
                   ais_msg->id, ais_dest(&(ais_msg->host)),
                   msg_type2text(ais_msg->host.type),
                   ais_dest(&(ais_msg->sender)), msg_type2text(ais_msg->sender.type));
     }
 }
 
 void
 pcmk_cluster_id_swab(void *msg)
 {
     struct crm_identify_msg_s *ais_msg = msg;
 
     ais_trace("Performing endian conversion...");
     ais_msg->id = swab32(ais_msg->id);
     ais_msg->pid = swab32(ais_msg->pid);
     ais_msg->votes = swab32(ais_msg->votes);
     ais_msg->processes = swab32(ais_msg->processes);
     ais_msg->born_on = swab64(ais_msg->born_on);
 
     ais_msg->header.size = swab32(ais_msg->header.size);
     ais_msg->header.id = swab32(ais_msg->header.id);
 }
 
 void
 pcmk_cluster_id_callback(ais_void_ptr * message, unsigned int nodeid)
 {
     int changed = 0;
     const struct crm_identify_msg_s *msg = message;
 
     if (nodeid != msg->id) {
         ais_err("Invalid message: Node %u claimed to be node %d", nodeid, msg->id);
         return;
     }
     ais_debug("Node update: %s (%s)", msg->uname, msg->version);
     changed =
         update_member(nodeid, msg->born_on, membership_seq, msg->votes, msg->processes, msg->uname,
                       NULL, msg->version);
 
     if (changed) {
         send_member_notification();
     }
 }
 
 struct res_overlay {
     cs_ipc_header_response_t header __attribute((aligned(8)));
     char buf[4096];
 };
 
 struct res_overlay *res_overlay = NULL;
 
 static void
 send_ipc_ack(void *conn)
 {
     if (res_overlay == NULL) {
         ais_malloc0(res_overlay, sizeof(struct res_overlay));
     }
 
     res_overlay->header.id = CRM_MESSAGE_IPC_ACK;
     res_overlay->header.size = sizeof(cs_ipc_header_response_t);
     res_overlay->header.error = CS_OK;
     pcmk_api->ipc_response_send(conn, res_overlay, res_overlay->header.size);
 }
 
 /* local callbacks */
 void
 pcmk_ipc(void *conn, ais_void_ptr * msg)
 {
     AIS_Message *mutable;
     int type = 0;
     gboolean transient = TRUE;
     const AIS_Message *ais_msg = (const AIS_Message *)msg;
     void *async_conn = conn;
 
     ais_trace("Message from client %p", conn);
 
     if (check_message_sanity(msg, ((const AIS_Message *)msg)->data) == FALSE) {
         /* The message is corrupted - ignore */
         send_ipc_ack(conn);
         msg = NULL;
         return;
     }
 
     /* Make a copy of the message here and ACK it
      * The message is only valid until a response is sent
      * but the response must also be sent _before_ we send anything else
      */
 
     mutable = ais_msg_copy(ais_msg);
     AIS_ASSERT(check_message_sanity(mutable, mutable->data));
 
     type = mutable->sender.type;
     ais_trace
         ("type: %d local: %d conn: %p host type: %d ais: %d sender pid: %d child pid: %d size: %d",
          type, mutable->host.local, pcmk_children[type].conn, mutable->host.type, crm_msg_ais,
          mutable->sender.pid, pcmk_children[type].pid, ((int)SIZEOF(pcmk_children)));
 
     if (type > crm_msg_none && type < SIZEOF(pcmk_children)) {
         /* known child process */
         transient = FALSE;
     }
 #if 0
     /* If this check fails, the order of pcmk_children probably
      *   doesn't match that of the crm_ais_msg_types enum
      */
     AIS_CHECK(transient || mutable->sender.pid == pcmk_children[type].pid,
               ais_err("Sender: %d, child[%d]: %d", mutable->sender.pid, type,
                       pcmk_children[type].pid);
               ais_free(mutable);
               return);
 #endif
 
     if (transient == FALSE
         && type > crm_msg_none
         && mutable->host.local
         && pcmk_children[type].conn == NULL && mutable->host.type == crm_msg_ais) {
         AIS_CHECK(mutable->sender.type != mutable->sender.pid,
                   ais_err("Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type));
 
         ais_info("Recorded connection %p for %s/%d",
                  conn, pcmk_children[type].name, pcmk_children[type].pid);
         pcmk_children[type].conn = conn;
         pcmk_children[type].async_conn = async_conn;
 
         /* Make sure they have the latest membership */
         if (pcmk_children[type].flags & crm_flag_members) {
             char *update = pcmk_generate_membership_data();
 
             g_hash_table_replace(membership_notify_list, async_conn, async_conn);
             ais_info("Sending membership update " U64T " to %s",
                      membership_seq, pcmk_children[type].name);
             send_client_msg(async_conn, crm_class_members, crm_msg_none, update);
         }
 
     } else if (transient) {
         AIS_CHECK(mutable->sender.type == mutable->sender.pid,
                   ais_err("Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type));
         g_hash_table_replace(ipc_client_list, async_conn, GUINT_TO_POINTER(mutable->sender.pid));
     }
 
     mutable->sender.id = local_nodeid;
     mutable->sender.size = local_uname_len;
     memset(mutable->sender.uname, 0, MAX_NAME);
     memcpy(mutable->sender.uname, local_uname, mutable->sender.size);
 
     route_ais_message(mutable, TRUE);
     send_ipc_ack(conn);
     msg = NULL;
     ais_free(mutable);
 }
 
 int
 pcmk_shutdown(void)
 {
     int lpc = 0;
     static int phase = 0;
     static int max_wait = 0;
     static time_t next_log = 0;
     static int max = SIZEOF(pcmk_children);
 
     if (use_mcp) {
         if (pcmk_children[crm_msg_crmd].conn || pcmk_children[crm_msg_stonith_ng].conn) {
             time_t now = time(NULL);
 
             if (now > next_log) {
                 next_log = now + 300;
                 ais_notice
                     ("Preventing Corosync shutdown.  Please ensure Pacemaker is stopped first.");
             }
             return -1;
         }
         ais_notice("Unloading Pacemaker plugin");
         return 0;
     }
 
     if (phase == 0) {
         ais_notice("Shuting down Pacemaker");
         phase = max;
     }
 
     wait_active = FALSE;        /* stop the wait loop */
 
     for (; phase > 0; phase--) {
         /* dont stop anything with start_seq < 1 */
 
         for (lpc = max - 1; lpc >= 0; lpc--) {
             if (phase != pcmk_children[lpc].start_seq) {
                 continue;
             }
 
             if (pcmk_children[lpc].pid) {
                 pid_t pid = 0;
                 int status = 0;
                 time_t now = time(NULL);
 
                 if (pcmk_children[lpc].respawn) {
                     max_wait = 5;       /* 5 * 30s = 2.5 minutes... plenty once the crmd is gone */
                     next_log = now + 30;
                     pcmk_children[lpc].respawn = FALSE;
                     stop_child(&(pcmk_children[lpc]), SIGTERM);
                 }
 
                 pid = wait4(pcmk_children[lpc].pid, &status, WNOHANG, NULL);
                 if (pid < 0) {
                     ais_perror("Call to wait4(%s/%d) failed - treating it as stopped",
                                pcmk_children[lpc].name, pcmk_children[lpc].pid);
 
                 } else if (pid == 0) {
                     if (now >= next_log) {
                         max_wait--;
                         next_log = now + 30;
                         ais_notice("Still waiting for %s (pid=%d, seq=%d) to terminate...",
                                    pcmk_children[lpc].name, pcmk_children[lpc].pid,
                                    pcmk_children[lpc].start_seq);
                         if (max_wait <= 0 && phase < pcmk_children[crm_msg_crmd].start_seq) {
                             ais_err("Child %s taking too long to terminate, sending SIGKILL",
                                     pcmk_children[lpc].name);
                             stop_child(&(pcmk_children[lpc]), SIGKILL);
                         }
                     }
                     /* Return control to corosync */
                     return -1;
                 }
             }
 
             /* cleanup */
             ais_notice("%s confirmed stopped", pcmk_children[lpc].name);
             pcmk_children[lpc].async_conn = NULL;
             pcmk_children[lpc].conn = NULL;
             pcmk_children[lpc].pid = 0;
         }
     }
 
     send_cluster_id();
     ais_notice("Shutdown complete");
     /* TODO: Add back the logsys flush call once its written */
 
     return 0;
 }
 
 struct member_loop_data {
     char *string;
 };
 
 static void
 member_vote_count_fn(gpointer key, gpointer value, gpointer user_data)
 {
     crm_node_t *node = value;
 
     if (ais_str_eq(CRM_NODE_MEMBER, node->state)) {
         plugin_has_votes += node->votes;
     }
 }
 
 void
 member_loop_fn(gpointer key, gpointer value, gpointer user_data)
 {
     crm_node_t *node = value;
     struct member_loop_data *data = user_data;
 
     ais_trace("Dumping node %u", node->id);
     data->string = append_member(data->string, node);
 }
 
 char *
 pcmk_generate_membership_data(void)
 {
     int size = 0;
     struct member_loop_data data;
 
     size = 256;
     ais_malloc0(data.string, size);
 
     /* Ensure the list of active processes is up-to-date */
     update_member(local_nodeid, 0, 0, -1, get_process_list(), local_uname, CRM_NODE_MEMBER, NULL);
 
     plugin_has_votes = 0;
     g_hash_table_foreach(membership_list, member_vote_count_fn, NULL);
     if (plugin_has_votes > plugin_expected_votes) {
         update_expected_votes(plugin_has_votes);
     }
 
     snprintf(data.string, size,
              "<nodes id=\"" U64T "\" quorate=\"%s\" expected=\"%u\" actual=\"%u\">",
              membership_seq, plugin_has_quorum()? "true" : "false",
              plugin_expected_votes, plugin_has_votes);
 
     g_hash_table_foreach(membership_list, member_loop_fn, &data);
     size = strlen(data.string);
     data.string = realloc(data.string, size + 9);       /* 9 = </nodes> + nul */
     sprintf(data.string + size, "</nodes>");
     return data.string;
 }
 
 void
 pcmk_nodes(void *conn, ais_void_ptr * msg)
 {
     char *data = pcmk_generate_membership_data();
     void *async_conn = conn;
 
     /* send the ACK before we send any other messages
      * - but after we no longer need to access the message
      */
     send_ipc_ack(conn);
     msg = NULL;
 
     if (async_conn) {
         send_client_msg(async_conn, crm_class_members, crm_msg_none, data);
     }
     ais_free(data);
 }
 
 void
 pcmk_remove_member(void *conn, ais_void_ptr * msg)
 {
     const AIS_Message *ais_msg = msg;
     char *data = get_ais_data(ais_msg);
 
     send_ipc_ack(conn);
     msg = NULL;
 
     if (data != NULL) {
         char *bcast = ais_concat("remove-peer", data, ':');
 
         send_plugin_msg(crm_msg_ais, NULL, bcast);
         ais_info("Sent: %s", bcast);
         ais_free(bcast);
     }
 
     ais_free(data);
 }
 
 static void
 send_quorum_details(void *conn)
 {
     int size = 256;
     char *data = NULL;
 
     ais_malloc0(data, size);
 
     snprintf(data, size, "<quorum id=\"" U64T "\" quorate=\"%s\" expected=\"%u\" actual=\"%u\"/>",
              membership_seq, plugin_has_quorum()? "true" : "false",
              plugin_expected_votes, plugin_has_votes);
 
     send_client_msg(conn, crm_class_quorum, crm_msg_none, data);
     ais_free(data);
 }
 
 void
 pcmk_quorum(void *conn, ais_void_ptr * msg)
 {
     char *dummy = NULL;
     const AIS_Message *ais_msg = msg;
     char *data = get_ais_data(ais_msg);
 
     send_ipc_ack(conn);
     msg = NULL;
 
     /* Make sure the current number of votes is accurate */
     dummy = pcmk_generate_membership_data();
     ais_free(dummy);
 
     /* Calls without data just want the current quorum details */
     if (data != NULL && strlen(data) > 0) {
         int value = ais_get_int(data, NULL);
 
         update_expected_votes(value);
     }
 
     send_quorum_details(conn);
     ais_free(data);
 }
 
 void
 pcmk_notify(void *conn, ais_void_ptr * msg)
 {
     const AIS_Message *ais_msg = msg;
     char *data = get_ais_data(ais_msg);
     void *async_conn = conn;
 
     int enable = 0;
     int sender = ais_msg->sender.pid;
 
     send_ipc_ack(conn);
     msg = NULL;
 
     if (ais_str_eq("true", data)) {
         enable = 1;
     }
 
     ais_info("%s node notifications for child %d (%p)",
              enable ? "Enabling" : "Disabling", sender, async_conn);
     if (enable) {
         g_hash_table_replace(membership_notify_list, async_conn, async_conn);
     } else {
         g_hash_table_remove(membership_notify_list, async_conn);
     }
     ais_free(data);
 }
 
 void
 pcmk_nodeid(void *conn, ais_void_ptr * msg)
 {
     static int counter = 0;
     struct crm_ais_nodeid_resp_s resp;
 
     ais_trace("Sending local nodeid: %d to %p[%d]", local_nodeid, conn, counter);
 
     resp.header.id = crm_class_nodeid;
     resp.header.size = sizeof(struct crm_ais_nodeid_resp_s);
     resp.header.error = CS_OK;
     resp.id = local_nodeid;
     resp.counter = counter++;
     memset(resp.uname, 0, MAX_NAME);
     memcpy(resp.uname, local_uname, local_uname_len);
     memset(resp.cname, 0, MAX_NAME);
     memcpy(resp.cname, local_cname, local_cname_len);
 
     pcmk_api->ipc_response_send(conn, &resp, resp.header.size);
 }
 
 static gboolean
 ghash_send_update(gpointer key, gpointer value, gpointer data)
 {
     if (send_client_msg(value, crm_class_members, crm_msg_none, data) != 0) {
         /* remove it */
         return TRUE;
     }
     return FALSE;
 }
 
 void
 send_member_notification(void)
 {
     char *update = pcmk_generate_membership_data();
 
     ais_info("Sending membership update " U64T " to %d children",
              membership_seq, g_hash_table_size(membership_notify_list));
 
     g_hash_table_foreach_remove(membership_notify_list, ghash_send_update, update);
     ais_free(update);
 }
 
 gboolean
 check_message_sanity(const AIS_Message * msg, const char *data)
 {
     gboolean sane = TRUE;
     gboolean repaired = FALSE;
     int dest = msg->host.type;
     int tmp_size = msg->header.size - sizeof(AIS_Message);
 
     if (sane && msg->header.size == 0) {
         ais_err("Message with no size");
         sane = FALSE;
     }
 
     if (sane && msg->header.error != CS_OK) {
         ais_err("Message header contains an error: %d", msg->header.error);
         sane = FALSE;
     }
 
     AIS_CHECK(msg->header.size > sizeof(AIS_Message),
               ais_err("Message %d size too small: %d < %zu",
                       msg->header.id, msg->header.size, sizeof(AIS_Message));
               return FALSE);
 
     if (sane && ais_data_len(msg) != tmp_size) {
         ais_warn("Message payload size is incorrect: expected %d, got %d", ais_data_len(msg),
                  tmp_size);
         sane = TRUE;
     }
 
     if (sane && ais_data_len(msg) == 0) {
         ais_err("Message with no payload");
         sane = FALSE;
     }
 
     if (sane && data && msg->is_compressed == FALSE) {
         int str_size = strlen(data) + 1;
 
         if (ais_data_len(msg) != str_size) {
             int lpc = 0;
 
             ais_err("Message payload is corrupted: expected %d bytes, got %d",
                     ais_data_len(msg), str_size);
             sane = FALSE;
             for (lpc = (str_size - 10); lpc < msg->size; lpc++) {
                 if (lpc < 0) {
                     lpc = 0;
                 }
                 ais_trace("bad_data[%d]: %d / '%c'", lpc, data[lpc], data[lpc]);
             }
         }
     }
 
     if (sane == FALSE) {
         AIS_CHECK(sane,
                   ais_err
                   ("Invalid message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
                    msg->id, ais_dest(&(msg->host)), msg_type2text(dest), ais_dest(&(msg->sender)),
                    msg_type2text(msg->sender.type), msg->sender.pid, msg->is_compressed,
                    ais_data_len(msg), msg->header.size));
 
     } else if (repaired) {
         ais_err
             ("Repaired message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
              msg->id, ais_dest(&(msg->host)), msg_type2text(dest), ais_dest(&(msg->sender)),
              msg_type2text(msg->sender.type), msg->sender.pid, msg->is_compressed,
              ais_data_len(msg), msg->header.size);
     } else {
         ais_trace
             ("Verified message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
              msg->id, ais_dest(&(msg->host)), msg_type2text(dest), ais_dest(&(msg->sender)),
              msg_type2text(msg->sender.type), msg->sender.pid, msg->is_compressed,
              ais_data_len(msg), msg->header.size);
     }
     return sane;
 }
 
 static int delivered_transient = 0;
 static void
 deliver_transient_msg(gpointer key, gpointer value, gpointer user_data)
 {
     int pid = GPOINTER_TO_INT(value);
     AIS_Message *mutable = user_data;
 
     if (pid == mutable->host.type) {
         int rc = send_client_ipc(key, mutable);
 
         delivered_transient++;
 
         ais_info("Sent message to %s.%d (rc=%d)", ais_dest(&(mutable->host)), pid, rc);
         if (rc != 0) {
             ais_warn("Sending message to %s.%d failed (rc=%d)",
                      ais_dest(&(mutable->host)), pid, rc);
             log_ais_message(LOG_DEBUG, mutable);
         }
     }
 }
 
 gboolean
 route_ais_message(const AIS_Message * msg, gboolean local_origin)
 {
     int rc = 0;
     int dest = msg->host.type;
     const char *reason = "unknown";
     AIS_Message *mutable = ais_msg_copy(msg);
     static int service_id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 0);
 
     ais_trace("Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d)",
               mutable->id, ais_dest(&(mutable->host)), msg_type2text(dest),
               ais_dest(&(mutable->sender)), msg_type2text(mutable->sender.type),
               mutable->sender.pid, local_origin ? "false" : "true", ais_data_len((mutable)));
 
     if (local_origin == FALSE) {
         if (mutable->host.size == 0 || ais_str_eq(local_uname, mutable->host.uname)) {
             mutable->host.local = TRUE;
         }
     }
 
     if (check_message_sanity(mutable, mutable->data) == FALSE) {
         /* Dont send this message to anyone */
         rc = 1;
         goto bail;
     }
 
     if (mutable->host.local) {
         void *conn = NULL;
         const char *lookup = NULL;
         int children_index = 0;
 
         if (dest == crm_msg_ais) {
             process_ais_message(mutable);
             goto bail;
 
         } else if (dest == crm_msg_lrmd) {
             /* lrmd messages are routed via the crm */
             dest = crm_msg_crmd;
 
         } else if (dest == crm_msg_te) {
             /* te messages are routed via the crm */
             dest = crm_msg_crmd;
 
         } else if (dest >= SIZEOF(pcmk_children)) {
             /* Transient client */
 
             delivered_transient = 0;
             g_hash_table_foreach(ipc_client_list, deliver_transient_msg, mutable);
             if (delivered_transient) {
                 ais_trace("Sent message to %d transient clients: %d", delivered_transient, dest);
                 goto bail;
 
             } else {
                 /* try the crmd */
                 ais_trace("Sending message to transient client %d via crmd", dest);
                 dest = crm_msg_crmd;
             }
 
         } else if (dest == 0) {
             ais_err("Invalid destination: %d", dest);
             log_ais_message(LOG_ERR, mutable);
             log_printf(LOG_ERR, "%s", get_ais_data(mutable));
             rc = 1;
             goto bail;
         }
 
         lookup = msg_type2text(dest);
 
         if (dest == crm_msg_pe && ais_str_eq(pcmk_children[7].name, lookup)) {
             children_index = 7;
 
         } else {
             children_index = dest;
         }
 
         conn = pcmk_children[children_index].async_conn;
 
         if (mutable->header.id == service_id) {
             mutable->header.id = 0;     /* reset this back to zero for IPC messages */
 
         } else if (mutable->header.id != 0) {
             ais_err("reset header id back to zero from %d", mutable->header.id);
             mutable->header.id = 0;     /* reset this back to zero for IPC messages */
         }
 
         reason = "ipc delivery failed";
         rc = send_client_ipc(conn, mutable);
 
     } else if (local_origin) {
         /* forward to other hosts */
         ais_trace("Forwarding to cluster");
         reason = "cluster delivery failed";
         rc = send_plugin_msg_raw(mutable);
     }
 
     if (rc != 0) {
         ais_warn("Sending message to %s.%s failed: %s (rc=%d)",
                  ais_dest(&(mutable->host)), msg_type2text(dest), reason, rc);
         log_ais_message(LOG_DEBUG, mutable);
     }
 
   bail:
     ais_free(mutable);
     return rc == 0 ? TRUE : FALSE;
 }
 
 int
 send_plugin_msg_raw(const AIS_Message * ais_msg)
 {
     int rc = 0;
     struct iovec iovec;
     static uint32_t msg_id = 0;
     AIS_Message *mutable = ais_msg_copy(ais_msg);
 
     AIS_ASSERT(local_nodeid != 0);
     AIS_ASSERT(ais_msg->header.size == (sizeof(AIS_Message) + ais_data_len(ais_msg)));
 
     if (mutable->id == 0) {
         msg_id++;
         AIS_CHECK(msg_id != 0 /* detect wrap-around */ ,
                   msg_id++; ais_err("Message ID wrapped around"));
         mutable->id = msg_id;
     }
 
     mutable->header.error = CS_OK;
     mutable->header.id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 0);
 
     mutable->sender.id = local_nodeid;
     mutable->sender.size = local_uname_len;
     memset(mutable->sender.uname, 0, MAX_NAME);
     memcpy(mutable->sender.uname, local_uname, mutable->sender.size);
 
     iovec.iov_base = (char *)mutable;
     iovec.iov_len = mutable->header.size;
 
     ais_trace("Sending message (size=%u)", (unsigned int)iovec.iov_len);
     rc = pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE);
 
     if (rc == 0 && mutable->is_compressed == FALSE) {
         ais_trace("Message sent: %.80s", mutable->data);
     }
 
     AIS_CHECK(rc == 0, ais_err("Message not sent (%d): %.120s", rc, mutable->data));
 
     ais_free(mutable);
     return rc;
 }
 
 #define min(x,y) (x)<(y)?(x):(y)
 
 void
 send_cluster_id(void)
 {
     int rc = 0;
     int len = 0;
     time_t now = time(NULL);
     struct iovec iovec;
     struct crm_identify_msg_s *msg = NULL;
 
     static time_t started = 0;
     static uint64_t first_seq = 0;
 
     AIS_ASSERT(local_nodeid != 0);
 
     if (started == 0) {
         started = now;
         first_seq = membership_seq;
     }
 
     if (local_born_on == 0) {
         if (started + 15 < now) {
             ais_debug("Born-on set to: " U64T " (age)", first_seq);
             local_born_on = first_seq;
 
         } else if (have_reliable_membership_id) {
             ais_debug("Born-on set to: " U64T " (peer)", membership_seq);
             local_born_on = membership_seq;
 
         } else {
             ais_debug("Leaving born-on unset: " U64T, membership_seq);
         }
     }
 
     ais_malloc0(msg, sizeof(struct crm_identify_msg_s));
     msg->header.size = sizeof(struct crm_identify_msg_s);
 
     msg->id = local_nodeid;
     /* msg->header.error = CS_OK; */
     msg->header.id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 1);
 
     len = min(local_uname_len, MAX_NAME - 1);
     memset(msg->uname, 0, MAX_NAME);
     memcpy(msg->uname, local_uname, len);
 
     len = min(strlen(VERSION), MAX_NAME - 1);
     memset(msg->version, 0, MAX_NAME);
     memcpy(msg->version, VERSION, len);
 
     msg->votes = 1;
     msg->pid = getpid();
     msg->processes = get_process_list();
     msg->born_on = local_born_on;
 
     ais_debug("Local update: id=%u, born=" U64T ", seq=" U64T "",
               local_nodeid, local_born_on, membership_seq);
     update_member(local_nodeid, local_born_on, membership_seq, msg->votes, msg->processes, NULL,
                   NULL, VERSION);
 
     iovec.iov_base = (char *)msg;
     iovec.iov_len = msg->header.size;
 
     rc = pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE);
 
     AIS_CHECK(rc == 0, ais_err("Message not sent (%d)", rc));
 
     ais_free(msg);
 }
 
 static gboolean
 ghash_send_removal(gpointer key, gpointer value, gpointer data)
 {
     send_quorum_details(value);
     if (send_client_msg(value, crm_class_rmpeer, crm_msg_none, data) != 0) {
         /* remove it */
         return TRUE;
     }
     return FALSE;
 }
 
 void
 ais_remove_peer(char *node_id)
 {
     uint32_t id = ais_get_int(node_id, NULL);
     crm_node_t *node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id));
 
     if (node == NULL) {
         ais_info("Peer %u is unknown", id);
 
     } else if (ais_str_eq(CRM_NODE_MEMBER, node->state)) {
         ais_warn("Peer %u/%s is still active", id, node->uname);
 
     } else if (g_hash_table_remove(membership_list, GUINT_TO_POINTER(id))) {
         plugin_expected_votes--;
         ais_notice("Removed dead peer %u from the membership list", id);
         ais_info("Sending removal of %u to %d children",
                  id, g_hash_table_size(membership_notify_list));
 
         g_hash_table_foreach_remove(membership_notify_list, ghash_send_removal, node_id);
 
     } else {
         ais_warn("Peer %u/%s was not removed", id, node->uname);
     }
 }
 
 void
 ais_remove_peer_by_name(const char *node_name)
 {
     GHashTableIter iter;
     gpointer key = 0;
     crm_node_t *node = NULL;
     GList *node_list = NULL;
 
     g_hash_table_iter_init(&iter, membership_list);
 
     while (g_hash_table_iter_next(&iter, &key, (void **)&node)) {
         if (ais_str_eq(node_name, node->uname)) {
             uint32_t node_id = GPOINTER_TO_UINT(key);
             char *node_id_s = NULL;
 
             ais_malloc0(node_id_s, 32);
             snprintf(node_id_s, 31, "%u", node_id);
             node_list = g_list_append(node_list, node_id_s);
         }
     }
 
     if (node_list) {
         GList *gIter = NULL;
 
         for (gIter = node_list; gIter != NULL; gIter = gIter->next) {
             char *node_id_s = gIter->data;
 
             ais_remove_peer(node_id_s);
         }
         g_list_free_full(node_list, free);
 
     } else {
         ais_warn("Peer %s is unkown", node_name);
     }
 }
 
 gboolean
 process_ais_message(const AIS_Message * msg)
 {
     int len = ais_data_len(msg);
     char *data = get_ais_data(msg);
 
     do_ais_log(LOG_DEBUG,
                "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s",
                msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type),
                ais_dest(&(msg->sender)), msg_type2text(msg->sender.type),
                msg->sender.pid,
                msg->sender.uname == local_uname ? "false" : "true", ais_data_len(msg), data);
 
     if (data && len > 12 && strncmp("remove-peer:", data, 12) == 0) {
         char *node = data + 12;
 
         ais_remove_peer_by_name(node);
     }
 
     ais_free(data);
     return TRUE;
 }
 
 static void
 member_dump_fn(gpointer key, gpointer value, gpointer user_data)
 {
     crm_node_t *node = value;
 
     ais_info(" node id:%u, uname=%s state=%s processes=%.16x born=" U64T " seen=" U64T
              " addr=%s version=%s", node->id, node->uname ? node->uname : "-unknown-", node->state,
              node->processes, node->born, node->last_seen, node->addr ? node->addr : "-unknown-",
              node->version ? node->version : "-unknown-");
 }
 
 void
 pcmk_exec_dump(void)
 {
     /* Called after SIG_USR2 */
     process_ais_conf();
     ais_info("Local id: %u, uname: %s, born: " U64T, local_nodeid, local_uname, local_born_on);
     ais_info("Membership id: " U64T ", quorate: %s, expected: %u, actual: %u",
              membership_seq, plugin_has_quorum()? "true" : "false",
              plugin_expected_votes, plugin_has_votes);
 
     g_hash_table_foreach(membership_list, member_dump_fn, NULL);
 }
diff --git a/lib/ais/utils.h b/lib/ais/utils.h
index f4a8fd7fdf..5cc4ecaf27 100644
--- a/lib/ais/utils.h
+++ b/lib/ais/utils.h
@@ -1,242 +1,242 @@
 /*
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #ifndef AIS_CRM_UTILS__H
 #  define AIS_CRM_UTILS__H
 
 #  include <syslog.h>
 
 #  ifdef AIS_WHITETANK
 #    include <openais/service/objdb.h>
 #    include <openais/service/print.h>
 
 #    define OPENAIS_EXTERNAL_SERVICE insane_ais_header_hack_in__totem_h
 #    include <openais/saAis.h>
 #    include <openais/service/swab.h>
 #    include <openais/totem/totempg.h>
 #    include <openais/service/service.h>
 #    include <openais/lcr/lcr_comp.h>
 #    include <openais/lcr/lcr_ifact.h>
 #    include <openais/service/config.h>
 #    define COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED OPENAIS_FLOW_CONTROL_NOT_REQUIRED
 
 /* New names for old things */
 typedef unsigned int hdb_handle_t;
 
 #    define corosync_api_v1 objdb_iface_ver0
 #    define corosync_lib_handler openais_lib_handler
 #    define corosync_exec_handler openais_exec_handler
 #    define corosync_service_engine openais_service_handler
 
 extern int openais_response_send(void *conn, void *msg, int mlen);
 extern int openais_dispatch_send(void *conn, void *msg, int mlen);
 
 #  endif
 
 #  ifdef SUPPORT_COROSYNC
 #    include <corosync/corodefs.h>
 #    include <corosync/swab.h>
 #    include <corosync/hdb.h>
 
 #    include <corosync/engine/objdb.h>
 #    include <corosync/engine/coroapi.h>
 #    include <corosync/engine/logsys.h>
 
 #    include <corosync/lcr/lcr_comp.h>
 LOGSYS_DECLARE_SUBSYS("pcmk");
 #  endif
 
 /* #include "plugin.h" */
 #  define 	SIZEOF(a)   (sizeof(a) / sizeof(a[0]))
 
 typedef struct crm_child_s {
     int pid;
     long flag;
     long flags;
     int start_seq;
     int respawn_count;
     gboolean respawn;
     const char *name;
     const char *uid;
     const char *command;
     void *conn;
     void *async_conn;
 
 } crm_child_t;
 
 extern void destroy_ais_node(gpointer data);
 extern void delete_member(uint32_t id, const char *uname);
 extern int update_member(unsigned int id, uint64_t born, uint64_t seq, int32_t votes,
                          uint32_t procs, const char *uname, const char *state, const char *version);
 
 extern const char *member_uname(uint32_t id);
 extern char *append_member(char *data, crm_node_t * node);
 extern void member_loop_fn(gpointer key, gpointer value, gpointer user_data);
 
 extern gboolean stop_child(crm_child_t * child, int signal);
 extern gboolean spawn_child(crm_child_t * child);
 
 extern void swap_sender(AIS_Message * msg);
 extern char *get_ais_data(const AIS_Message * msg);
 
 extern gboolean route_ais_message(const AIS_Message * msg, gboolean local);
 extern gboolean process_ais_message(const AIS_Message * msg);
 
 extern int send_plugin_msg(enum crm_ais_msg_types type, const char *host, const char *data);
 extern int send_client_msg(void *conn, enum crm_ais_msg_class class,
                            enum crm_ais_msg_types type, const char *data);
 extern void send_member_notification(void);
 extern void log_ais_message(int level, const AIS_Message * msg);
 
 extern hdb_handle_t config_find_init(struct corosync_api_v1 *config, char *name);
 extern hdb_handle_t config_find_next(struct corosync_api_v1 *config, char *name,
                                      hdb_handle_t top_handle);
 extern void config_find_done(struct corosync_api_v1 *config, hdb_handle_t local_handle);
 extern int get_config_opt(struct corosync_api_v1 *config,
                           hdb_handle_t object_service_handle,
                           char *key, char **value, const char *fallback);
 
 extern int ais_get_boolean(const char *s);
 extern long long ais_get_int(const char *text, char **end_text);
 extern char *ais_concat(const char *prefix, const char *suffix, char join);
 extern int send_client_ipc(void *conn, const AIS_Message * ais_msg);
 
 extern GHashTable *membership_list;
 extern pthread_t crm_wait_thread;
 extern int plugin_log_level;
 extern char *local_uname;
 extern int local_uname_len;
 extern unsigned int local_nodeid;
 
 static inline const char *
 level2char(int level)
 {
     switch (level) {
         case LOG_CRIT:
             return "CRIT";
         case LOG_ERR:
             return "ERROR";
         case LOG_WARNING:
             return "WARN";
         case LOG_NOTICE:
             return "notice";
         case LOG_INFO:
             return "info";
     }
     return "debug";
 }
 
 #  define do_ais_log(level, fmt, args...) do {				\
 	if(plugin_log_level < (level)) {				\
 	    continue;							\
 	} else if((level) > LOG_DEBUG) {				\
 	    log_printf(LOG_DEBUG, "debug%d: %s: " fmt,			\
-		       level-LOG_INFO, __PRETTY_FUNCTION__ , ##args);	\
+		       level-LOG_INFO, __FUNCTION__ , ##args);	\
 	} else {							\
 	    log_printf(level, "%s: %s: " fmt, level2char(level),	\
-		       __PRETTY_FUNCTION__ , ##args);			\
+		       __FUNCTION__ , ##args);			\
 	}								\
     } while(0)
 
 #  define ais_perror(fmt, args...) log_printf(				\
 	LOG_ERR, "%s: " fmt ": (%d) %s",				\
-	__PRETTY_FUNCTION__ , ##args, errno, strerror(errno))
+	__FUNCTION__ , ##args, errno, strerror(errno))
 
 #  define ais_crit(fmt, args...)    do_ais_log(LOG_CRIT,    fmt , ##args)
 #  define ais_err(fmt, args...)     do_ais_log(LOG_ERR,     fmt , ##args)
 #  define ais_warn(fmt, args...)    do_ais_log(LOG_WARNING, fmt , ##args)
 #  define ais_notice(fmt, args...)  do_ais_log(LOG_NOTICE,  fmt , ##args)
 #  define ais_info(fmt, args...)    do_ais_log(LOG_INFO,    fmt , ##args)
 #  define ais_debug(fmt, args...)   do_ais_log(LOG_DEBUG,   fmt , ##args)
 #  define ais_trace(fmt, args...)   do_ais_log(LOG_DEBUG+1, fmt , ##args)
 
 #  define ais_malloc0(malloc_obj, length) do {				\
 	malloc_obj = malloc(length);					\
 	if(malloc_obj == NULL) {					\
 	    abort();							\
 	}								\
 	memset(malloc_obj, 0, length);					\
     } while(0)
 
 #  define ais_free(obj) do {			\
 	if(obj) {				\
 	    free(obj);				\
 	    obj = NULL;				\
 	}					\
     } while(0)
 
 #  define AIS_ASSERT(expr) if((expr) == FALSE) {				\
 	ais_crit("Assertion failure line %d: %s", __LINE__, #expr);	\
 	abort();							\
     }
 
 #  define AIS_CHECK(expr, failure_action) if((expr) == FALSE) {		\
 	int p = fork();							\
 	if(p == 0) { abort(); }						\
 	ais_err("Child %d spawned to record non-fatal assertion failure line %d: %s", p, __LINE__, #expr); \
 	failure_action;							\
     }
 
 static inline char *
 ais_strdup(const char *src)
 {
     char *dup = NULL;
 
     if (src == NULL) {
         return NULL;
     }
     ais_malloc0(dup, strlen(src) + 1);
     return strcpy(dup, src);
 }
 
 static inline gboolean
 ais_str_eq(const char *a, const char *b)
 {
     if (a == NULL || b == NULL) {
         return FALSE;
 
     } else if (a == b) {
         return TRUE;
 
     } else if (strcasecmp(a, b) == 0) {
         return TRUE;
     }
     return FALSE;
 }
 
 static inline int
 libais_connection_active(void *conn)
 {
     if (conn != NULL) {
         return TRUE;
     }
     return FALSE;
 }
 
 struct pcmk_env_s {
     const char *debug;
     const char *syslog;
     const char *logfile;
     const char *use_logd;
     const char *quorum;
 };
 
 extern struct pcmk_env_s pcmk_env;
 extern int pcmk_user_lookup(const char *name, uid_t * uid, gid_t * gid);
 
 #endif
diff --git a/lib/common/logging.c b/lib/common/logging.c
index 90387567b4..e34fc1e35a 100644
--- a/lib/common/logging.c
+++ b/lib/common/logging.c
@@ -1,1162 +1,1162 @@
 /*
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  *
  * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
 
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
 #include <limits.h>
 #include <ctype.h>
 #include <pwd.h>
 #include <grp.h>
 #include <time.h>
 #include <libgen.h>
 #include <signal.h>
 #include <bzlib.h>
 
 #include <qb/qbdefs.h>
 
 #include <crm/crm.h>
 #include <crm/common/mainloop.h>
 
 unsigned int crm_log_priority = LOG_NOTICE;
 unsigned int crm_log_level = LOG_INFO;
 static gboolean crm_tracing_enabled(void);
 unsigned int crm_trace_nonlog = 0;
 bool crm_is_daemon = 0;
 
 #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
 GLogFunc glib_log_default;
 
 static void
 crm_glib_handler(const gchar * log_domain, GLogLevelFlags flags, const gchar * message,
                  gpointer user_data)
 {
     int log_level = LOG_WARNING;
     GLogLevelFlags msg_level = (flags & G_LOG_LEVEL_MASK);
     static struct qb_log_callsite *glib_cs = NULL;
 
     if (glib_cs == NULL) {
-        glib_cs = qb_log_callsite_get(__PRETTY_FUNCTION__, __FILE__, "glib-handler", LOG_DEBUG, __LINE__, crm_trace_nonlog);
+        glib_cs = qb_log_callsite_get(__FUNCTION__, __FILE__, "glib-handler", LOG_DEBUG, __LINE__, crm_trace_nonlog);
     }
 
 
     switch (msg_level) {
         case G_LOG_LEVEL_CRITICAL:
             log_level = LOG_CRIT;
 
             if (crm_is_callsite_active(glib_cs, LOG_DEBUG, 0) == FALSE) {
                 /* log and record how we got here */
-                crm_abort(__FILE__, __PRETTY_FUNCTION__, __LINE__, message, TRUE, TRUE);
+                crm_abort(__FILE__, __FUNCTION__, __LINE__, message, TRUE, TRUE);
             }
             break;
 
         case G_LOG_LEVEL_ERROR:
             log_level = LOG_ERR;
             break;
         case G_LOG_LEVEL_MESSAGE:
             log_level = LOG_NOTICE;
             break;
         case G_LOG_LEVEL_INFO:
             log_level = LOG_INFO;
             break;
         case G_LOG_LEVEL_DEBUG:
             log_level = LOG_DEBUG;
             break;
 
         case G_LOG_LEVEL_WARNING:
         case G_LOG_FLAG_RECURSION:
         case G_LOG_FLAG_FATAL:
         case G_LOG_LEVEL_MASK:
             log_level = LOG_WARNING;
             break;
     }
 
     do_crm_log(log_level, "%s: %s", log_domain, message);
 }
 #endif
 
 #ifndef NAME_MAX
 #  define NAME_MAX 256
 #endif
 
 static void
 crm_trigger_blackbox(int nsig)
 {
     if(nsig == SIGTRAP) {
         /* Turn it on if it wasn't already */
         crm_enable_blackbox(nsig);
     }
     crm_write_blackbox(nsig, NULL);
 }
 
 const char *
 daemon_option(const char *option)
 {
     char env_name[NAME_MAX];
     const char *value = NULL;
 
     snprintf(env_name, NAME_MAX, "PCMK_%s", option);
     value = getenv(env_name);
     if (value != NULL) {
         crm_trace("Found %s = %s", env_name, value);
         return value;
     }
 
     snprintf(env_name, NAME_MAX, "HA_%s", option);
     value = getenv(env_name);
     if (value != NULL) {
         crm_trace("Found %s = %s", env_name, value);
         return value;
     }
 
     crm_trace("Nothing found for %s", option);
     return NULL;
 }
 
 void
 set_daemon_option(const char *option, const char *value)
 {
     char env_name[NAME_MAX];
 
     snprintf(env_name, NAME_MAX, "PCMK_%s", option);
     if (value) {
         crm_trace("Setting %s to %s", env_name, value);
         setenv(env_name, value, 1);
     } else {
         crm_trace("Unsetting %s", env_name);
         unsetenv(env_name);
     }
 
     snprintf(env_name, NAME_MAX, "HA_%s", option);
     if (value) {
         crm_trace("Setting %s to %s", env_name, value);
         setenv(env_name, value, 1);
     } else {
         crm_trace("Unsetting %s", env_name);
         unsetenv(env_name);
     }
 }
 
 gboolean
 daemon_option_enabled(const char *daemon, const char *option)
 {
     const char *value = daemon_option(option);
 
     if (value != NULL && crm_is_true(value)) {
         return TRUE;
 
     } else if (value != NULL && strstr(value, daemon)) {
         return TRUE;
     }
 
     return FALSE;
 }
 
 void
 crm_log_deinit(void)
 {
 #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
     g_log_set_default_handler(glib_log_default, NULL);
 #endif
 }
 
 #define FMT_MAX 256
 static void
 set_format_string(int method, const char *daemon)
 {
     int offset = 0;
     char fmt[FMT_MAX];
 
     if (method > QB_LOG_STDERR) {
         /* When logging to a file */
         struct utsname res;
 
         if (uname(&res) == 0) {
             offset +=
                 snprintf(fmt + offset, FMT_MAX - offset, "%%t [%d] %s %10s: ", getpid(),
                          res.nodename, daemon);
         } else {
             offset += snprintf(fmt + offset, FMT_MAX - offset, "%%t [%d] %10s: ", getpid(), daemon);
         }
     }
 
     if (crm_tracing_enabled() && method >= QB_LOG_STDERR) {
         offset += snprintf(fmt + offset, FMT_MAX - offset, "(%%-12f:%%5l %%g) %%-7p: %%n: ");
     } else {
         offset += snprintf(fmt + offset, FMT_MAX - offset, "%%g %%-7p: %%n: ");
     }
 
     if (method == QB_LOG_SYSLOG) {
         offset += snprintf(fmt + offset, FMT_MAX - offset, "%%b");
     } else {
         offset += snprintf(fmt + offset, FMT_MAX - offset, "\t%%b");
     }
     qb_log_format_set(method, fmt);
 }
 
 gboolean
 crm_add_logfile(const char *filename)
 {
     struct stat parent;
     int fd = 0, rc = 0;
     FILE *logfile = NULL;
     char *parent_dir = NULL;
     char *filename_cp;
 
     static gboolean have_logfile = FALSE;
 
     if (filename == NULL && have_logfile == FALSE) {
         filename = "/var/log/pacemaker.log";
     }
 
     if (filename == NULL) {
         return FALSE;           /* Nothing to do */
     }
 
     /* Check the parent directory */
     filename_cp = strdup(filename);
     parent_dir = dirname(filename_cp);
     rc = stat(parent_dir, &parent);
 
     if (rc != 0) {
         crm_err("Directory '%s' does not exist: logging to '%s' is disabled", parent_dir, filename);
         free(filename_cp);
         return FALSE;
     }
     free(filename_cp);
 
     errno = 0;
     logfile = fopen(filename, "a");
     if(logfile == NULL) {
         crm_err("%s (%d): Logging to '%s' as uid=%u, gid=%u is disabled",
                 pcmk_strerror(errno), errno, filename, geteuid(), getegid());
         return FALSE;
     }
 
     /* Check/Set permissions if we're root */
     if (geteuid() == 0) {
         struct stat st;
         uid_t pcmk_uid = 0;
         gid_t pcmk_gid = 0;
         gboolean fix = FALSE;
         int logfd = fileno(logfile);
 
         rc = fstat(logfd, &st);
         if (rc < 0) {
             crm_perror(LOG_WARNING, "Cannot stat %s", filename);
             fclose(logfile);
             return FALSE;
         }
 
         if(crm_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) == 0) {
             if (st.st_gid != pcmk_gid) {
                 /* Wrong group */
                 fix = TRUE;
             } else if ((st.st_mode & S_IRWXG) != (S_IRGRP | S_IWGRP)) {
                 /* Not read/writable by the correct group */
                 fix = TRUE;
             }
         }
 
         if (fix) {
             rc = fchown(logfd, pcmk_uid, pcmk_gid);
             if (rc < 0) {
                 crm_warn("Cannot change the ownership of %s to user %s and gid %d",
                          filename, CRM_DAEMON_USER, pcmk_gid);
             }
 
             rc = fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
             if (rc < 0) {
                 crm_warn("Cannot change the mode of %s to rw-rw----", filename);
             }
 
             fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n",
                     pcmk_uid, pcmk_gid, filename);
             if (fflush(logfile) < 0 || fsync(logfd) < 0) {
                 crm_err("Couldn't write out logfile: %s", filename);
             }
         }
     }
 
     /* Close and reopen with libqb */
     fclose(logfile);
     fd = qb_log_file_open(filename);
 
     if (fd < 0) {
         crm_perror(LOG_WARNING, "Couldn't send additional logging to %s", filename);
         return FALSE;
     }
 
     crm_notice("Additional logging available in %s", filename);
     qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
     /* qb_log_ctl(fd, QB_LOG_CONF_FILE_SYNC, 1);  Turn on synchronous writes */
 
     /* Enable callsites */
     crm_update_callsites();
     have_logfile = TRUE;
     return TRUE;
 }
 
 static int blackbox_trigger = 0;
 static char *blackbox_file_prefix = NULL;
 
 static void
 blackbox_logger(int32_t t, struct qb_log_callsite *cs, time_t timestamp, const char *msg)
 {
     if(cs && cs->priority < LOG_ERR) {
         crm_write_blackbox(SIGTRAP, cs); /* Bypass the over-dumping logic */
     } else {
         crm_write_blackbox(0, cs);
     }
 }
 
 static void
 crm_control_blackbox(int nsig, bool enable)
 {
     if (blackbox_file_prefix == NULL) {
         pid_t pid = getpid();
 
         blackbox_file_prefix = malloc(NAME_MAX);
         snprintf(blackbox_file_prefix, NAME_MAX, "%s/%s-%d", CRM_BLACKBOX_DIR, crm_system_name, pid);
     }
 
     if (enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
         qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 5 * 1024 * 1024); /* Any size change drops existing entries */
         qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);      /* Setting the size seems to disable it */
 
         crm_notice("Initiated blackbox recorder: %s", blackbox_file_prefix);
 
         /* Save to disk on abnormal termination */
         crm_signal(SIGSEGV, crm_trigger_blackbox);
         crm_signal(SIGABRT, crm_trigger_blackbox);
         crm_signal(SIGILL,  crm_trigger_blackbox);
         crm_signal(SIGBUS,  crm_trigger_blackbox);
 
         crm_update_callsites();
 
         blackbox_trigger = qb_log_custom_open(blackbox_logger, NULL, NULL, NULL);
         qb_log_ctl(blackbox_trigger, QB_LOG_CONF_ENABLED, QB_TRUE);
         crm_trace("Trigger: %d is %d %d", blackbox_trigger,
                   qb_log_ctl(blackbox_trigger, QB_LOG_CONF_STATE_GET, 0), QB_LOG_STATE_ENABLED);
 
         crm_update_callsites();
 
     } else if (!enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
         qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
     }
 }
 
 void
 crm_enable_blackbox(int nsig)
 {
     crm_control_blackbox(nsig, TRUE);
 }
 
 void
 crm_disable_blackbox(int nsig)
 {
     crm_control_blackbox(nsig, FALSE);
 }
 
 void
 crm_write_blackbox(int nsig, struct qb_log_callsite *cs)
 {
     static int counter = 1;
     static time_t last = 0;
 
     char buffer[NAME_MAX];
     time_t now = time(NULL);
 
     if (blackbox_file_prefix == NULL) {
         return;
     }
 
     switch (nsig) {
         case 0:
         case SIGTRAP:
             /* The graceful case - such as assertion failure or user request */
 
             if (nsig == 0 && now == last) {
                 /* Prevent over-dumping */
                 return;
             }
 
             snprintf(buffer, NAME_MAX, "%s.%d", blackbox_file_prefix, counter++);
             if (nsig == SIGTRAP) {
                 crm_notice("Blackbox dump requested, please see %s for contents", buffer);
 
             } else if (cs) {
                 syslog(LOG_NOTICE,
                        "Problem detected at %s:%d (%s), please see %s for additional details",
                        cs->function, cs->lineno, cs->filename, buffer);
             } else {
                 crm_notice("Problem detected, please see %s for additional details", buffer);
             }
 
             last = now;
             qb_log_blackbox_write_to_file(buffer);
 
             /* Flush the existing contents
              * A size change would also work
              */
             qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
             qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
             break;
 
         default:
             /* Do as little as possible, just try to get what we have out
              * We logged the filename when the blackbox was enabled
              */
             crm_signal(nsig, SIG_DFL);
             qb_log_blackbox_write_to_file(blackbox_file_prefix);
             qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
             raise(nsig);
             break;
     }
 }
 
 gboolean
 crm_log_cli_init(const char *entity)
 {
     return crm_log_init(entity, LOG_ERR, FALSE, FALSE, 0, NULL, TRUE);
 }
 
 static const char *
 crm_quark_to_string(uint32_t tag)
 {
     const char *text = g_quark_to_string(tag);
 
     if (text) {
         return text;
     }
     return "";
 }
 
 static void
 crm_log_filter_source(int source, const char *trace_files, const char *trace_fns,
                       const char *trace_fmts, const char *trace_tags, const char *trace_blackbox,
                       struct qb_log_callsite *cs)
 {
     if (qb_log_ctl(source, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
         return;
     } else if (cs->tags != crm_trace_nonlog && source == QB_LOG_BLACKBOX) {
         /* Blackbox gets everything if enabled */
         qb_bit_set(cs->targets, source);
 
     } else if (source == blackbox_trigger && blackbox_trigger > 0) {
         /* Should this log message result in the blackbox being dumped */
         if (cs->priority <= LOG_ERR) {
             qb_bit_set(cs->targets, source);
 
         } else if (trace_blackbox) {
             char *key = g_strdup_printf("%s:%d", cs->function, cs->lineno);
 
             if (strstr(trace_blackbox, key) != NULL) {
                 qb_bit_set(cs->targets, source);
             }
             free(key);
         }
 
     } else if (source == QB_LOG_SYSLOG) {       /* No tracing to syslog */
         if (cs->priority <= crm_log_priority && cs->priority <= crm_log_level) {
             qb_bit_set(cs->targets, source);
         }
         /* Log file tracing options... */
     } else if (cs->priority <= crm_log_level) {
         qb_bit_set(cs->targets, source);
     } else if (trace_files && strstr(trace_files, cs->filename) != NULL) {
         qb_bit_set(cs->targets, source);
     } else if (trace_fns && strstr(trace_fns, cs->function) != NULL) {
         qb_bit_set(cs->targets, source);
     } else if (trace_fmts && strstr(trace_fmts, cs->format) != NULL) {
         qb_bit_set(cs->targets, source);
     } else if (trace_tags
                && cs->tags != 0
                && cs->tags != crm_trace_nonlog && g_quark_to_string(cs->tags) != NULL) {
         qb_bit_set(cs->targets, source);
     }
 }
 
 static void
 crm_log_filter(struct qb_log_callsite *cs)
 {
     int lpc = 0;
     static int need_init = 1;
     static const char *trace_fns = NULL;
     static const char *trace_tags = NULL;
     static const char *trace_fmts = NULL;
     static const char *trace_files = NULL;
     static const char *trace_blackbox = NULL;
 
     if (need_init) {
         need_init = 0;
         trace_fns = getenv("PCMK_trace_functions");
         trace_fmts = getenv("PCMK_trace_formats");
         trace_tags = getenv("PCMK_trace_tags");
         trace_files = getenv("PCMK_trace_files");
         trace_blackbox = getenv("PCMK_trace_blackbox");
 
         if (trace_tags != NULL) {
             uint32_t tag;
             char token[500];
             const char *offset = NULL;
             const char *next = trace_tags;
 
             do {
                 offset = next;
                 next = strchrnul(offset, ',');
                 snprintf(token, 499, "%.*s", (int)(next - offset), offset);
 
                 tag = g_quark_from_string(token);
                 crm_info("Created GQuark %u from token '%s' in '%s'", tag, token, trace_tags);
 
                 if (next[0] != 0) {
                     next++;
                 }
 
             } while (next != NULL && next[0] != 0);
         }
     }
 
     cs->targets = 0;            /* Reset then find targets to enable */
     for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
         crm_log_filter_source(lpc, trace_files, trace_fns, trace_fmts, trace_tags, trace_blackbox,
                               cs);
     }
 }
 
 gboolean
 crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
 {
     gboolean refilter = FALSE;
 
     if (cs == NULL) {
         return FALSE;
     }
 
     if (cs->priority != level) {
         cs->priority = level;
         refilter = TRUE;
     }
 
     if (cs->tags != tags) {
         cs->tags = tags;
         refilter = TRUE;
     }
 
     if (refilter) {
         crm_log_filter(cs);
     }
 
     if (cs->targets == 0) {
         return FALSE;
     }
     return TRUE;
 }
 
 void
 crm_update_callsites(void)
 {
     static gboolean log = TRUE;
 
     if (log) {
         log = FALSE;
         crm_debug
             ("Enabling callsites based on priority=%d, files=%s, functions=%s, formats=%s, tags=%s",
              crm_log_level, getenv("PCMK_trace_files"), getenv("PCMK_trace_functions"),
              getenv("PCMK_trace_formats"), getenv("PCMK_trace_tags"));
     }
     qb_log_filter_fn_set(crm_log_filter);
 }
 
 static gboolean
 crm_tracing_enabled(void)
 {
     if (crm_log_level >= LOG_TRACE) {
         return TRUE;
     } else if (getenv("PCMK_trace_files") || getenv("PCMK_trace_functions")
                || getenv("PCMK_trace_formats") || getenv("PCMK_trace_tags")) {
         return TRUE;
     }
     return FALSE;
 }
 
 static int
 crm_priority2int(const char *name)
 {
     struct syslog_names {
         const char *name;
         int priority;
     };
     static struct syslog_names p_names[] = {
         {"emerg", LOG_EMERG},
         {"alert", LOG_ALERT},
         {"crit", LOG_CRIT},
         {"error", LOG_ERR},
         {"warning", LOG_WARNING},
         {"notice", LOG_NOTICE},
         {"info", LOG_INFO},
         {"debug", LOG_DEBUG},
         {NULL, -1}
     };
     int lpc;
 
     for (lpc = 0; name != NULL && p_names[lpc].name != NULL; lpc++) {
         if (crm_str_eq(p_names[lpc].name, name, TRUE)) {
             return p_names[lpc].priority;
         }
     }
     return crm_log_priority;
 }
 
 gboolean
 crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr,
              int argc, char **argv, gboolean quiet)
 {
     int lpc = 0;
     const char *logfile = daemon_option("debugfile");
     const char *facility = daemon_option("logfacility");
     const char *f_copy = facility;
 
     crm_is_daemon = daemon;
 
     if (crm_trace_nonlog == 0) {
         crm_trace_nonlog = g_quark_from_static_string("Pacemaker non-logging tracepoint");
     }
 
     umask(S_IWGRP | S_IWOTH | S_IROTH);
 
     /* Redirect messages from glib functions to our handler */
 #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
     glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL);
 #endif
 
     /* and for good measure... - this enum is a bit field (!) */
     g_log_set_always_fatal((GLogLevelFlags) 0); /*value out of range */
 
     if (facility == NULL) {
         facility = "daemon";
 
     } else if (safe_str_eq(facility, "none")) {
         facility = "daemon";
         quiet = TRUE;
     }
 
     if (entity) {
         free(crm_system_name);
         crm_system_name = strdup(entity);
 
     } else if (argc > 0 && argv != NULL) {
         char *mutable = strdup(argv[0]);
         char *modified = basename(mutable);
 
         if (strstr(modified, "lt-") == modified) {
             modified += 3;
         }
 
         free(crm_system_name);
         crm_system_name = strdup(modified);
         free(mutable);
 
     } else if (crm_system_name == NULL) {
         crm_system_name = strdup("Unknown");
     }
 
     setenv("PCMK_service", crm_system_name, 1);
 
     if (daemon_option_enabled(crm_system_name, "debug")) {
         /* Override the default setting */
         level = LOG_DEBUG;
     }
 
     if (daemon_option_enabled(crm_system_name, "stderr")) {
         /* Override the default setting */
         to_stderr = TRUE;
     }
 
     crm_log_priority = crm_priority2int(daemon_option("logpriority"));
 
     crm_log_level = level;
     qb_log_init(crm_system_name, qb_log_facility2int(facility), level);
     qb_log_tags_stringify_fn_set(crm_quark_to_string);
 
     /* Set default format strings */
     for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
         set_format_string(lpc, crm_system_name);
     }
 
     crm_enable_stderr(to_stderr);
 
     if (logfile) {
         crm_add_logfile(logfile);
     }
 
     if (crm_is_daemon && daemon_option_enabled(crm_system_name, "blackbox")) {
         crm_enable_blackbox(0);
     }
 
     crm_trace("Quiet: %d, facility %s", quiet, f_copy);
     daemon_option("debugfile");
     daemon_option("logfacility");
 
     if (quiet) {
         /* Nuke any syslog activity */
         facility = NULL;
         qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
     }
 
     if (crm_is_daemon) {
         set_daemon_option("logfacility", facility);
     }
 
     if (crm_is_daemon && crm_tracing_enabled()
         && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED
         && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
         /* Make sure tracing goes somewhere */
         crm_add_logfile(NULL);
     }
 
     crm_update_callsites();
 
     /* Ok, now we can start logging... */
     if (quiet == FALSE && crm_is_daemon == FALSE) {
         crm_log_args(argc, argv);
     }
 
     if (crm_is_daemon) {
         const char *user = getenv("USER");
 
         if (user != NULL && safe_str_neq(user, "root") && safe_str_neq(user, CRM_DAEMON_USER)) {
             crm_trace("Not switching to corefile directory for %s", user);
             crm_is_daemon = FALSE;
         }
     }
 
     if (crm_is_daemon) {
         int user = getuid();
         const char *base = CRM_CORE_DIR;
         struct passwd *pwent = getpwuid(user);
 
         if (pwent == NULL) {
             crm_perror(LOG_ERR, "Cannot get name for uid: %d", user);
 
         } else if (safe_str_neq(pwent->pw_name, "root")
                    && safe_str_neq(pwent->pw_name, CRM_DAEMON_USER)) {
             crm_trace("Don't change active directory for regular user: %s", pwent->pw_name);
 
         } else if (chdir(base) < 0) {
             crm_perror(LOG_INFO, "Cannot change active directory to %s", base);
 
         } else {
             crm_info("Changed active directory to %s/%s", base, pwent->pw_name);
 #if 0
             {
                 char path[512];
 
                 snprintf(path, 512, "%s-%d", crm_system_name, getpid());
                 mkdir(path, 0750);
                 chdir(path);
                 crm_info("Changed active directory to %s/%s/%s", base, pwent->pw_name, path);
             }
 #endif
         }
 
         /* Original meanings from signal(7)
          *
          * Signal       Value     Action   Comment
          * SIGTRAP        5        Core    Trace/breakpoint trap
          * SIGUSR1     30,10,16    Term    User-defined signal 1
          * SIGUSR2     31,12,17    Term    User-defined signal 2
          *
          * Our usage is as similar as possible
          */
         mainloop_add_signal(SIGUSR1, crm_enable_blackbox);
         mainloop_add_signal(SIGUSR2, crm_disable_blackbox);
         mainloop_add_signal(SIGTRAP, crm_trigger_blackbox);
     }
 
     crm_xml_init(); /* Sets buffer allocation strategy */
     return TRUE;
 }
 
 /* returns the old value */
 unsigned int
 set_crm_log_level(unsigned int level)
 {
     unsigned int old = crm_log_level;
 
     crm_log_level = level;
     crm_update_callsites();
     crm_trace("New log level: %d", level);
     return old;
 }
 
 void
 crm_enable_stderr(int enable)
 {
     if (enable && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
         qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
         crm_update_callsites();
 
     } else if (enable == FALSE) {
         qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
     }
 }
 
 void
 crm_bump_log_level(int argc, char **argv)
 {
     static int args = TRUE;
     int level = crm_log_level;
 
     if (args && argc > 1) {
         crm_log_args(argc, argv);
     }
 
     if (qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
         set_crm_log_level(level + 1);
     }
 
     /* Enable after potentially logging the argstring, not before */
     crm_enable_stderr(TRUE);
 }
 
 unsigned int
 get_crm_log_level(void)
 {
     return crm_log_level;
 }
 
 #define ARGS_FMT "Invoked: %s"
 void
 crm_log_args(int argc, char **argv)
 {
     int lpc = 0;
     int len = 0;
     int restore = FALSE;
     int existing_len = 0;
     int line = __LINE__;
     static int logged = 0;
 
     char *arg_string = NULL;
     struct qb_log_callsite *args_cs =
         qb_log_callsite_get(__func__, __FILE__, ARGS_FMT, LOG_NOTICE, line, 0);
 
     if (argc == 0 || argv == NULL || logged) {
         return;
     }
 
     logged = 1;
     qb_bit_set(args_cs->targets, QB_LOG_SYSLOG);        /* Turn on syslog too */
 
     restore = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_STATE_GET, 0);
     qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
 
     for (; lpc < argc; lpc++) {
         if (argv[lpc] == NULL) {
             break;
         }
 
         len = 2 + strlen(argv[lpc]);    /* +1 space, +1 EOS */
         arg_string = realloc(arg_string, len + existing_len);
         existing_len += sprintf(arg_string + existing_len, "%s ", argv[lpc]);
     }
 
     qb_log_from_external_source(__func__, __FILE__, ARGS_FMT, LOG_NOTICE, line, 0, arg_string);
     qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, restore);
 
     free(arg_string);
 }
 
 const char *
 pcmk_errorname(int rc) 
 {
     int error = ABS(rc);
 
     switch (error) {
         case E2BIG: return "E2BIG";
         case EACCES: return "EACCES";
         case EADDRINUSE: return "EADDRINUSE";
         case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
         case EAFNOSUPPORT: return "EAFNOSUPPORT";
         case EAGAIN: return "EAGAIN";
         case EALREADY: return "EALREADY";
         case EBADF: return "EBADF";
         case EBADMSG: return "EBADMSG";
         case EBUSY: return "EBUSY";
         case ECANCELED: return "ECANCELED";
         case ECHILD: return "ECHILD";
         case ECOMM: return "ECOMM";
         case ECONNABORTED: return "ECONNABORTED";
         case ECONNREFUSED: return "ECONNREFUSED";
         case ECONNRESET: return "ECONNRESET";
         /* case EDEADLK: return "EDEADLK"; */
         case EDESTADDRREQ: return "EDESTADDRREQ";
         case EDOM: return "EDOM";
         case EDQUOT: return "EDQUOT";
         case EEXIST: return "EEXIST";
         case EFAULT: return "EFAULT";
         case EFBIG: return "EFBIG";
         case EHOSTDOWN: return "EHOSTDOWN";
         case EHOSTUNREACH: return "EHOSTUNREACH";
         case EIDRM: return "EIDRM";
         case EILSEQ: return "EILSEQ";
         case EINPROGRESS: return "EINPROGRESS";
         case EINTR: return "EINTR";
         case EINVAL: return "EINVAL";
         case EIO: return "EIO";
         case EISCONN: return "EISCONN";
         case EISDIR: return "EISDIR";
         case ELIBACC: return "ELIBACC";
         case ELOOP: return "ELOOP";
         case EMFILE: return "EMFILE";
         case EMLINK: return "EMLINK";
         case EMSGSIZE: return "EMSGSIZE";
         case EMULTIHOP: return "EMULTIHOP";
         case ENAMETOOLONG: return "ENAMETOOLONG";
         case ENETDOWN: return "ENETDOWN";
         case ENETRESET: return "ENETRESET";
         case ENETUNREACH: return "ENETUNREACH";
         case ENFILE: return "ENFILE";
         case ENOBUFS: return "ENOBUFS";
         case ENODATA: return "ENODATA";
         case ENODEV: return "ENODEV";
         case ENOENT: return "ENOENT";
         case ENOEXEC: return "ENOEXEC";
         case ENOKEY: return "ENOKEY";
         case ENOLCK: return "ENOLCK";
         case ENOLINK: return "ENOLINK";
         case ENOMEM: return "ENOMEM";
         case ENOMSG: return "ENOMSG";
         case ENOPROTOOPT: return "ENOPROTOOPT";
         case ENOSPC: return "ENOSPC";
         case ENOSR: return "ENOSR";
         case ENOSTR: return "ENOSTR";
         case ENOSYS: return "ENOSYS";
         case ENOTBLK: return "ENOTBLK";
         case ENOTCONN: return "ENOTCONN";
         case ENOTDIR: return "ENOTDIR";
         case ENOTEMPTY: return "ENOTEMPTY";
         case ENOTSOCK: return "ENOTSOCK";
         /* case ENOTSUP: return "ENOTSUP"; */
         case ENOTTY: return "ENOTTY";
         case ENOTUNIQ: return "ENOTUNIQ";
         case ENXIO: return "ENXIO";
         case EOPNOTSUPP: return "EOPNOTSUPP";
         case EOVERFLOW: return "EOVERFLOW";
         case EPERM: return "EPERM";
         case EPFNOSUPPORT: return "EPFNOSUPPORT";
         case EPIPE: return "EPIPE";
         case EPROTO: return "EPROTO";
         case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
         case EPROTOTYPE: return "EPROTOTYPE";
         case ERANGE: return "ERANGE";
         case EREMOTE: return "EREMOTE";
         case EREMOTEIO: return "EREMOTEIO";
 
         case EROFS: return "EROFS";
         case ESHUTDOWN: return "ESHUTDOWN";
         case ESPIPE: return "ESPIPE";
         case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
         case ESRCH: return "ESRCH";
         case ESTALE: return "ESTALE";
         case ETIME: return "ETIME";
         case ETIMEDOUT: return "ETIMEDOUT";
         case ETXTBSY: return "ETXTBSY";
         case EUNATCH: return "EUNATCH";
         case EUSERS: return "EUSERS";
         /* case EWOULDBLOCK: return "EWOULDBLOCK"; */
         case EXDEV: return "EXDEV";
             
 #ifdef EBADE
             /* Not available on OSX */
         case EBADE: return "EBADE";
         case EBADFD: return "EBADFD";
         case EBADSLT: return "EBADSLT";
         case EDEADLOCK: return "EDEADLOCK";
         case EBADR: return "EBADR";
         case EBADRQC: return "EBADRQC";
         case ECHRNG: return "ECHRNG";
 #ifdef EISNAM /* Not available on Illumos/Solaris */
         case EISNAM: return "EISNAM";
         case EKEYEXPIRED: return "EKEYEXPIRED";
         case EKEYREJECTED: return "EKEYREJECTED";
         case EKEYREVOKED: return "EKEYREVOKED";
 #endif
         case EL2HLT: return "EL2HLT";
         case EL2NSYNC: return "EL2NSYNC";
         case EL3HLT: return "EL3HLT";
         case EL3RST: return "EL3RST";
         case ELIBBAD: return "ELIBBAD";
         case ELIBMAX: return "ELIBMAX";
         case ELIBSCN: return "ELIBSCN";
         case ELIBEXEC: return "ELIBEXEC";
 #ifdef ENOMEDIUM  /* Not available on Illumos/Solaris */
         case ENOMEDIUM: return "ENOMEDIUM";
         case EMEDIUMTYPE: return "EMEDIUMTYPE";
 #endif
         case ENONET: return "ENONET";
         case ENOPKG: return "ENOPKG";
         case EREMCHG: return "EREMCHG";
         case ERESTART: return "ERESTART";
         case ESTRPIPE: return "ESTRPIPE";
 #ifdef EUCLEAN  /* Not available on Illumos/Solaris */
         case EUCLEAN: return "EUCLEAN";
 #endif
         case EXFULL: return "EXFULL";
 #endif
 
         case pcmk_err_generic: return "pcmk_err_generic";
         case pcmk_err_no_quorum: return "pcmk_err_no_quorum";
         case pcmk_err_dtd_validation: return "pcmk_err_dtd_validation";
         case pcmk_err_transform_failed: return "pcmk_err_transform_failed";
         case pcmk_err_old_data: return "pcmk_err_old_data";
         case pcmk_err_diff_failed: return "pcmk_err_diff_failed";
         case pcmk_err_diff_resync: return "pcmk_err_diff_resync";
         case pcmk_err_cib_modified: return "pcmk_err_cib_modified";
         case pcmk_err_cib_backup: return "pcmk_err_cib_backup";
         case pcmk_err_cib_save: return "pcmk_err_cib_save";
     }
     return "Unknown";
 }
 
 
 const char *
 pcmk_strerror(int rc)
 {
     int error = abs(rc);
 
     if (error == 0) {
         return "OK";
     } else if (error < PCMK_ERROR_OFFSET) {
         return strerror(error);
     }
 
     switch (error) {
         case pcmk_err_generic:
             return "Generic Pacemaker error";
         case pcmk_err_no_quorum:
             return "Operation requires quorum";
         case pcmk_err_dtd_validation:
             return "Update does not conform to the configured schema";
         case pcmk_err_transform_failed:
             return "Schema transform failed";
         case pcmk_err_old_data:
             return "Update was older than existing configuration";
         case pcmk_err_diff_failed:
             return "Application of an update diff failed";
         case pcmk_err_diff_resync:
             return "Application of an update diff failed, requesting a full refresh";
         case pcmk_err_cib_modified:
             return "The on-disk configuration was manually modified";
         case pcmk_err_cib_backup:
             return "Could not archive the previous configuration";
         case pcmk_err_cib_save:
             return "Could not save the new configuration to disk";
 
             /* The following cases will only be hit on systems for which they are non-standard */
             /* coverity[dead_error_condition] False positive on non-Linux */
         case ENOTUNIQ:
             return "Name not unique on network";
             /* coverity[dead_error_condition] False positive on non-Linux */
         case ECOMM:
             return "Communication error on send";
             /* coverity[dead_error_condition] False positive on non-Linux */
         case ELIBACC:
             return "Can not access a needed shared library";
             /* coverity[dead_error_condition] False positive on non-Linux */
         case EREMOTEIO:
             return "Remote I/O error";
             /* coverity[dead_error_condition] False positive on non-Linux */
         case EUNATCH:
             return "Protocol driver not attached";
             /* coverity[dead_error_condition] False positive on non-Linux */
         case ENOKEY:
             return "Required key not available";
     }
 
     crm_err("Unknown error code: %d", rc);
     return "Unknown error";
 }
 
 const char *
 bz2_strerror(int rc)
 {
     /* http://www.bzip.org/1.0.3/html/err-handling.html */
     switch (rc) {
         case BZ_OK:
         case BZ_RUN_OK:
         case BZ_FLUSH_OK:
         case BZ_FINISH_OK:
         case BZ_STREAM_END:
             return "Ok";
         case BZ_CONFIG_ERROR:
             return "libbz2 has been improperly compiled on your platform";
         case BZ_SEQUENCE_ERROR:
             return "library functions called in the wrong order";
         case BZ_PARAM_ERROR:
             return "parameter is out of range or otherwise incorrect";
         case BZ_MEM_ERROR:
             return "memory allocation failed";
         case BZ_DATA_ERROR:
             return "data integrity error is detected during decompression";
         case BZ_DATA_ERROR_MAGIC:
             return "the compressed stream does not start with the correct magic bytes";
         case BZ_IO_ERROR:
             return "error reading or writing in the compressed file";
         case BZ_UNEXPECTED_EOF:
             return "compressed file finishes before the logical end of stream is detected";
         case BZ_OUTBUFF_FULL:
             return "output data will not fit into the buffer provided";
     }
     return "Unknown error";
 }
 
 void
 crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix,
                   const char *output)
 {
     const char *next = NULL;
     const char *offset = NULL;
 
     if (output == NULL) {
         level = LOG_DEBUG;
         output = "-- empty --";
     }
 
     next = output;
     do {
         offset = next;
         next = strchrnul(offset, '\n');
         do_crm_log_alias(level, file, function, line, "%s [ %.*s ]", prefix,
                          (int)(next - offset), offset);
         if (next[0] != 0) {
             next++;
         }
 
     } while (next != NULL && next[0] != 0);
 }
diff --git a/lib/common/xml.c b/lib/common/xml.c
index e9dfc74d61..17b5ad7cb0 100644
--- a/lib/common/xml.c
+++ b/lib/common/xml.c
@@ -1,3349 +1,3349 @@
 /*
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  *
  * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <crm_internal.h>
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <time.h>
 #include <string.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <ctype.h>
 
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <libxml/xmlreader.h>
 
 #if HAVE_BZLIB_H
 #  include <bzlib.h>
 #endif
 
 #if HAVE_LIBXML2
 #  include <libxml/parser.h>
 #  include <libxml/tree.h>
 #  include <libxml/relaxng.h>
 #endif
 
 #if HAVE_LIBXSLT
 #  include <libxslt/xslt.h>
 #  include <libxslt/transform.h>
 #endif
 
 #define XML_BUFFER_SIZE	4096
 #define XML_PARSER_DEBUG 0
 #define BEST_EFFORT_STATUS 0
 
 void
 xml_log(int priority, const char *fmt, ...)
 G_GNUC_PRINTF(2, 3);
 
 void
 xml_log(int priority, const char *fmt, ...)
 {
     va_list ap;
 
     va_start(ap, fmt);
     qb_log_from_external_source_va(__FUNCTION__, __FILE__, fmt, priority, __LINE__, 0, ap);
     va_end(ap);
 }
 
 typedef struct {
     xmlRelaxNGPtr rng;
     xmlRelaxNGValidCtxtPtr valid;
     xmlRelaxNGParserCtxtPtr parser;
 } relaxng_ctx_cache_t;
 
 struct schema_s {
     int type;
     const char *name;
     const char *location;
     const char *transform;
     int after_transform;
     void *cache;
 };
 
 typedef struct {
     int found;
     const char *string;
 } filter_t;
 
 /* *INDENT-OFF* */
 
 struct schema_s known_schemas[] = {
     /* 0 */    { 0, NULL, NULL, NULL, 1 },
     /* 1 */    { 1, "pacemaker-0.6",    "crm.dtd",		"upgrade06.xsl", 4, NULL },
     /* 2 */    { 1, "transitional-0.6", "crm-transitional.dtd",	"upgrade06.xsl", 4, NULL },
     /* 3 */    { 2, "pacemaker-0.7",    "pacemaker-1.0.rng",	NULL, 0, NULL },
     /* 4 */    { 2, "pacemaker-1.0",    "pacemaker-1.0.rng",	NULL, 6, NULL },
     /* 5 */    { 2, "pacemaker-1.1",    "pacemaker-1.1.rng",	NULL, 6, NULL },
     /* 6 */    { 2, "pacemaker-1.2",    "pacemaker-1.2.rng",	NULL, 0, NULL },
     /* 7 */    { 0, "none", NULL, NULL, 0, NULL },
 };
 
 static filter_t filter[] = {
     { 0, XML_ATTR_ORIGIN },
     { 0, XML_CIB_ATTR_WRITTEN },
     { 0, XML_ATTR_UPDATE_ORIG },
     { 0, XML_ATTR_UPDATE_CLIENT },
     { 0, XML_ATTR_UPDATE_USER },
 };
 /* *INDENT-ON* */
 
 static int all_schemas = DIMOF(known_schemas);
 static int max_schemas = DIMOF(known_schemas) - 2;      /* skip back past 'none' */
 
 #define CHUNK_SIZE 1024
 
 #define buffer_print(buffer, max, offset, fmt, args...) do {            \
         int rc = (max);                                                 \
         if(buffer) {                                                    \
             rc = snprintf((buffer) + (offset), (max) - (offset), fmt, ##args); \
         }                                                               \
         if(rc < 0) {                                                    \
             crm_perror(LOG_ERR, "snprintf failed");                     \
             (buffer)[(offset)] = 0;                                     \
             return;                                                     \
         } else if(rc >= ((max) - (offset))) {                           \
             (max) = QB_MAX(CHUNK_SIZE, (max) * 2);                             \
             (buffer) = realloc((buffer), (max) + 1);                    \
         } else {                                                        \
             offset += rc;                                               \
             break;                                                      \
         }                                                               \
     } while(1);
 
 static void
 insert_prefix(int options, char **buffer, int *offset, int *max, int depth)
 {
     if (options & xml_log_option_formatted) {
         size_t spaces = 2 * depth;
 
         if ((*buffer) == NULL || spaces >= ((*max) - (*offset))) {
             (*max) = QB_MAX(CHUNK_SIZE, (*max) * 2);
             (*buffer) = realloc((*buffer), (*max) + 1);
         }
         memset((*buffer) + (*offset), ' ', spaces);
         (*offset) += spaces;
     }
 }
 
 static char *
 get_schema_path(const char *file)
 {
     static const char *base = NULL;
 
     if (base == NULL) {
         base = getenv("PCMK_schema_directory");
     }
     if (base == NULL || strlen(base) == 0) {
         base = CRM_DTD_DIRECTORY;
     }
     return crm_concat(base, file, '/');
 }
 
 int get_tag_name(const char *input, size_t offset, size_t max);
 int get_attr_name(const char *input, size_t offset, size_t max);
 int get_attr_value(const char *input, size_t offset, size_t max);
 gboolean can_prune_leaf(xmlNode * xml_node);
 
 void diff_filter_context(int context, int upper_bound, int lower_bound,
                          xmlNode * xml_node, xmlNode * parent);
 int in_upper_context(int depth, int context, xmlNode * xml_node);
 int add_xml_object(xmlNode * parent, xmlNode * target, xmlNode * update, gboolean as_diff);
 
 static inline const char *
 crm_attr_value(xmlAttr * attr)
 {
     if (attr == NULL || attr->children == NULL) {
         return NULL;
     }
     return (const char *)attr->children->content;
 }
 
 static inline xmlAttr *
 crm_first_attr(xmlNode * xml)
 {
     if (xml == NULL) {
         return NULL;
     }
     return xml->properties;
 }
 
 xmlNode *
 find_xml_node(xmlNode * root, const char *search_path, gboolean must_find)
 {
     xmlNode *a_child = NULL;
     const char *name = "NULL";
 
     if (root != NULL) {
         name = crm_element_name(root);
     }
 
     if (search_path == NULL) {
         crm_warn("Will never find <NULL>");
         return NULL;
     }
 
     for (a_child = __xml_first_child(root); a_child != NULL; a_child = __xml_next(a_child)) {
         if (strcmp((const char *)a_child->name, search_path) == 0) {
 /* 		crm_trace("returning node (%s).", crm_element_name(a_child)); */
             return a_child;
         }
     }
 
     if (must_find) {
         crm_warn("Could not find %s in %s.", search_path, name);
     } else if (root != NULL) {
         crm_trace("Could not find %s in %s.", search_path, name);
     } else {
         crm_trace("Could not find %s in <NULL>.", search_path);
     }
 
     return NULL;
 }
 
 xmlNode *
 find_entity(xmlNode * parent, const char *node_name, const char *id)
 {
     xmlNode *a_child = NULL;
 
     for (a_child = __xml_first_child(parent); a_child != NULL; a_child = __xml_next(a_child)) {
         /* Uncertain if node_name == NULL check is strictly necessary here */
         if (node_name == NULL || strcmp((const char *)a_child->name, node_name) == 0) {
             if (id == NULL || strcmp(id, ID(a_child)) == 0) {
                 return a_child;
             }
         }
     }
 
     crm_trace("node <%s id=%s> not found in %s.", node_name, id, crm_element_name(parent));
     return NULL;
 }
 
 void
 copy_in_properties(xmlNode * target, xmlNode * src)
 {
     if (src == NULL) {
         crm_warn("No node to copy properties from");
 
     } else if (target == NULL) {
         crm_err("No node to copy properties into");
 
     } else {
         xmlAttrPtr pIter = NULL;
 
         for (pIter = crm_first_attr(src); pIter != NULL; pIter = pIter->next) {
             const char *p_name = (const char *)pIter->name;
             const char *p_value = crm_attr_value(pIter);
 
             expand_plus_plus(target, p_name, p_value);
         }
     }
 
     return;
 }
 
 void
 fix_plus_plus_recursive(xmlNode * target)
 {
     /* TODO: Remove recursion and use xpath searches for value++ */
     xmlNode *child = NULL;
     xmlAttrPtr pIter = NULL;
 
     for (pIter = crm_first_attr(target); pIter != NULL; pIter = pIter->next) {
         const char *p_name = (const char *)pIter->name;
         const char *p_value = crm_attr_value(pIter);
 
         expand_plus_plus(target, p_name, p_value);
     }
     for (child = __xml_first_child(target); child != NULL; child = __xml_next(child)) {
         fix_plus_plus_recursive(child);
     }
 }
 
 void
 expand_plus_plus(xmlNode * target, const char *name, const char *value)
 {
     int offset = 1;
     int name_len = 0;
     int int_value = 0;
     int value_len = 0;
 
     const char *old_value = NULL;
 
     if (value == NULL || name == NULL) {
         return;
     }
 
     old_value = crm_element_value(target, name);
 
     if (old_value == NULL) {
         /* if no previous value, set unexpanded */
         goto set_unexpanded;
 
     } else if (strstr(value, name) != value) {
         goto set_unexpanded;
     }
 
     name_len = strlen(name);
     value_len = strlen(value);
     if (value_len < (name_len + 2)
         || value[name_len] != '+' || (value[name_len + 1] != '+' && value[name_len + 1] != '=')) {
         goto set_unexpanded;
     }
 
     /* if we are expanding ourselves,
      * then no previous value was set and leave int_value as 0
      */
     if (old_value != value) {
         int_value = char2score(old_value);
     }
 
     if (value[name_len + 1] != '+') {
         const char *offset_s = value + (name_len + 2);
 
         offset = char2score(offset_s);
     }
     int_value += offset;
 
     if (int_value > INFINITY) {
         int_value = INFINITY;
     }
 
     crm_xml_add_int(target, name, int_value);
     return;
 
   set_unexpanded:
     if (old_value == value) {
         /* the old value is already set, nothing to do */
         return;
     }
     crm_xml_add(target, name, value);
     return;
 }
 
 xmlDoc *
 getDocPtr(xmlNode * node)
 {
     xmlDoc *doc = NULL;
 
     CRM_CHECK(node != NULL, return NULL);
 
     doc = node->doc;
     if (doc == NULL) {
         doc = xmlNewDoc((const xmlChar *)"1.0");
         xmlDocSetRootElement(doc, node);
         xmlSetTreeDoc(node, doc);
     }
     return doc;
 }
 
 xmlNode *
 add_node_copy(xmlNode * parent, xmlNode * src_node)
 {
     xmlNode *child = NULL;
     xmlDoc *doc = getDocPtr(parent);
 
     CRM_CHECK(src_node != NULL, return NULL);
 
     child = xmlDocCopyNode(src_node, doc, 1);
     xmlAddChild(parent, child);
     return child;
 }
 
 int
 add_node_nocopy(xmlNode * parent, const char *name, xmlNode * child)
 {
     add_node_copy(parent, child);
     free_xml(child);
     return 1;
 }
 
 const char *
 crm_xml_add(xmlNode * node, const char *name, const char *value)
 {
     xmlAttr *attr = NULL;
 
     CRM_CHECK(node != NULL, return NULL);
     CRM_CHECK(name != NULL, return NULL);
 
     if (value == NULL) {
         return NULL;
     }
 #if XML_PARANOIA_CHECKS
     {
         const char *old_value = NULL;
 
         old_value = crm_element_value(node, name);
 
         /* Could be re-setting the same value */
         CRM_CHECK(old_value != value, crm_err("Cannot reset %s with crm_xml_add(%s)", name, value);
                   return value);
     }
 #endif
 
     attr = xmlSetProp(node, (const xmlChar *)name, (const xmlChar *)value);
     CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
     return (char *)attr->children->content;
 }
 
 const char *
 crm_xml_replace(xmlNode * node, const char *name, const char *value)
 {
     xmlAttr *attr = NULL;
     const char *old_value = NULL;
 
     CRM_CHECK(node != NULL, return NULL);
     CRM_CHECK(name != NULL && name[0] != 0, return NULL);
 
     old_value = crm_element_value(node, name);
 
     /* Could be re-setting the same value */
     CRM_CHECK(old_value != value, return value);
 
     if (old_value != NULL && value == NULL) {
         xml_remove_prop(node, name);
         return NULL;
 
     } else if (value == NULL) {
         return NULL;
     }
 
     attr = xmlSetProp(node, (const xmlChar *)name, (const xmlChar *)value);
     CRM_CHECK(attr && attr->children && attr->children->content, return NULL);
     return (char *)attr->children->content;
 }
 
 const char *
 crm_xml_add_int(xmlNode * node, const char *name, int value)
 {
     char *number = crm_itoa(value);
     const char *added = crm_xml_add(node, name, number);
 
     free(number);
     return added;
 }
 
 xmlNode *
 create_xml_node(xmlNode * parent, const char *name)
 {
     xmlDoc *doc = NULL;
     xmlNode *node = NULL;
 
     if (name == NULL || name[0] == 0) {
         return NULL;
     }
 
     if (parent == NULL) {
         doc = xmlNewDoc((const xmlChar *)"1.0");
         node = xmlNewDocRawNode(doc, NULL, (const xmlChar *)name, NULL);
         xmlDocSetRootElement(doc, node);
 
     } else {
         doc = getDocPtr(parent);
         node = xmlNewDocRawNode(doc, NULL, (const xmlChar *)name, NULL);
         xmlAddChild(parent, node);
     }
     return node;
 }
 
 void
 free_xml(xmlNode * child)
 {
     if (child != NULL) {
         xmlNode *top = NULL;
         xmlDoc *doc = child->doc;
 
         if (doc != NULL) {
             top = xmlDocGetRootElement(doc);
         }
 
         if (doc != NULL && top == child) {
             /* Free everything */
             xmlFreeDoc(doc);
 
         } else {
             /* Free this particular subtree
              * Make sure to unlink it from the parent first
              */
             xmlUnlinkNode(child);
             xmlFreeNode(child);
         }
     }
 }
 
 xmlNode *
 copy_xml(xmlNode * src)
 {
     xmlDoc *doc = xmlNewDoc((const xmlChar *)"1.0");
     xmlNode *copy = xmlDocCopyNode(src, doc, 1);
 
     xmlDocSetRootElement(doc, copy);
     xmlSetTreeDoc(copy, doc);
     return copy;
 }
 
 static void
 crm_xml_err(void *ctx, const char *msg, ...)
 G_GNUC_PRINTF(2, 3);
 
 static void
 crm_xml_err(void *ctx, const char *msg, ...)
 {
     int len = 0;
     va_list args;
     char *buf = NULL;
     static int buffer_len = 0;
     static char *buffer = NULL;
 
     va_start(args, msg);
     len = vasprintf(&buf, msg, args);
 
     if (strchr(buf, '\n')) {
         buf[len - 1] = 0;
         if (buffer) {
             crm_err("XML Error: %s%s", buffer, buf);
             free(buffer);
         } else {
             crm_err("XML Error: %s", buf);
         }
         buffer = NULL;
         buffer_len = 0;
 
     } else if (buffer == NULL) {
         buffer_len = len;
         buffer = buf;
         buf = NULL;
 
     } else {
         buffer = realloc(buffer, 1 + buffer_len + len);
         memcpy(buffer + buffer_len, buf, len);
         buffer_len += len;
         buffer[buffer_len] = 0;
     }
 
     va_end(args);
     free(buf);
 }
 
 xmlNode *
 string2xml(const char *input)
 {
     xmlNode *xml = NULL;
     xmlDocPtr output = NULL;
     xmlParserCtxtPtr ctxt = NULL;
     xmlErrorPtr last_error = NULL;
 
     if (input == NULL) {
         crm_err("Can't parse NULL input");
         return NULL;
     }
 
     /* create a parser context */
     ctxt = xmlNewParserCtxt();
     CRM_CHECK(ctxt != NULL, return NULL);
 
     /* xmlCtxtUseOptions(ctxt, XML_PARSE_NOBLANKS|XML_PARSE_RECOVER); */
 
     xmlCtxtResetLastError(ctxt);
     xmlSetGenericErrorFunc(ctxt, crm_xml_err);
     /* initGenericErrorDefaultFunc(crm_xml_err); */
     output =
         xmlCtxtReadDoc(ctxt, (const xmlChar *)input, NULL, NULL,
                        XML_PARSE_NOBLANKS | XML_PARSE_RECOVER);
     if (output) {
         xml = xmlDocGetRootElement(output);
     }
     last_error = xmlCtxtGetLastError(ctxt);
     if (last_error && last_error->code != XML_ERR_OK) {
-        /* crm_abort(__FILE__,__PRETTY_FUNCTION__,__LINE__, "last_error->code != XML_ERR_OK", TRUE, TRUE); */
+        /* crm_abort(__FILE__,__FUNCTION__,__LINE__, "last_error->code != XML_ERR_OK", TRUE, TRUE); */
         /*
          * http://xmlsoft.org/html/libxml-xmlerror.html#xmlErrorLevel
          * http://xmlsoft.org/html/libxml-xmlerror.html#xmlParserErrors
          */
         crm_warn("Parsing failed (domain=%d, level=%d, code=%d): %s",
                  last_error->domain, last_error->level, last_error->code, last_error->message);
 
         if (last_error->code == XML_ERR_DOCUMENT_EMPTY) {
-            crm_abort(__FILE__, __PRETTY_FUNCTION__, __LINE__, "Cannot parse an empty string", TRUE,
+            crm_abort(__FILE__, __FUNCTION__, __LINE__, "Cannot parse an empty string", TRUE,
                       TRUE);
 
         } else if (last_error->code != XML_ERR_DOCUMENT_END) {
             crm_err("Couldn't%s parse %d chars: %s", xml ? " fully" : "", (int)strlen(input),
                     input);
             if (xml != NULL) {
                 crm_log_xml_err(xml, "Partial");
             }
 
         } else {
             int len = strlen(input);
             int lpc = 0;
 
             while(lpc < len) {
                 crm_warn("Parse error[+%.3d]: %.80s", lpc, input+lpc);
                 lpc += 80;
             }
 
-            crm_abort(__FILE__, __PRETTY_FUNCTION__, __LINE__, "String parsing error", TRUE, TRUE);
+            crm_abort(__FILE__, __FUNCTION__, __LINE__, "String parsing error", TRUE, TRUE);
         }
     }
 
     xmlFreeParserCtxt(ctxt);
     return xml;
 }
 
 xmlNode *
 stdin2xml(void)
 {
     size_t data_length = 0;
     size_t read_chars = 0;
 
     char *xml_buffer = NULL;
     xmlNode *xml_obj = NULL;
 
     do {
         size_t next = XML_BUFFER_SIZE + data_length + 1;
 
         if(next <= 0) {
             crm_err("Buffer size exceeded at: %l + %d", data_length, XML_BUFFER_SIZE);
             break;
         }
 
         xml_buffer = realloc(xml_buffer, next);
         read_chars = fread(xml_buffer + data_length, 1, XML_BUFFER_SIZE, stdin);
         data_length += read_chars;
     } while (read_chars > 0);
 
     if (data_length == 0) {
         crm_warn("No XML supplied on stdin");
         free(xml_buffer);
         return NULL;
     }
 
     xml_buffer[data_length] = '\0';
 
     xml_obj = string2xml(xml_buffer);
     free(xml_buffer);
 
     crm_log_xml_trace(xml_obj, "Created fragment");
     return xml_obj;
 }
 
 static char *
 decompress_file(const char *filename)
 {
     char *buffer = NULL;
 
 #if HAVE_BZLIB_H
     int rc = 0;
     size_t length = 0, read_len = 0;
 
     BZFILE *bz_file = NULL;
     FILE *input = fopen(filename, "r");
 
     if (input == NULL) {
         crm_perror(LOG_ERR, "Could not open %s for reading", filename);
         return NULL;
     }
 
     bz_file = BZ2_bzReadOpen(&rc, input, 0, 0, NULL, 0);
 
     if (rc != BZ_OK) {
         BZ2_bzReadClose(&rc, bz_file);
         return NULL;
     }
 
     rc = BZ_OK;
     while (rc == BZ_OK) {
         buffer = realloc(buffer, XML_BUFFER_SIZE + length + 1);
         read_len = BZ2_bzRead(&rc, bz_file, buffer + length, XML_BUFFER_SIZE);
 
         crm_trace("Read %ld bytes from file: %d", (long)read_len, rc);
 
         if (rc == BZ_OK || rc == BZ_STREAM_END) {
             length += read_len;
         }
     }
 
     buffer[length] = '\0';
     read_len = length;
 
     if (rc != BZ_STREAM_END) {
         crm_err("Couldnt read compressed xml from file");
         free(buffer);
         buffer = NULL;
     }
 
     BZ2_bzReadClose(&rc, bz_file);
     fclose(input);
 
 #else
     crm_err("Cannot read compressed files:" " bzlib was not available at compile time");
 #endif
     return buffer;
 }
 
 void
 strip_text_nodes(xmlNode * xml)
 {
     xmlNode *iter = xml->children;
 
     while (iter) {
         xmlNode *next = iter->next;
 
         switch (iter->type) {
             case XML_TEXT_NODE:
                 /* Remove it */
                 xmlUnlinkNode(iter);
                 xmlFreeNode(iter);
                 break;
 
             case XML_ELEMENT_NODE:
                 /* Search it */
                 strip_text_nodes(iter);
                 break;
 
             default:
                 /* Leave it */
                 break;
         }
 
         iter = next;
     }
 }
 
 xmlNode *
 filename2xml(const char *filename)
 {
     xmlNode *xml = NULL;
     xmlDocPtr output = NULL;
     const char *match = NULL;
     xmlParserCtxtPtr ctxt = NULL;
     xmlErrorPtr last_error = NULL;
     static int xml_options = XML_PARSE_NOBLANKS | XML_PARSE_RECOVER;
 
     /* create a parser context */
     ctxt = xmlNewParserCtxt();
     CRM_CHECK(ctxt != NULL, return NULL);
 
     /* xmlCtxtUseOptions(ctxt, XML_PARSE_NOBLANKS|XML_PARSE_RECOVER); */
 
     xmlCtxtResetLastError(ctxt);
     xmlSetGenericErrorFunc(ctxt, crm_xml_err);
     /* initGenericErrorDefaultFunc(crm_xml_err); */
 
     if (filename) {
         match = strstr(filename, ".bz2");
     }
 
     if (filename == NULL) {
         /* STDIN_FILENO == fileno(stdin) */
         output = xmlCtxtReadFd(ctxt, STDIN_FILENO, "unknown.xml", NULL, xml_options);
 
     } else if (match == NULL || match[4] != 0) {
         output = xmlCtxtReadFile(ctxt, filename, NULL, xml_options);
 
     } else {
         char *input = decompress_file(filename);
 
         output = xmlCtxtReadDoc(ctxt, (const xmlChar *)input, NULL, NULL, xml_options);
         free(input);
     }
 
     if (output && (xml = xmlDocGetRootElement(output))) {
         strip_text_nodes(xml);
     }
 
     last_error = xmlCtxtGetLastError(ctxt);
     if (last_error && last_error->code != XML_ERR_OK) {
-        /* crm_abort(__FILE__,__PRETTY_FUNCTION__,__LINE__, "last_error->code != XML_ERR_OK", TRUE, TRUE); */
+        /* crm_abort(__FILE__,__FUNCTION__,__LINE__, "last_error->code != XML_ERR_OK", TRUE, TRUE); */
         /*
          * http://xmlsoft.org/html/libxml-xmlerror.html#xmlErrorLevel
          * http://xmlsoft.org/html/libxml-xmlerror.html#xmlParserErrors
          */
         crm_err("Parsing failed (domain=%d, level=%d, code=%d): %s",
                 last_error->domain, last_error->level, last_error->code, last_error->message);
 
         if (last_error && last_error->code != XML_ERR_OK) {
             crm_err("Couldn't%s parse %s", xml ? " fully" : "", filename);
             if (xml != NULL) {
                 crm_log_xml_err(xml, "Partial");
             }
         }
     }
 
     xmlFreeParserCtxt(ctxt);
     return xml;
 }
 
 static int
 write_xml_stream(xmlNode * xml_node, const char *filename, FILE * stream, gboolean compress)
 {
     int res = 0;
     char *buffer = NULL;
     unsigned int out = 0;
     static mode_t cib_mode = S_IRUSR | S_IWUSR;
 
     CRM_CHECK(stream != NULL, return -1);
 
     crm_trace("Writing XML out to %s", filename);
     if (xml_node == NULL) {
         crm_err("Cannot write NULL to %s", filename);
         fclose(stream);
         return -1;
     }
 
 
     crm_log_xml_trace(xml_node, "Writing out");
 
     if(strstr(filename, "cib") != NULL) {
         /* Only CIB's need this field written */
         time_t now = time(NULL);
         char *now_str = ctime(&now);
 
         now_str[24] = EOS;          /* replace the newline */
         crm_xml_add(xml_node, XML_CIB_ATTR_WRITTEN, now_str);
 
         /* establish the correct permissions */
         fchmod(fileno(stream), cib_mode);
     }
 
     buffer = dump_xml_formatted(xml_node);
     CRM_CHECK(buffer != NULL && strlen(buffer) > 0, crm_log_xml_warn(xml_node, "dump:failed");
               goto bail);
 
     if (compress) {
 #if HAVE_BZLIB_H
         int rc = BZ_OK;
         unsigned int in = 0;
         BZFILE *bz_file = NULL;
 
         bz_file = BZ2_bzWriteOpen(&rc, stream, 5, 0, 30);
         if (rc != BZ_OK) {
             crm_err("bzWriteOpen failed: %d", rc);
         } else {
             BZ2_bzWrite(&rc, bz_file, buffer, strlen(buffer));
             if (rc != BZ_OK) {
                 crm_err("bzWrite() failed: %d", rc);
             }
         }
 
         if (rc == BZ_OK) {
             BZ2_bzWriteClose(&rc, bz_file, 0, &in, &out);
             if (rc != BZ_OK) {
                 crm_err("bzWriteClose() failed: %d", rc);
                 out = -1;
             } else {
                 crm_trace("%s: In: %d, out: %d", filename, in, out);
             }
         }
 #else
         crm_err("Cannot write compressed files:" " bzlib was not available at compile time");
 #endif
     }
 
     if (out <= 0) {
         res = fprintf(stream, "%s", buffer);
         if (res < 0) {
             crm_perror(LOG_ERR, "Cannot write output to %s", filename);
             goto bail;
         }
     }
 
   bail:
 
     if (fflush(stream) != 0) {
         crm_perror(LOG_ERR, "fflush for %s failed:", filename);
         res = -1;
     }
 
     if (fsync(fileno(stream)) < 0) {
         crm_perror(LOG_ERR, "fsync for %s failed:", filename);
         res = -1;
     }
 
     fclose(stream);
 
     crm_trace("Saved %d bytes to the Cib as XML", res);
     free(buffer);
 
     return res;
 }
 
 int
 write_xml_fd(xmlNode * xml_node, const char *filename, int fd, gboolean compress)
 {
     FILE *stream = NULL;
 
     CRM_CHECK(fd > 0, return -1);
     stream = fdopen(fd, "w");
     return write_xml_stream(xml_node, filename, stream, compress);
 }
 
 int
 write_xml_file(xmlNode * xml_node, const char *filename, gboolean compress)
 {
     FILE *stream = NULL;
 
     stream = fopen(filename, "w");
 
     return write_xml_stream(xml_node, filename, stream, compress);
 }
 
 xmlNode *
 get_message_xml(xmlNode * msg, const char *field)
 {
     xmlNode *tmp = first_named_child(msg, field);
 
     return __xml_first_child(tmp);
 }
 
 gboolean
 add_message_xml(xmlNode * msg, const char *field, xmlNode * xml)
 {
     xmlNode *holder = create_xml_node(msg, field);
 
     add_node_copy(holder, xml);
     return TRUE;
 }
 
 static char *
 crm_xml_escape_shuffle(char *text, int start, int *length, const char *replace)
 {
     int lpc;
     int offset = strlen(replace) - 1;   /* We have space for 1 char already */
 
     *length += offset;
     text = realloc(text, *length);
 
     for (lpc = (*length) - 1; lpc > (start + offset); lpc--) {
         text[lpc] = text[lpc - offset];
     }
 
     memcpy(text + start, replace, offset + 1);
     return text;
 }
 
 static char *
 crm_xml_escape(const char *text)
 {
     int index;
     int changes = 0;
     int length = 1 + strlen(text);
     char *copy = strdup(text);
 
     /*
      * When xmlCtxtReadDoc() parses &lt; and friends in a
      * value, it converts them to their human readable
      * form.
      *
      * If one uses xmlNodeDump() to convert it back to a
      * string, all is well, because special characters are
      * converted back to their escape sequences.
      *
      * However xmlNodeDump() is randomly dog slow, even with the same
      * input. So we need to replicate the escapeing in our custom
      * version so that the result can be re-parsed by xmlCtxtReadDoc()
      * when necessary.
      */
 
     for (index = 0; index < length; index++) {
         switch (copy[index]) {
             case 0:
                 break;
             case '<':
                 copy = crm_xml_escape_shuffle(copy, index, &length, "&lt;");
                 changes++;
                 break;
             case '>':
                 copy = crm_xml_escape_shuffle(copy, index, &length, "&gt;");
                 changes++;
                 break;
             case '"':
                 copy = crm_xml_escape_shuffle(copy, index, &length, "&quot;");
                 changes++;
                 break;
             case '\'':
                 copy = crm_xml_escape_shuffle(copy, index, &length, "&apos;");
                 changes++;
                 break;
             case '&':
                 copy = crm_xml_escape_shuffle(copy, index, &length, "&amp;");
                 changes++;
                 break;
             case '\t':
                 /* Might as well just expand to a few spaces... */
                 copy = crm_xml_escape_shuffle(copy, index, &length, "    ");
                 changes++;
                 break;
             case '\n':
                 /* crm_trace("Convert: \\%.3o", copy[index]); */
                 copy = crm_xml_escape_shuffle(copy, index, &length, "\\n");
                 changes++;
                 break;
             case '\r':
                 copy = crm_xml_escape_shuffle(copy, index, &length, "\\r");
                 changes++;
                 break;
                 /* For debugging...
             case '\\':
                 crm_trace("Passthrough: \\%c", copy[index+1]);
                 break;
                 */
             default:
                 /* Check for and replace non-printing characters with their octal equivalent */
                 if(copy[index] < ' ' || copy[index] > '~') {
                     char *replace = g_strdup_printf("\\%.3o", copy[index]);
 
                     /* crm_trace("Convert to octal: \\%.3o", copy[index]); */
                     copy = crm_xml_escape_shuffle(copy, index, &length, replace);
                     free(replace);
                     changes++;
                 }
         }
     }
 
     if (changes) {
         crm_trace("Dumped '%s'", copy);
     }
     return copy;
 }
 
 static inline void
 dump_xml_attr(xmlAttrPtr attr, int options, char **buffer, int *offset, int *max)
 {
     char *p_value = NULL;
     const char *p_name = NULL;
 
     if (attr == NULL || attr->children == NULL) {
         return;
     }
 
     p_name = (const char *)attr->name;
     p_value = crm_xml_escape((const char *)attr->children->content);
     buffer_print(*buffer, *max, *offset, " %s=\"%s\"", p_name, p_value);
     free(p_value);
 }
 
 void
 log_data_element(int log_level, const char *file, const char *function, int line,
                  const char *prefix, xmlNode * data, int depth, int options)
 {
     xmlNode *a_child = NULL;
 
     int max = 0;
     int offset = 0;
     char *buffer = NULL;
     char *prefix_m = NULL;
 
     xmlAttrPtr pIter = NULL;
     const char *name = NULL;
     const char *hidden = NULL;
 
     if (prefix == NULL) {
         prefix = "";
     }
 
     /* Since we use the same file and line, to avoid confusing libqb, we need to use the same format strings */
     if (data == NULL) {
         do_crm_log_alias(log_level, file, function, line, "%s: %s", prefix,
                          "No data to dump as XML");
         return;
     }
 
     name = crm_element_name(data);
 
     if (is_set(options, xml_log_option_formatted)) {
         if (is_set(options, xml_log_option_diff_plus)
             && (data->children == NULL || crm_element_value(data, XML_DIFF_MARKER))) {
             options |= xml_log_option_diff_all;
             prefix_m = strdup(prefix);
             prefix_m[1] = '+';
             prefix = prefix_m;
 
         } else if (is_set(options, xml_log_option_diff_minus)
                    && (data->children == NULL || crm_element_value(data, XML_DIFF_MARKER))) {
             options |= xml_log_option_diff_all;
             prefix_m = strdup(prefix);
             prefix_m[1] = '-';
             prefix = prefix_m;
         }
     }
 
     if (is_set(options, xml_log_option_diff_short)
                && is_not_set(options, xml_log_option_diff_all)) {
         /* Still searching for the actual change */
         for (a_child = __xml_first_child(data); a_child != NULL; a_child = __xml_next(a_child)) {
             log_data_element(log_level, file, function, line, prefix, a_child, depth + 1, options);
         }
         return;
     }
 
     insert_prefix(options, &buffer, &offset, &max, depth);
     if(data->type == XML_COMMENT_NODE) {
         buffer_print(buffer, max, offset, "<!--");
         buffer_print(buffer, max, offset, "%s", data->content);
         buffer_print(buffer, max, offset, "-->");
 
     } else {
         buffer_print(buffer, max, offset, "<%s", name);
     }
 
     hidden = crm_element_value(data, "hidden");
     for (pIter = crm_first_attr(data); pIter != NULL; pIter = pIter->next) {
         const char *p_name = (const char *)pIter->name;
         const char *p_value = crm_attr_value(pIter);
         char *p_copy = NULL;
 
         if ((is_set(options, xml_log_option_diff_plus)
              || is_set(options, xml_log_option_diff_minus))
             && strcmp(XML_DIFF_MARKER, p_name) == 0) {
             continue;
 
         } else if (hidden != NULL && p_name[0] != 0 && strstr(hidden, p_name) != NULL) {
             p_copy = strdup("*****");
 
         } else {
             p_copy = crm_xml_escape(p_value);
         }
 
         buffer_print(buffer, max, offset, " %s=\"%s\"", p_name, p_copy);
         free(p_copy);
     }
 
     if (xml_has_children(data)) {
         buffer_print(buffer, max, offset, ">");
     } else {
         buffer_print(buffer, max, offset, "/>");
     }
 
     do_crm_log_alias(log_level, file, function, line, "%s %s", prefix, buffer);
 
     if (data->children && data->type != XML_COMMENT_NODE) {
         offset = 0;
         max = 0;
         free(buffer);
         buffer = NULL;
 
         for (a_child = __xml_first_child(data); a_child != NULL; a_child = __xml_next(a_child)) {
             log_data_element(log_level, file, function, line, prefix, a_child, depth + 1, options);
         }
 
         insert_prefix(options, &buffer, &offset, &max, depth);
         buffer_print(buffer, max, offset, "</%s>", name);
 
         do_crm_log_alias(log_level, file, function, line, "%s %s", prefix, buffer);
     }
 
     free(prefix_m);
     free(buffer);
 }
 
 static void
 dump_filtered_xml(xmlNode * data, int options, char **buffer, int *offset, int *max)
 {
     int lpc;
     xmlAttrPtr xIter = NULL;
     static int filter_len = DIMOF(filter);
 
     for (lpc = 0; options && lpc < filter_len; lpc++) {
         filter[lpc].found = FALSE;
     }
 
     for (xIter = crm_first_attr(data); xIter != NULL; xIter = xIter->next) {
         bool skip = FALSE;
         const char *p_name = (const char *)xIter->name;
 
         for (lpc = 0; skip == FALSE && lpc < filter_len; lpc++) {
             if (filter[lpc].found == FALSE && strcmp(p_name, filter[lpc].string) == 0) {
                 filter[lpc].found = TRUE;
                 skip = TRUE;
                 break;
             }
         }
 
         if (skip == FALSE) {
             dump_xml_attr(xIter, options, buffer, offset, max);
         }
     }
 }
 
 static void
 dump_xml(xmlNode * data, int options, char **buffer, int *offset, int *max, int depth);
 
 static void
 dump_xml_element(xmlNode * data, int options, char **buffer, int *offset, int *max, int depth)
 {
     const char *name = NULL;
 
     CRM_ASSERT(max != NULL);
     CRM_ASSERT(offset != NULL);
     CRM_ASSERT(buffer != NULL);
 
     if (data == NULL) {
         crm_trace("Nothing to dump");
         return;
     }
 
     if (*buffer == NULL) {
         *offset = 0;
         *max = 0;
     }
 
     name = crm_element_name(data);
     CRM_ASSERT(name != NULL);
 
     insert_prefix(options, buffer, offset, max, depth);
     buffer_print(*buffer, *max, *offset, "<%s", name);
 
     if (options & xml_log_option_filtered) {
         dump_filtered_xml(data, options, buffer, offset, max);
 
     } else {
         xmlAttrPtr xIter = NULL;
 
         for (xIter = crm_first_attr(data); xIter != NULL; xIter = xIter->next) {
             dump_xml_attr(xIter, options, buffer, offset, max);
         }
     }
 
     if (data->children == NULL) {
         buffer_print(*buffer, *max, *offset, "/>");
 
     } else {
         buffer_print(*buffer, *max, *offset, ">");
     }
 
     if (options & xml_log_option_formatted) {
         buffer_print(*buffer, *max, *offset, "\n");
     }
 
     if (data->children) {
         xmlNode *xChild = NULL;
 
         for (xChild = __xml_first_child(data); xChild != NULL; xChild = __xml_next(xChild)) {
             dump_xml(xChild, options, buffer, offset, max, depth + 1);
         }
 
         insert_prefix(options, buffer, offset, max, depth);
         buffer_print(*buffer, *max, *offset, "</%s>", name);
 
         if (options & xml_log_option_formatted) {
             buffer_print(*buffer, *max, *offset, "\n");
         }
     }
 }
 
 static void
 dump_xml_comment(xmlNode * data, int options, char **buffer, int *offset, int *max, int depth)
 {
     CRM_ASSERT(max != NULL);
     CRM_ASSERT(offset != NULL);
     CRM_ASSERT(buffer != NULL);
 
     if (data == NULL) {
         crm_trace("Nothing to dump");
         return;
     }
 
     if (*buffer == NULL) {
         *offset = 0;
         *max = 0;
     }
 
     insert_prefix(options, buffer, offset, max, depth);
 
     buffer_print(*buffer, *max, *offset, "<!--");
     buffer_print(*buffer, *max, *offset, "%s", data->content);
     buffer_print(*buffer, *max, *offset, "-->");
 
     if (options & xml_log_option_formatted) {
         buffer_print(*buffer, *max, *offset, "\n");
     }
 }
 
 static void
 dump_xml(xmlNode * data, int options, char **buffer, int *offset, int *max, int depth)
 {
 #if 0
     if (is_not_set(options, xml_log_option_filtered)) {
         /* Turning this code on also changes the PE tests for some reason
          * (not just newlines).  Figure out why before considering to
          * enable this permanently.
          *
          * It exists to help debug slowness in xmlNodeDump() and
          * potentially if we ever want to go back to it.
          *
          * In theory its a good idea (reuse) but our custom version does
          * better for the filtered case and avoids the final strdup() for
          * everything
          */
 
         time_t now, next;
         xmlDoc *doc = NULL;
         xmlBuffer *xml_buffer = NULL;
 
         *buffer = NULL;
         doc = getDocPtr(data);
         /* doc will only be NULL if data is */
         CRM_CHECK(doc != NULL, return);
 
         now = time(NULL);
         xml_buffer = xmlBufferCreate();
         CRM_ASSERT(xml_buffer != NULL);
 
         /* The default allocator XML_BUFFER_ALLOC_EXACT does far too many
          * realloc()s and it can take upwards of 18 seconds (yes, seconds)
          * to dump a 28kb tree which XML_BUFFER_ALLOC_DOUBLEIT can do in
          * less than 1 second.
          *
          * We could also use xmlBufferCreateSize() to start with a
          * sane-ish initial size and avoid the first few doubles.
          */
         xmlBufferSetAllocationScheme(xml_buffer, XML_BUFFER_ALLOC_DOUBLEIT);
 
         *max = xmlNodeDump(xml_buffer, doc, data, 0, (options & xml_log_option_formatted));
         if (*max > 0) {
             *buffer = strdup((char *)xml_buffer->content);
         }
 
         next = time(NULL);
         if ((now + 1) < next) {
             crm_log_xml_trace(data, "Long time");
             crm_err("xmlNodeDump() -> %dbytes took %ds", *max, next - now);
         }
 
         xmlBufferFree(xml_buffer);
         return;
     }
 #endif
 
     switch(data->type) {
         case XML_ELEMENT_NODE:
             /* Handle below */
             dump_xml_element(data, options, buffer, offset, max, depth);
             break;
         case XML_TEXT_NODE:
             /* Ignore */
             return;
         case XML_COMMENT_NODE:
             dump_xml_comment(data, options, buffer, offset, max, depth);
             break;
         default:
             crm_warn("Unhandled type: %d", data->type);
             return;
 
             /*
             XML_ATTRIBUTE_NODE = 2
             XML_CDATA_SECTION_NODE = 4
             XML_ENTITY_REF_NODE = 5
             XML_ENTITY_NODE = 6
             XML_PI_NODE = 7
             XML_DOCUMENT_NODE = 9
             XML_DOCUMENT_TYPE_NODE = 10
             XML_DOCUMENT_FRAG_NODE = 11
             XML_NOTATION_NODE = 12
             XML_HTML_DOCUMENT_NODE = 13
             XML_DTD_NODE = 14
             XML_ELEMENT_DECL = 15
             XML_ATTRIBUTE_DECL = 16
             XML_ENTITY_DECL = 17
             XML_NAMESPACE_DECL = 18
             XML_XINCLUDE_START = 19
             XML_XINCLUDE_END = 20
             XML_DOCB_DOCUMENT_NODE = 21
             */
     }
 
 }
 
 static void
 fix_digest_buffer(char **buffer, int *offset, int *max, char c)
 {
     buffer_print(*buffer, *max, *offset, "%c", c);
 }
 
 static char *
 dump_xml_for_digest(xmlNode * an_xml_node)
 {
     char *buffer = NULL;
     int offset = 0, max = 0;
 
     /* for compatability with the old result which is used for v1 digests */
     fix_digest_buffer(&buffer, &offset, &max, ' ');
     dump_xml(an_xml_node, 0, &buffer, &offset, &max, 0);
     fix_digest_buffer(&buffer, &offset, &max, '\n');
 
     return buffer;
 }
 
 char *
 dump_xml_formatted(xmlNode * an_xml_node)
 {
     char *buffer = NULL;
     int offset = 0, max = 0;
 
     dump_xml(an_xml_node, xml_log_option_formatted, &buffer, &offset, &max, 0);
     return buffer;
 }
 
 char *
 dump_xml_unformatted(xmlNode * an_xml_node)
 {
     char *buffer = NULL;
     int offset = 0, max = 0;
 
     dump_xml(an_xml_node, 0, &buffer, &offset, &max, 0);
     return buffer;
 }
 
 gboolean
 xml_has_children(const xmlNode * xml_root)
 {
     if (xml_root != NULL && xml_root->children != NULL) {
         return TRUE;
     }
     return FALSE;
 }
 
 int
 crm_element_value_int(xmlNode * data, const char *name, int *dest)
 {
     const char *value = crm_element_value(data, name);
 
     CRM_CHECK(dest != NULL, return -1);
     if (value) {
         *dest = crm_int_helper(value, NULL);
         return 0;
     }
     return -1;
 }
 
 int
 crm_element_value_const_int(const xmlNode * data, const char *name, int *dest)
 {
     return crm_element_value_int((xmlNode *) data, name, dest);
 }
 
 const char *
 crm_element_value_const(const xmlNode * data, const char *name)
 {
     return crm_element_value((xmlNode *) data, name);
 }
 
 char *
 crm_element_value_copy(xmlNode * data, const char *name)
 {
     char *value_copy = NULL;
     const char *value = crm_element_value(data, name);
 
     if (value != NULL) {
         value_copy = strdup(value);
     }
     return value_copy;
 }
 
 void
 xml_remove_prop(xmlNode * obj, const char *name)
 {
     xmlUnsetProp(obj, (const xmlChar *)name);
 }
 
 void
 log_xml_diff(uint8_t log_level, xmlNode * diff, const char *function)
 {
     xmlNode *child = NULL;
     xmlNode *added = find_xml_node(diff, "diff-added", FALSE);
     xmlNode *removed = find_xml_node(diff, "diff-removed", FALSE);
     gboolean is_first = TRUE;
     int options = xml_log_option_formatted;
 
     static struct qb_log_callsite *diff_cs = NULL;
 
     if (diff_cs == NULL) {
         diff_cs = qb_log_callsite_get(function, __FILE__, "xml-diff", log_level, __LINE__, 0);
     }
 
     if (crm_is_callsite_active(diff_cs, log_level, 0) == FALSE) {
         return;
     }
 
     if (log_level < LOG_DEBUG || function == NULL) {
         options |= xml_log_option_diff_short;
     }
     for (child = __xml_first_child(removed); child != NULL; child = __xml_next(child)) {
         log_data_element(log_level, __FILE__, function, __LINE__, "- ", child, 0,
                          options | xml_log_option_diff_minus);
         if (is_first) {
             is_first = FALSE;
         } else {
             do_crm_log(log_level, " --- ");
         }
     }
 
     is_first = TRUE;
     for (child = __xml_first_child(added); child != NULL; child = __xml_next(child)) {
         log_data_element(log_level, __FILE__, function, __LINE__, "+ ", child, 0,
                          options | xml_log_option_diff_plus);
         if (is_first) {
             is_first = FALSE;
         } else {
             do_crm_log(log_level, " +++ ");
         }
     }
 }
 
 void
 purge_diff_markers(xmlNode * a_node)
 {
     xmlNode *child = NULL;
 
     CRM_CHECK(a_node != NULL, return);
 
     xml_remove_prop(a_node, XML_DIFF_MARKER);
     for (child = __xml_first_child(a_node); child != NULL; child = __xml_next(child)) {
         purge_diff_markers(child);
     }
 }
 
 static void
 save_xml_to_file(xmlNode * xml, const char *desc, const char *filename)
 {
     char *f = NULL;
 
     if (filename == NULL) {
         char *uuid = crm_generate_uuid();
 
         f = g_strdup_printf("/tmp/%s", uuid);
         filename = f;
         free(uuid);
     }
 
     crm_info("Saving %s to %s", desc, filename);
     write_xml_file(xml, filename, FALSE);
     g_free(f);
 }
 
 gboolean
 apply_xml_diff(xmlNode * old, xmlNode * diff, xmlNode ** new)
 {
     gboolean result = TRUE;
     int root_nodes_seen = 0;
     static struct qb_log_callsite *digest_cs = NULL;
     const char *digest = crm_element_value(diff, XML_ATTR_DIGEST);
     const char *version = crm_element_value(diff, XML_ATTR_CRM_VERSION);
 
     xmlNode *child_diff = NULL;
     xmlNode *added = find_xml_node(diff, "diff-added", FALSE);
     xmlNode *removed = find_xml_node(diff, "diff-removed", FALSE);
 
     CRM_CHECK(new != NULL, return FALSE);
     if (digest_cs == NULL) {
         digest_cs =
             qb_log_callsite_get(__func__, __FILE__, "diff-digest", LOG_TRACE, __LINE__,
                                 crm_trace_nonlog);
     }
 
     crm_trace("Substraction Phase");
     for (child_diff = __xml_first_child(removed); child_diff != NULL;
          child_diff = __xml_next(child_diff)) {
         CRM_CHECK(root_nodes_seen == 0, result = FALSE);
         if (root_nodes_seen == 0) {
             *new = subtract_xml_object(NULL, old, child_diff, FALSE, NULL, NULL);
         }
         root_nodes_seen++;
     }
 
     if (root_nodes_seen == 0) {
         *new = copy_xml(old);
 
     } else if (root_nodes_seen > 1) {
         crm_err("(-) Diffs cannot contain more than one change set..." " saw %d", root_nodes_seen);
         result = FALSE;
     }
 
     root_nodes_seen = 0;
     crm_trace("Addition Phase");
     if (result) {
         xmlNode *child_diff = NULL;
 
         for (child_diff = __xml_first_child(added); child_diff != NULL;
              child_diff = __xml_next(child_diff)) {
             CRM_CHECK(root_nodes_seen == 0, result = FALSE);
             if (root_nodes_seen == 0) {
                 add_xml_object(NULL, *new, child_diff, TRUE);
             }
             root_nodes_seen++;
         }
     }
 
     if (root_nodes_seen > 1) {
         crm_err("(+) Diffs cannot contain more than one change set..." " saw %d", root_nodes_seen);
         result = FALSE;
 
     } else if (result && digest) {
         char *new_digest = NULL;
 
         purge_diff_markers(*new);       /* Purge now so the diff is ok */
         new_digest = calculate_xml_versioned_digest(*new, FALSE, TRUE, version);
         if (safe_str_neq(new_digest, digest)) {
             crm_info("Digest mis-match: expected %s, calculated %s", digest, new_digest);
             result = FALSE;
 
             crm_trace("%p %0.6x", digest_cs, digest_cs ? digest_cs->targets : 0);
             if (digest_cs && digest_cs->targets) {
                 save_xml_to_file(old, "diff:original", NULL);
                 save_xml_to_file(diff, "diff:input", NULL);
                 save_xml_to_file(*new, "diff:new", NULL);
             }
 
         } else {
             crm_trace("Digest matched: expected %s, calculated %s", digest, new_digest);
         }
         free(new_digest);
 
     } else if (result) {
         purge_diff_markers(*new);       /* Purge now so the diff is ok */
     }
 
     return result;
 }
 
 xmlNode *
 diff_xml_object(xmlNode * old, xmlNode * new, gboolean suppress)
 {
     xmlNode *tmp1 = NULL;
     xmlNode *diff = create_xml_node(NULL, "diff");
     xmlNode *removed = create_xml_node(diff, "diff-removed");
     xmlNode *added = create_xml_node(diff, "diff-added");
 
     crm_xml_add(diff, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
 
     tmp1 = subtract_xml_object(removed, old, new, FALSE, NULL, "removed:top");
     if (suppress && tmp1 != NULL && can_prune_leaf(tmp1)) {
         free_xml(tmp1);
     }
 
     tmp1 = subtract_xml_object(added, new, old, TRUE, NULL, "added:top");
     if (suppress && tmp1 != NULL && can_prune_leaf(tmp1)) {
         free_xml(tmp1);
     }
 
     if (added->children == NULL && removed->children == NULL) {
         free_xml(diff);
         diff = NULL;
     }
 
     return diff;
 }
 
 gboolean
 can_prune_leaf(xmlNode * xml_node)
 {
     xmlNode *child = NULL;
     xmlAttrPtr pIter = NULL;
     gboolean can_prune = TRUE;
 
     for (pIter = crm_first_attr(xml_node); pIter != NULL; pIter = pIter->next) {
         const char *p_name = (const char *)pIter->name;
 
         if (strcmp(p_name, XML_ATTR_ID) == 0) {
             continue;
         }
         can_prune = FALSE;
     }
 
     for (child = __xml_first_child(xml_node); child != NULL; child = __xml_next(child)) {
         if (can_prune_leaf(child)) {
             free_xml(child);
         } else {
             can_prune = FALSE;
         }
     }
     return can_prune;
 }
 
 void
 diff_filter_context(int context, int upper_bound, int lower_bound,
                     xmlNode * xml_node, xmlNode * parent)
 {
     xmlNode *us = NULL;
     xmlNode *child = NULL;
     xmlAttrPtr pIter = NULL;
     xmlNode *new_parent = parent;
     const char *name = crm_element_name(xml_node);
 
     CRM_CHECK(xml_node != NULL && name != NULL, return);
 
     us = create_xml_node(parent, name);
     for (pIter = crm_first_attr(xml_node); pIter != NULL; pIter = pIter->next) {
         const char *p_name = (const char *)pIter->name;
         const char *p_value = crm_attr_value(pIter);
 
         lower_bound = context;
         crm_xml_add(us, p_name, p_value);
     }
 
     if (lower_bound >= 0 || upper_bound >= 0) {
         crm_xml_add(us, XML_ATTR_ID, ID(xml_node));
         new_parent = us;
 
     } else {
         upper_bound = in_upper_context(0, context, xml_node);
         if (upper_bound >= 0) {
             crm_xml_add(us, XML_ATTR_ID, ID(xml_node));
             new_parent = us;
         } else {
             free_xml(us);
             us = NULL;
         }
     }
 
     for (child = __xml_first_child(us); child != NULL; child = __xml_next(child)) {
         diff_filter_context(context, upper_bound - 1, lower_bound - 1, child, new_parent);
     }
 }
 
 int
 in_upper_context(int depth, int context, xmlNode * xml_node)
 {
     if (context == 0) {
         return 0;
     }
 
     if (xml_node->properties) {
         return depth;
 
     } else if (depth < context) {
         xmlNode *child = NULL;
 
         for (child = __xml_first_child(xml_node); child != NULL; child = __xml_next(child)) {
             if (in_upper_context(depth + 1, context, child)) {
                 return depth;
             }
         }
     }
     return 0;
 }
 
 static xmlNode *
 find_xml_comment(xmlNode * root, xmlNode * search_comment)
 {
     xmlNode *a_child = NULL;
 
     CRM_CHECK(search_comment->type == XML_COMMENT_NODE, return NULL);
 
     for (a_child = __xml_first_child(root); a_child != NULL; a_child = __xml_next(a_child)) {
         if (a_child->type != XML_COMMENT_NODE) {
             continue;
         }
         if (safe_str_eq((const char *)a_child->content, (const char *)search_comment->content)) {
             return a_child;
         }
     }
 
     return NULL;
 }
 
 static xmlNode *
 subtract_xml_comment(xmlNode * parent, xmlNode * left, xmlNode * right,
                      gboolean * changed)
 {
     CRM_CHECK(left != NULL, return NULL);
     CRM_CHECK(left->type == XML_COMMENT_NODE, return NULL);
 
     if (right == NULL
         || safe_str_neq((const char *)left->content, (const char *)right->content)) {
         xmlNode *deleted = NULL;
 
         deleted = add_node_copy(parent, left);
         *changed = TRUE;
 
         return deleted;
     }
 
     return NULL;
 }
 
 xmlNode *
 subtract_xml_object(xmlNode * parent, xmlNode * left, xmlNode * right,
                     gboolean full, gboolean * changed, const char *marker)
 {
     gboolean dummy = FALSE;
     gboolean skip = FALSE;
     xmlNode *diff = NULL;
     xmlNode *right_child = NULL;
     xmlNode *left_child = NULL;
     xmlAttrPtr xIter = NULL;
 
     const char *id = NULL;
     const char *name = NULL;
     const char *value = NULL;
     const char *right_val = NULL;
 
     int lpc = 0;
     static int filter_len = DIMOF(filter);
 
     if (changed == NULL) {
         changed = &dummy;
     }
 
     if (left == NULL) {
         return NULL;
     }
 
     if (left->type == XML_COMMENT_NODE) {
         return subtract_xml_comment(parent, left, right, changed);
     }
 
     id = ID(left);
     if (right == NULL) {
         xmlNode *deleted = NULL;
 
         crm_trace("Processing <%s id=%s> (complete copy)", crm_element_name(left), id);
         deleted = add_node_copy(parent, left);
         crm_xml_add(deleted, XML_DIFF_MARKER, marker);
 
         *changed = TRUE;
         return deleted;
     }
 
     name = crm_element_name(left);
     CRM_CHECK(name != NULL, return NULL);
 
     /* check for XML_DIFF_MARKER in a child */
     value = crm_element_value(right, XML_DIFF_MARKER);
     if (value != NULL && strcmp(value, "removed:top") == 0) {
         crm_trace("We are the root of the deletion: %s.id=%s", name, id);
         *changed = TRUE;
         free_xml(diff);
         return NULL;
     }
 
     /* Avoiding creating the full heirarchy would save even more work here */
     diff = create_xml_node(parent, name);
 
     /* Reset filter */
     for (lpc = 0; lpc < filter_len; lpc++) {
         filter[lpc].found = FALSE;
     }
 
     /* changes to child objects */
     for (left_child = __xml_first_child(left); left_child != NULL;
          left_child = __xml_next(left_child)) {
         gboolean child_changed = FALSE;
 
         if (left_child->type == XML_COMMENT_NODE) {
             right_child = find_xml_comment(right, left_child);
 
         } else {
             right_child = find_entity(right, crm_element_name(left_child), ID(left_child));
         }
 
         subtract_xml_object(diff, left_child, right_child, full, &child_changed, marker);
         if (child_changed) {
             *changed = TRUE;
         }
     }
 
     if (*changed == FALSE) {
         /* Nothing to do */
 
     } else if (full) {
         xmlAttrPtr pIter = NULL;
 
         for (pIter = crm_first_attr(left); pIter != NULL; pIter = pIter->next) {
             const char *p_name = (const char *)pIter->name;
             const char *p_value = crm_attr_value(pIter);
 
             xmlSetProp(diff, (const xmlChar *)p_name, (const xmlChar *)p_value);
         }
 
         /* We already have everything we need... */
         goto done;
 
     } else if (id) {
         xmlSetProp(diff, (const xmlChar *)XML_ATTR_ID, (const xmlChar *)id);
     }
 
     /* changes to name/value pairs */
     for (xIter = crm_first_attr(left); xIter != NULL; xIter = xIter->next) {
         const char *prop_name = (const char *)xIter->name;
 
         if (strcmp(prop_name, XML_ATTR_ID) == 0) {
             continue;
         }
 
         skip = FALSE;
         for (lpc = 0; skip == FALSE && lpc < filter_len; lpc++) {
             if (filter[lpc].found == FALSE && strcmp(prop_name, filter[lpc].string) == 0) {
                 filter[lpc].found = TRUE;
                 skip = TRUE;
                 break;
             }
         }
 
         if (skip) {
             continue;
         }
 
         right_val = crm_element_value(right, prop_name);
         if (right_val == NULL) {
             /* new */
             *changed = TRUE;
             if (full) {
                 xmlAttrPtr pIter = NULL;
 
                 for (pIter = crm_first_attr(left); pIter != NULL; pIter = pIter->next) {
                     const char *p_name = (const char *)pIter->name;
                     const char *p_value = crm_attr_value(pIter);
 
                     xmlSetProp(diff, (const xmlChar *)p_name, (const xmlChar *)p_value);
                 }
                 break;
 
             } else {
                 const char *left_value = crm_element_value(left, prop_name);
 
                 xmlSetProp(diff, (const xmlChar *)prop_name, (const xmlChar *)value);
                 crm_xml_add(diff, prop_name, left_value);
             }
 
         } else {
             /* Only now do we need the left value */
             const char *left_value = crm_element_value(left, prop_name);
 
             if (strcmp(left_value, right_val) == 0) {
                 /* unchanged */
 
             } else {
                 *changed = TRUE;
                 if (full) {
                     xmlAttrPtr pIter = NULL;
 
                     crm_trace("Changes detected to %s in <%s id=%s>", prop_name,
                               crm_element_name(left), id);
                     for (pIter = crm_first_attr(left); pIter != NULL; pIter = pIter->next) {
                         const char *p_name = (const char *)pIter->name;
                         const char *p_value = crm_attr_value(pIter);
 
                         xmlSetProp(diff, (const xmlChar *)p_name, (const xmlChar *)p_value);
                     }
                     break;
 
                 } else {
                     crm_trace("Changes detected to %s (%s -> %s) in <%s id=%s>",
                               prop_name, left_value, right_val, crm_element_name(left), id);
                     crm_xml_add(diff, prop_name, left_value);
                 }
             }
         }
     }
 
     if (*changed == FALSE) {
         free_xml(diff);
         return NULL;
 
     } else if (full == FALSE && id) {
         crm_xml_add(diff, XML_ATTR_ID, id);
     }
   done:
     return diff;
 }
 
 static int
 add_xml_comment(xmlNode * parent, xmlNode * target, xmlNode * update)
 {
     CRM_CHECK(update != NULL, return 0);
     CRM_CHECK(update->type == XML_COMMENT_NODE, return 0);
 
     if (target == NULL) {
         target = find_xml_comment(parent, update);
     } 
     
     if (target == NULL) {
         add_node_copy(parent, update);
 
     /* We wont reach here currently */
     } else if (safe_str_neq((const char *)target->content, (const char *)update->content)) {
         xmlFree(target->content);
         target->content = xmlStrdup(update->content);
     }
 
     return 0;
 }
 
 int
 add_xml_object(xmlNode * parent, xmlNode * target, xmlNode * update, gboolean as_diff)
 {
     xmlNode *a_child = NULL;
     const char *object_id = NULL;
     const char *object_name = NULL;
 
 #if XML_PARSE_DEBUG
     crm_log_xml_trace("update:", update);
     crm_log_xml_trace("target:", target);
 #endif
 
     CRM_CHECK(update != NULL, return 0);
 
     if (update->type == XML_COMMENT_NODE) {
         return add_xml_comment(parent, target, update);
     }
 
     object_name = crm_element_name(update);
     object_id = ID(update);
 
     CRM_CHECK(object_name != NULL, return 0);
 
     if (target == NULL && object_id == NULL) {
         /*  placeholder object */
         target = find_xml_node(parent, object_name, FALSE);
 
     } else if (target == NULL) {
         target = find_entity(parent, object_name, object_id);
     }
 
     if (target == NULL) {
         target = create_xml_node(parent, object_name);
         CRM_CHECK(target != NULL, return 0);
 #if XML_PARSER_DEBUG
         crm_trace("Added  <%s%s%s/>", crm_str(object_name),
                   object_id ? " id=" : "", object_id ? object_id : "");
 
     } else {
         crm_trace("Found node <%s%s%s/> to update",
                   crm_str(object_name), object_id ? " id=" : "", object_id ? object_id : "");
 #endif
     }
 
     if (as_diff == FALSE) {
         /* So that expand_plus_plus() gets called */
         copy_in_properties(target, update);
 
     } else {
         /* No need for expand_plus_plus(), just raw speed */
         xmlAttrPtr pIter = NULL;
 
         for (pIter = crm_first_attr(update); pIter != NULL; pIter = pIter->next) {
             const char *p_name = (const char *)pIter->name;
             const char *p_value = crm_attr_value(pIter);
 
             /* Remove it first so the ordering of the update is preserved */
             xmlUnsetProp(target, (const xmlChar *)p_name);
             xmlSetProp(target, (const xmlChar *)p_name, (const xmlChar *)p_value);
         }
     }
 
     for (a_child = __xml_first_child(update); a_child != NULL; a_child = __xml_next(a_child)) {
 #if XML_PARSER_DEBUG
         crm_trace("Updating child <%s id=%s>", crm_element_name(a_child), ID(a_child));
 #endif
         add_xml_object(target, NULL, a_child, as_diff);
     }
 
 #if XML_PARSER_DEBUG
     crm_trace("Finished with <%s id=%s>", crm_str(object_name), crm_str(object_id));
 #endif
     return 0;
 }
 
 gboolean
 update_xml_child(xmlNode * child, xmlNode * to_update)
 {
     gboolean can_update = TRUE;
     xmlNode *child_of_child = NULL;
 
     CRM_CHECK(child != NULL, return FALSE);
     CRM_CHECK(to_update != NULL, return FALSE);
 
     if (safe_str_neq(crm_element_name(to_update), crm_element_name(child))) {
         can_update = FALSE;
 
     } else if (safe_str_neq(ID(to_update), ID(child))) {
         can_update = FALSE;
 
     } else if (can_update) {
 #if XML_PARSER_DEBUG
         crm_log_xml_trace(child, "Update match found...");
 #endif
         add_xml_object(NULL, child, to_update, FALSE);
     }
 
     for (child_of_child = __xml_first_child(child); child_of_child != NULL;
          child_of_child = __xml_next(child_of_child)) {
         /* only update the first one */
         if (can_update) {
             break;
         }
         can_update = update_xml_child(child_of_child, to_update);
     }
 
     return can_update;
 }
 
 int
 find_xml_children(xmlNode ** children, xmlNode * root,
                   const char *tag, const char *field, const char *value, gboolean search_matches)
 {
     int match_found = 0;
 
     CRM_CHECK(root != NULL, return FALSE);
     CRM_CHECK(children != NULL, return FALSE);
 
     if (tag != NULL && safe_str_neq(tag, crm_element_name(root))) {
 
     } else if (value != NULL && safe_str_neq(value, crm_element_value(root, field))) {
 
     } else {
         if (*children == NULL) {
             *children = create_xml_node(NULL, __FUNCTION__);
         }
         add_node_copy(*children, root);
         match_found = 1;
     }
 
     if (search_matches || match_found == 0) {
         xmlNode *child = NULL;
 
         for (child = __xml_first_child(root); child != NULL; child = __xml_next(child)) {
             match_found += find_xml_children(children, child, tag, field, value, search_matches);
         }
     }
 
     return match_found;
 }
 
 gboolean
 replace_xml_child(xmlNode * parent, xmlNode * child, xmlNode * update, gboolean delete_only)
 {
     gboolean can_delete = FALSE;
     xmlNode *child_of_child = NULL;
 
     const char *up_id = NULL;
     const char *child_id = NULL;
     const char *right_val = NULL;
 
     CRM_CHECK(child != NULL, return FALSE);
     CRM_CHECK(update != NULL, return FALSE);
 
     up_id = ID(update);
     child_id = ID(child);
 
     if (up_id == NULL || (child_id && strcmp(child_id, up_id) == 0)) {
         can_delete = TRUE;
     }
     if (safe_str_neq(crm_element_name(update), crm_element_name(child))) {
         can_delete = FALSE;
     }
     if (can_delete && delete_only) {
         xmlAttrPtr pIter = NULL;
 
         for (pIter = crm_first_attr(update); pIter != NULL; pIter = pIter->next) {
             const char *p_name = (const char *)pIter->name;
             const char *p_value = crm_attr_value(pIter);
 
             right_val = crm_element_value(child, p_name);
             if (safe_str_neq(p_value, right_val)) {
                 can_delete = FALSE;
             }
         }
     }
 
     if (can_delete && parent != NULL) {
         crm_log_xml_trace(child, "Delete match found...");
         if (delete_only || update == NULL) {
             free_xml(child);
 
         } else {
             xmlNode *tmp = copy_xml(update);
             xmlDoc *doc = tmp->doc;
             xmlNode *old = xmlReplaceNode(child, tmp);
 
             free_xml(old);
             xmlDocSetRootElement(doc, NULL);
             xmlFreeDoc(doc);
         }
         child = NULL;
         return TRUE;
 
     } else if (can_delete) {
         crm_log_xml_debug(child, "Cannot delete the search root");
         can_delete = FALSE;
     }
 
     child_of_child = __xml_first_child(child);
     while (child_of_child) {
         xmlNode *next = __xml_next(child_of_child);
 
         can_delete = replace_xml_child(child, child_of_child, update, delete_only);
 
         /* only delete the first one */
         if (can_delete) {
             child_of_child = NULL;
         } else {
             child_of_child = next;
         }
     }
 
     return can_delete;
 }
 
 void
 hash2nvpair(gpointer key, gpointer value, gpointer user_data)
 {
     const char *name = key;
     const char *s_value = value;
 
     xmlNode *xml_node = user_data;
     xmlNode *xml_child = create_xml_node(xml_node, XML_CIB_TAG_NVPAIR);
 
     crm_xml_add(xml_child, XML_ATTR_ID, name);
     crm_xml_add(xml_child, XML_NVPAIR_ATTR_NAME, name);
     crm_xml_add(xml_child, XML_NVPAIR_ATTR_VALUE, s_value);
 
     crm_trace("dumped: name=%s value=%s", name, s_value);
 }
 
 void
 hash2smartfield(gpointer key, gpointer value, gpointer user_data)
 {
     const char *name = key;
     const char *s_value = value;
 
     xmlNode *xml_node = user_data;
 
     if (isdigit(name[0])) {
         xmlNode *tmp = create_xml_node(xml_node, XML_TAG_PARAM);
 
         crm_xml_add(tmp, XML_NVPAIR_ATTR_NAME, name);
         crm_xml_add(tmp, XML_NVPAIR_ATTR_VALUE, s_value);
 
     } else if (crm_element_value(xml_node, name) == NULL) {
         crm_xml_add(xml_node, name, s_value);
         crm_trace("dumped: %s=%s", name, s_value);
 
     } else {
         crm_trace("duplicate: %s=%s", name, s_value);
     }
 }
 
 void
 hash2field(gpointer key, gpointer value, gpointer user_data)
 {
     const char *name = key;
     const char *s_value = value;
 
     xmlNode *xml_node = user_data;
 
     if (crm_element_value(xml_node, name) == NULL) {
         crm_xml_add(xml_node, name, s_value);
 
     } else {
         crm_trace("duplicate: %s=%s", name, s_value);
     }
 }
 
 void
 hash2metafield(gpointer key, gpointer value, gpointer user_data)
 {
     char *crm_name = NULL;
 
     if (key == NULL || value == NULL) {
         return;
     } else if (((char *)key)[0] == '#') {
         return;
     } else if (strstr(key, ":")) {
         return;
     }
 
     crm_name = crm_meta_name(key);
     hash2field(crm_name, value, user_data);
     free(crm_name);
 }
 
 GHashTable *
 xml2list(xmlNode * parent)
 {
     xmlNode *child = NULL;
     xmlAttrPtr pIter = NULL;
     xmlNode *nvpair_list = NULL;
     GHashTable *nvpair_hash = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                                     g_hash_destroy_str, g_hash_destroy_str);
 
     CRM_CHECK(parent != NULL, return nvpair_hash);
 
     nvpair_list = find_xml_node(parent, XML_TAG_ATTRS, FALSE);
     if (nvpair_list == NULL) {
         crm_trace("No attributes in %s", crm_element_name(parent));
         crm_log_xml_trace(parent, "No attributes for resource op");
     }
 
     crm_log_xml_trace(nvpair_list, "Unpacking");
 
     for (pIter = crm_first_attr(nvpair_list); pIter != NULL; pIter = pIter->next) {
         const char *p_name = (const char *)pIter->name;
         const char *p_value = crm_attr_value(pIter);
 
         crm_trace("Added %s=%s", p_name, p_value);
 
         g_hash_table_insert(nvpair_hash, strdup(p_name), strdup(p_value));
     }
 
     for (child = __xml_first_child(nvpair_list); child != NULL; child = __xml_next(child)) {
         if (strcmp((const char *)child->name, XML_TAG_PARAM) == 0) {
             const char *key = crm_element_value(child, XML_NVPAIR_ATTR_NAME);
             const char *value = crm_element_value(child, XML_NVPAIR_ATTR_VALUE);
 
             crm_trace("Added %s=%s", key, value);
             if (key != NULL && value != NULL) {
                 g_hash_table_insert(nvpair_hash, strdup(key), strdup(value));
             }
         }
     }
 
     return nvpair_hash;
 }
 
 typedef struct name_value_s {
     const char *name;
     const void *value;
 } name_value_t;
 
 static gint
 sort_pairs(gconstpointer a, gconstpointer b)
 {
     int rc = 0;
     const name_value_t *pair_a = a;
     const name_value_t *pair_b = b;
 
     CRM_ASSERT(a != NULL);
     CRM_ASSERT(pair_a->name != NULL);
 
     CRM_ASSERT(b != NULL);
     CRM_ASSERT(pair_b->name != NULL);
 
     rc = strcmp(pair_a->name, pair_b->name);
     if (rc < 0) {
         return -1;
     } else if (rc > 0) {
         return 1;
     }
     return 0;
 }
 
 static void
 dump_pair(gpointer data, gpointer user_data)
 {
     name_value_t *pair = data;
     xmlNode *parent = user_data;
 
     crm_xml_add(parent, pair->name, pair->value);
 }
 
 xmlNode *
 sorted_xml(xmlNode * input, xmlNode * parent, gboolean recursive)
 {
     xmlNode *child = NULL;
     GListPtr sorted = NULL;
     GListPtr unsorted = NULL;
     name_value_t *pair = NULL;
     xmlNode *result = NULL;
     const char *name = NULL;
     xmlAttrPtr pIter = NULL;
 
     CRM_CHECK(input != NULL, return NULL);
 
     name = crm_element_name(input);
     CRM_CHECK(name != NULL, return NULL);
 
     result = create_xml_node(parent, name);
 
     for (pIter = crm_first_attr(input); pIter != NULL; pIter = pIter->next) {
         const char *p_name = (const char *)pIter->name;
         const char *p_value = crm_attr_value(pIter);
 
         pair = calloc(1, sizeof(name_value_t));
         pair->name = p_name;
         pair->value = p_value;
         unsorted = g_list_prepend(unsorted, pair);
         pair = NULL;
     }
 
     sorted = g_list_sort(unsorted, sort_pairs);
     g_list_foreach(sorted, dump_pair, result);
     g_list_free_full(sorted, free);
 
     for (child = __xml_first_child(input); child != NULL; child = __xml_next(child)) {
         if (recursive) {
             sorted_xml(child, result, recursive);
         } else {
             add_node_copy(result, child);
         }
     }
 
     return result;
 }
 
 /* "c048eae664dba840e1d2060f00299e9d" */
 static char *
 calculate_xml_digest_v1(xmlNode * input, gboolean sort, gboolean ignored)
 {
     char *digest = NULL;
     char *buffer = NULL;
     xmlNode *copy = NULL;
 
     if (sort) {
         crm_trace("Sorting xml...");
         copy = sorted_xml(input, NULL, TRUE);
         crm_trace("Done");
         input = copy;
     }
 
     buffer = dump_xml_for_digest(input);
     CRM_CHECK(buffer != NULL && strlen(buffer) > 0, free_xml(copy);
               free(buffer);
               return NULL);
 
     digest = crm_md5sum(buffer);
     crm_log_xml_trace(copy, "digest:source");
 
     free(buffer);
     free_xml(copy);
     return digest;
 }
 
 static char *
 calculate_xml_digest_v2(xmlNode * source, gboolean do_filter)
 {
     char *digest = NULL;
     char *buffer = NULL;
     int offset, max;
 
     static struct qb_log_callsite *digest_cs = NULL;
 
     crm_trace("Begin digest %s", do_filter?"filtered":"");
     if (do_filter && BEST_EFFORT_STATUS) {
         /* Exclude the status calculation from the digest
          *
          * This doesn't mean it wont be sync'd, we just wont be paranoid
          * about it being an _exact_ copy
          *
          * We don't need it to be exact, since we throw it away and regenerate
          * from our peers whenever a new DC is elected anyway
          *
          * Importantly, this reduces the amount of XML to copy+export as
          * well as the amount of data for MD5 needs to operate on
          */
 
     } else {
         dump_xml(source, do_filter ? xml_log_option_filtered : 0, &buffer, &offset, &max, 0);
     }
 
     CRM_ASSERT(buffer != NULL);
     digest = crm_md5sum(buffer);
 
     if (digest_cs == NULL) {
         digest_cs = qb_log_callsite_get(__func__, __FILE__, "cib-digest", LOG_TRACE, __LINE__,
                                         crm_trace_nonlog);
     }
     if (digest_cs && digest_cs->targets) {
         char *trace_file = crm_concat("/tmp/cib-digest", digest, '-');
 
         crm_trace("Saving %s.%s.%s to %s",
                   crm_element_value(source, XML_ATTR_GENERATION_ADMIN),
                   crm_element_value(source, XML_ATTR_GENERATION),
                   crm_element_value(source, XML_ATTR_NUMUPDATES), trace_file);
         save_xml_to_file(source, "digest input", trace_file);
         free(trace_file);
     }
 
     free(buffer);
     crm_trace("End digest");
     return digest;
 }
 
 char *
 calculate_on_disk_digest(xmlNode * input)
 {
     /* Always use the v1 format for on-disk digests
      * a) its a compatability nightmare
      * b) we only use this once at startup, all other
      *    invocations are in a separate child process
      */
     return calculate_xml_digest_v1(input, FALSE, FALSE);
 }
 
 char *
 calculate_operation_digest(xmlNode * input, const char *version)
 {
     /* We still need the sorting for parameter digests */
     return calculate_xml_digest_v1(input, TRUE, FALSE);
 }
 
 char *
 calculate_xml_versioned_digest(xmlNode * input, gboolean sort, gboolean do_filter,
                                const char *version)
 {
     /*
      * The sorting associated with v1 digest creation accounted for 23% of
      * the CIB's CPU usage on the server. v2 drops this.
      *
      * The filtering accounts for an additional 2.5% and we may want to
      * remove it in future.
      *
      * v2 also uses the xmlBuffer contents directly to avoid additional copying
      */
     if (version == NULL || compare_version("3.0.5", version) > 0) {
         crm_trace("Using v1 digest algorithm for %s", crm_str(version));
         return calculate_xml_digest_v1(input, sort, do_filter);
     }
     crm_trace("Using v2 digest algorithm for %s", crm_str(version));
     return calculate_xml_digest_v2(input, do_filter);
 }
 
 static gboolean
 validate_with_dtd(xmlDocPtr doc, gboolean to_logs, const char *dtd_file)
 {
     gboolean valid = TRUE;
 
     xmlDtdPtr dtd = NULL;
     xmlValidCtxtPtr cvp = NULL;
 
     CRM_CHECK(doc != NULL, return FALSE);
     CRM_CHECK(dtd_file != NULL, return FALSE);
 
     dtd = xmlParseDTD(NULL, (const xmlChar *)dtd_file);
     if(dtd == NULL) {
         crm_err("Could not locate/parse DTD: %s", dtd_file);
         return TRUE;
     }
 
     cvp = xmlNewValidCtxt();
     if(cvp) {
         if (to_logs) {
             cvp->userData = (void *)LOG_ERR;
             cvp->error = (xmlValidityErrorFunc) xml_log;
             cvp->warning = (xmlValidityWarningFunc) xml_log;
         } else {
             cvp->userData = (void *)stderr;
             cvp->error = (xmlValidityErrorFunc) fprintf;
             cvp->warning = (xmlValidityWarningFunc) fprintf;
         }
 
         if (!xmlValidateDtd(cvp, doc, dtd)) {
             valid = FALSE;
         }
         xmlFreeValidCtxt(cvp);
 
     } else {
         crm_err("Internal error: No valid context");
     }
 
     xmlFreeDtd(dtd);
     return valid;
 }
 
 xmlNode *
 first_named_child(xmlNode * parent, const char *name)
 {
     xmlNode *match = NULL;
 
     for (match = __xml_first_child(parent); match != NULL; match = __xml_next(match)) {
         /*
          * name == NULL gives first child regardless of name; this is
          * semantically incorrect in this funciton, but may be necessary
          * due to prior use of xml_child_iter_filter
          */
         if (name == NULL || strcmp((const char *)match->name, name) == 0) {
             return match;
         }
     }
     return NULL;
 }
 
 #if 0
 static void
 relaxng_invalid_stderr(void *userData, xmlErrorPtr error)
 {
     /*
        Structure xmlError
        struct _xmlError {
        int      domain  : What part of the library raised this er
        int      code    : The error code, e.g. an xmlParserError
        char *   message : human-readable informative error messag
        xmlErrorLevel    level   : how consequent is the error
        char *   file    : the filename
        int      line    : the line number if available
        char *   str1    : extra string information
        char *   str2    : extra string information
        char *   str3    : extra string information
        int      int1    : extra number information
        int      int2    : column number of the error or 0 if N/A
        void *   ctxt    : the parser context if available
        void *   node    : the node in the tree
        }
      */
     crm_err("Structured error: line=%d, level=%d %s", error->line, error->level, error->message);
 }
 #endif
 
 static gboolean
 validate_with_relaxng(xmlDocPtr doc, gboolean to_logs, const char *relaxng_file,
                       relaxng_ctx_cache_t ** cached_ctx)
 {
     int rc = 0;
     gboolean valid = TRUE;
     relaxng_ctx_cache_t *ctx = NULL;
 
     CRM_CHECK(doc != NULL, return FALSE);
     CRM_CHECK(relaxng_file != NULL, return FALSE);
 
     if (cached_ctx && *cached_ctx) {
         ctx = *cached_ctx;
 
     } else {
         crm_info("Creating RNG parser context");
         ctx = calloc(1, sizeof(relaxng_ctx_cache_t));
 
         xmlLoadExtDtdDefaultValue = 1;
         ctx->parser = xmlRelaxNGNewParserCtxt(relaxng_file);
         CRM_CHECK(ctx->parser != NULL, goto cleanup);
 
         if (to_logs) {
             xmlRelaxNGSetParserErrors(ctx->parser,
                                       (xmlRelaxNGValidityErrorFunc) xml_log,
                                       (xmlRelaxNGValidityWarningFunc) xml_log,
                                       GUINT_TO_POINTER(LOG_ERR));
         } else {
             xmlRelaxNGSetParserErrors(ctx->parser,
                                       (xmlRelaxNGValidityErrorFunc) fprintf,
                                       (xmlRelaxNGValidityWarningFunc) fprintf, stderr);
         }
 
         ctx->rng = xmlRelaxNGParse(ctx->parser);
         CRM_CHECK(ctx->rng != NULL, crm_err("Could not find/parse %s", relaxng_file);
                   goto cleanup);
 
         ctx->valid = xmlRelaxNGNewValidCtxt(ctx->rng);
         CRM_CHECK(ctx->valid != NULL, goto cleanup);
 
         if (to_logs) {
             xmlRelaxNGSetValidErrors(ctx->valid,
                                      (xmlRelaxNGValidityErrorFunc) xml_log,
                                      (xmlRelaxNGValidityWarningFunc) xml_log,
                                      GUINT_TO_POINTER(LOG_ERR));
         } else {
             xmlRelaxNGSetValidErrors(ctx->valid,
                                      (xmlRelaxNGValidityErrorFunc) fprintf,
                                      (xmlRelaxNGValidityWarningFunc) fprintf, stderr);
         }
     }
 
     /* xmlRelaxNGSetValidStructuredErrors( */
     /*  valid, relaxng_invalid_stderr, valid); */
 
     xmlLineNumbersDefault(1);
     rc = xmlRelaxNGValidateDoc(ctx->valid, doc);
     if (rc > 0) {
         valid = FALSE;
 
     } else if (rc < 0) {
         crm_err("Internal libxml error during validation\n");
     }
 
   cleanup:
 
     if (cached_ctx) {
         *cached_ctx = ctx;
 
     } else {
         if (ctx->parser != NULL) {
             xmlRelaxNGFreeParserCtxt(ctx->parser);
         }
         if (ctx->valid != NULL) {
             xmlRelaxNGFreeValidCtxt(ctx->valid);
         }
         if (ctx->rng != NULL) {
             xmlRelaxNGFree(ctx->rng);
         }
         free(ctx);
     }
 
     return valid;
 }
 
 void
 crm_xml_init(void)
 {
     static bool init = TRUE;
 
     if(init) {
         init = FALSE;
         /* The default allocator XML_BUFFER_ALLOC_EXACT does far too many
          * realloc()s and it can take upwards of 18 seconds (yes, seconds)
          * to dump a 28kb tree which XML_BUFFER_ALLOC_DOUBLEIT can do in
          * less than 1 second.
          */
         xmlSetBufferAllocationScheme(XML_BUFFER_ALLOC_DOUBLEIT);
     }
 }
 
 void
 crm_xml_cleanup(void)
 {
     int lpc = 0;
     relaxng_ctx_cache_t *ctx = NULL;
 
     crm_info("Cleaning up memory from libxml2");
     for (; lpc < all_schemas; lpc++) {
         switch (known_schemas[lpc].type) {
             case 0:
                 /* None */
                 break;
             case 1:
                 /* DTD - Not cached */
                 break;
             case 2:
                 /* RNG - Cached */
                 ctx = (relaxng_ctx_cache_t *) known_schemas[lpc].cache;
                 if (ctx == NULL) {
                     break;
                 }
                 if (ctx->parser != NULL) {
                     xmlRelaxNGFreeParserCtxt(ctx->parser);
                 }
                 if (ctx->valid != NULL) {
                     xmlRelaxNGFreeValidCtxt(ctx->valid);
                 }
                 if (ctx->rng != NULL) {
                     xmlRelaxNGFree(ctx->rng);
                 }
                 free(ctx);
                 known_schemas[lpc].cache = NULL;
                 break;
             default:
                 break;
         }
     }
     xsltCleanupGlobals();
     xmlCleanupParser();
 }
 
 static gboolean
 validate_with(xmlNode * xml, int method, gboolean to_logs)
 {
     xmlDocPtr doc = NULL;
     gboolean valid = FALSE;
     int type = known_schemas[method].type;
     char *file = NULL;
 
     CRM_CHECK(xml != NULL, return FALSE);
     doc = getDocPtr(xml);
     file = get_schema_path(known_schemas[method].location);
 
     crm_trace("Validating with: %s (type=%d)", crm_str(file), type);
     switch (type) {
         case 0:
             valid = TRUE;
             break;
         case 1:
             valid = validate_with_dtd(doc, to_logs, file);
             break;
         case 2:
             valid =
                 validate_with_relaxng(doc, to_logs, file,
                                       (relaxng_ctx_cache_t **) & (known_schemas[method].cache));
             break;
         default:
             crm_err("Unknown validator type: %d", type);
             break;
     }
 
     free(file);
     return valid;
 }
 
 #include <stdio.h>
 static void
 dump_file(const char *filename)
 {
 
     FILE *fp = NULL;
     int ch, line = 0;
 
     CRM_CHECK(filename != NULL, return);
 
     fp = fopen(filename, "r");
     CRM_CHECK(fp != NULL, return);
 
     fprintf(stderr, "%4d ", ++line);
     do {
         ch = getc(fp);
         if (ch == EOF) {
             putc('\n', stderr);
             break;
         } else if (ch == '\n') {
             fprintf(stderr, "\n%4d ", ++line);
         } else {
             putc(ch, stderr);
         }
     } while (1);
 
     fclose(fp);
 }
 
 gboolean
 validate_xml_verbose(xmlNode * xml_blob)
 {
     int fd = 0;
     xmlDoc *doc = NULL;
     xmlNode *xml = NULL;
     gboolean rc = FALSE;
     char *filename = strdup(CRM_STATE_DIR "/cib-invalid.XXXXXX");
 
     umask(S_IWGRP | S_IWOTH | S_IROTH);
     fd = mkstemp(filename);
     write_xml_fd(xml_blob, filename, fd, FALSE);
 
     dump_file(filename);
 
     doc = xmlParseFile(filename);
     xml = xmlDocGetRootElement(doc);
     rc = validate_xml(xml, NULL, FALSE);
     free_xml(xml);
 
     unlink(filename);
 
     return rc;
 }
 
 gboolean
 validate_xml(xmlNode * xml_blob, const char *validation, gboolean to_logs)
 {
     int lpc = 0;
 
     if (validation == NULL) {
         validation = crm_element_value(xml_blob, XML_ATTR_VALIDATION);
     }
 
     if (validation == NULL) {
         validation = crm_element_value(xml_blob, "ignore-dtd");
         if (crm_is_true(validation)) {
             validation = "none";
         } else {
             validation = "pacemaker-1.0";
         }
     }
 
     if (strcmp(validation, "none") == 0) {
         return TRUE;
     }
 
     for (; lpc < all_schemas; lpc++) {
         if (known_schemas[lpc].name && strcmp(validation, known_schemas[lpc].name) == 0) {
             return validate_with(xml_blob, lpc, to_logs);
         }
     }
 
     crm_err("Unknown validator: %s", validation);
     return FALSE;
 }
 
 #if HAVE_LIBXSLT
 static xmlNode *
 apply_transformation(xmlNode * xml, const char *transform)
 {
     char *xform = NULL;
     xmlNode *out = NULL;
     xmlDocPtr res = NULL;
     xmlDocPtr doc = NULL;
     xsltStylesheet *xslt = NULL;
 
     CRM_CHECK(xml != NULL, return FALSE);
     doc = getDocPtr(xml);
     xform = get_schema_path(transform);
 
     xmlLoadExtDtdDefaultValue = 1;
     xmlSubstituteEntitiesDefault(1);
 
     xslt = xsltParseStylesheetFile((const xmlChar *)xform);
     CRM_CHECK(xslt != NULL, goto cleanup);
 
     res = xsltApplyStylesheet(xslt, doc, NULL);
     CRM_CHECK(res != NULL, goto cleanup);
 
     out = xmlDocGetRootElement(res);
 
   cleanup:
     if (xslt) {
         xsltFreeStylesheet(xslt);
     }
 
     free(xform);
 
     return out;
 }
 #endif
 
 const char *
 get_schema_name(int version)
 {
     if (version < 0 || version >= all_schemas) {
         return "unknown";
     }
     return known_schemas[version].name;
 }
 
 int
 get_schema_version(const char *name)
 {
     int lpc = 0;
 
     for (; lpc < all_schemas; lpc++) {
         if (safe_str_eq(name, known_schemas[lpc].name)) {
             return lpc;
         }
     }
     return -1;
 }
 
 /* set which validation to use */
 #include <crm/cib.h>
 int
 update_validation(xmlNode ** xml_blob, int *best, gboolean transform, gboolean to_logs)
 {
     xmlNode *xml = NULL;
     char *value = NULL;
     int lpc = 0, match = -1, rc = pcmk_ok;
 
     CRM_CHECK(best != NULL, return -EINVAL);
     CRM_CHECK(xml_blob != NULL, return -EINVAL);
     CRM_CHECK(*xml_blob != NULL, return -EINVAL);
 
     *best = 0;
     xml = *xml_blob;
     value = crm_element_value_copy(xml, XML_ATTR_VALIDATION);
 
     if (value != NULL) {
         match = get_schema_version(value);
 
         lpc = match;
         if (lpc >= 0 && transform == FALSE) {
             lpc++;
 
         } else if (lpc < 0) {
             crm_debug("Unknown validation type");
             lpc = 0;
         }
     }
 
     if (match >= max_schemas) {
         /* nothing to do */
         free(value);
         *best = match;
         return pcmk_ok;
     }
 
     for (; lpc < max_schemas; lpc++) {
         gboolean valid = TRUE;
 
         crm_debug("Testing '%s' validation",
                   known_schemas[lpc].name ? known_schemas[lpc].name : "<unset>");
         valid = validate_with(xml, lpc, to_logs);
 
         if (valid) {
             *best = lpc;
         }
 
         if (valid && transform) {
             xmlNode *upgrade = NULL;
             int next = known_schemas[lpc].after_transform;
 
             if (next <= 0) {
                 next = lpc + 1;
             }
 
             crm_notice("Upgrading %s-style configuration to %s with %s",
                        known_schemas[lpc].name, known_schemas[next].name,
                        known_schemas[lpc].transform ? known_schemas[lpc].transform : "no-op");
 
             if (known_schemas[lpc].transform == NULL) {
                 if (validate_with(xml, next, to_logs)) {
                     crm_debug("Configuration valid for schema: %s", known_schemas[next].name);
                     lpc = next;
                     *best = next;
                     rc = pcmk_ok;
 
                 } else {
                     crm_info("Configuration not valid for schema: %s", known_schemas[next].name);
                 }
 
             } else {
 #if HAVE_LIBXSLT
                 upgrade = apply_transformation(xml, known_schemas[lpc].transform);
 #endif
                 if (upgrade == NULL) {
                     crm_err("Transformation %s failed", known_schemas[lpc].transform);
                     rc = -pcmk_err_transform_failed;
 
                 } else if (validate_with(upgrade, next, to_logs)) {
                     crm_info("Transformation %s successful", known_schemas[lpc].transform);
                     lpc = next;
                     *best = next;
                     free_xml(xml);
                     xml = upgrade;
                     rc = pcmk_ok;
 
                 } else {
                     crm_err("Transformation %s did not produce a valid configuration",
                             known_schemas[lpc].transform);
                     crm_log_xml_info(upgrade, "transform:bad");
                     free_xml(upgrade);
                     rc = -pcmk_err_dtd_validation;
                 }
             }
         }
     }
 
     if (*best > match) {
         crm_notice("Upgraded from %s to %s validation", value ? value : "<none>",
                    known_schemas[*best].name);
         crm_xml_add(xml, XML_ATTR_VALIDATION, known_schemas[*best].name);
     }
 
     *xml_blob = xml;
     free(value);
     return rc;
 }
 
 /*
  * From xpath2.c
  *
  * All the elements returned by an XPath query are pointers to
  * elements from the tree *except* namespace nodes where the XPath
  * semantic is different from the implementation in libxml2 tree.
  * As a result when a returned node set is freed when
  * xmlXPathFreeObject() is called, that routine must check the
  * element type. But node from the returned set may have been removed
  * by xmlNodeSetContent() resulting in access to freed data.
  *
  * This can be exercised by running
  *       valgrind xpath2 test3.xml '//discarded' discarded
  *
  * There is 2 ways around it:
  *   - make a copy of the pointers to the nodes from the result set
  *     then call xmlXPathFreeObject() and then modify the nodes
  * or
  * - remove the references from the node set, if they are not
        namespace nodes, before calling xmlXPathFreeObject().
  */
 void
 freeXpathObject(xmlXPathObjectPtr xpathObj)
 {
     int lpc, max = numXpathResults(xpathObj);
 
     if(xpathObj == NULL) {
         return;
     }
 
     for(lpc = 0; lpc < max; lpc++) {
         if (xpathObj->nodesetval->nodeTab[lpc] && xpathObj->nodesetval->nodeTab[lpc]->type != XML_NAMESPACE_DECL) {
             xpathObj->nodesetval->nodeTab[lpc] = NULL;
         }
     }
 
     /* _Now_ its safe to free it */
     xmlXPathFreeObject(xpathObj);
 }
 
 xmlNode *
 getXpathResult(xmlXPathObjectPtr xpathObj, int index)
 {
     xmlNode *match = NULL;
     int max = numXpathResults(xpathObj);
 
     CRM_CHECK(index >= 0, return NULL);
     CRM_CHECK(xpathObj != NULL, return NULL);
 
     if (index >= max) {
         crm_err("Requested index %d of only %d items", index, max);
         return NULL;
 
     } else if(xpathObj->nodesetval->nodeTab[index] == NULL) {
         /* Previously requested */
         return NULL;
     }
 
     match = xpathObj->nodesetval->nodeTab[index];
     CRM_CHECK(match != NULL, return NULL);
 
     if (xpathObj->nodesetval->nodeTab[index]->type != XML_NAMESPACE_DECL) {
         /* See the comment for freeXpathObject() */
         xpathObj->nodesetval->nodeTab[index] = NULL;
     }
 
     if (match->type == XML_DOCUMENT_NODE) {
         /* Will happen if section = '/' */
         match = match->children;
 
     } else if (match->type != XML_ELEMENT_NODE
                && match->parent && match->parent->type == XML_ELEMENT_NODE) {
         /* reurning the parent instead */
         match = match->parent;
 
     } else if (match->type != XML_ELEMENT_NODE) {
         /* We only support searching nodes */
         crm_err("We only support %d not %d", XML_ELEMENT_NODE, match->type);
         match = NULL;
     }
     return match;
 }
 
 /* the caller needs to check if the result contains a xmlDocPtr or xmlNodePtr */
 xmlXPathObjectPtr
 xpath_search(xmlNode * xml_top, const char *path)
 {
     xmlDocPtr doc = NULL;
     xmlXPathObjectPtr xpathObj = NULL;
     xmlXPathContextPtr xpathCtx = NULL;
     const xmlChar *xpathExpr = (const xmlChar *)path;
 
     CRM_CHECK(path != NULL, return NULL);
     CRM_CHECK(xml_top != NULL, return NULL);
     CRM_CHECK(strlen(path) > 0, return NULL);
 
     doc = getDocPtr(xml_top);
 
     xpathCtx = xmlXPathNewContext(doc);
     CRM_ASSERT(xpathCtx != NULL);
 
     xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
     xmlXPathFreeContext(xpathCtx);
     return xpathObj;
 }
 
 gboolean
 cli_config_update(xmlNode ** xml, int *best_version, gboolean to_logs)
 {
     gboolean rc = TRUE;
     static int min_version = -1;
     static int max_version = -1;
 
     const char *value = crm_element_value(*xml, XML_ATTR_VALIDATION);
     int version = get_schema_version(value);
 
     if (min_version < 0) {
         min_version = get_schema_version(MINIMUM_SCHEMA_VERSION);
     }
     if (max_version < 0) {
         max_version = get_schema_version(LATEST_SCHEMA_VERSION);
     }
 
     if (version < min_version) {
         xmlNode *converted = NULL;
 
         converted = copy_xml(*xml);
         update_validation(&converted, &version, TRUE, to_logs);
 
         value = crm_element_value(converted, XML_ATTR_VALIDATION);
         if (version < min_version) {
             if (to_logs) {
                 crm_config_err("Your current configuration could only be upgraded to %s... "
                                "the minimum requirement is %s.\n", crm_str(value),
                                MINIMUM_SCHEMA_VERSION);
             } else {
                 fprintf(stderr, "Your current configuration could only be upgraded to %s... "
                         "the minimum requirement is %s.\n", crm_str(value), MINIMUM_SCHEMA_VERSION);
             }
 
             free_xml(converted);
             converted = NULL;
             rc = FALSE;
 
         } else {
             free_xml(*xml);
             *xml = converted;
 
             if (version < max_version) {
                 crm_config_warn("Your configuration was internally updated to %s... "
                                 "which is acceptable but not the most recent",
                                 get_schema_name(version));
 
             } else if (to_logs) {
                 crm_info("Your configuration was internally updated to the latest version (%s)",
                          get_schema_name(version));
             }
         }
     } else if (version > max_version) {
         if (to_logs) {
             crm_config_warn("Configuration validation is currently disabled."
                             " It is highly encouraged and prevents many common cluster issues.");
 
         } else {
             fprintf(stderr, "Configuration validation is currently disabled."
                     " It is highly encouraged and prevents many common cluster issues.\n");
         }
     }
 
     if (best_version) {
         *best_version = version;
     }
 
     return rc;
 }
 
 xmlNode *
 expand_idref(xmlNode * input, xmlNode * top)
 {
     const char *tag = NULL;
     const char *ref = NULL;
     xmlNode *result = input;
     char *xpath_string = NULL;
 
     if (result == NULL) {
         return NULL;
 
     } else if (top == NULL) {
         top = input;
     }
 
     tag = crm_element_name(result);
     ref = crm_element_value(result, XML_ATTR_IDREF);
 
     if (ref != NULL) {
         int xpath_max = 512, offset = 0;
 
         xpath_string = calloc(1, xpath_max);
 
         offset += snprintf(xpath_string + offset, xpath_max - offset, "//%s[@id='%s']", tag, ref);
         result = get_xpath_object(xpath_string, top, LOG_ERR);
         if (result == NULL) {
             char *nodePath = (char *)xmlGetNodePath(top);
 
             crm_err("No match for %s found in %s: Invalid configuration", xpath_string,
                     crm_str(nodePath));
             free(nodePath);
         }
     }
 
     free(xpath_string);
     return result;
 }
 
 xmlNode *
 get_xpath_object_relative(const char *xpath, xmlNode * xml_obj, int error_level)
 {
     int len = 0;
     xmlNode *result = NULL;
     char *xpath_full = NULL;
     char *xpath_prefix = NULL;
 
     if (xml_obj == NULL || xpath == NULL) {
         return NULL;
     }
 
     xpath_prefix = (char *)xmlGetNodePath(xml_obj);
     len += strlen(xpath_prefix);
     len += strlen(xpath);
 
     xpath_full = strdup(xpath_prefix);
     xpath_full = realloc(xpath_full, len + 1);
     strncat(xpath_full, xpath, len);
 
     result = get_xpath_object(xpath_full, xml_obj, error_level);
 
     free(xpath_prefix);
     free(xpath_full);
     return result;
 }
 
 xmlNode *
 get_xpath_object(const char *xpath, xmlNode * xml_obj, int error_level)
 {
     int max;
     xmlNode *result = NULL;
     xmlXPathObjectPtr xpathObj = NULL;
     char *nodePath = NULL;
     char *matchNodePath = NULL;
 
     if (xpath == NULL) {
         return xml_obj;         /* or return NULL? */
     }
 
     xpathObj = xpath_search(xml_obj, xpath);
     nodePath = (char *)xmlGetNodePath(xml_obj);
     max = numXpathResults(xpathObj);
 
     if (max < 1) {
         do_crm_log(error_level, "No match for %s in %s", xpath, crm_str(nodePath));
         crm_log_xml_explicit(xml_obj, "Unexpected Input");
 
     } else if (max > 1) {
         int lpc = 0;
 
         do_crm_log(error_level, "Too many matches for %s in %s", xpath, crm_str(nodePath));
 
         for (lpc = 0; lpc < max; lpc++) {
             xmlNode *match = getXpathResult(xpathObj, lpc);
 
             CRM_CHECK(match != NULL, continue);
 
             matchNodePath = (char *)xmlGetNodePath(match);
             do_crm_log(error_level, "%s[%d] = %s", xpath, lpc, crm_str(matchNodePath));
             free(matchNodePath);
         }
         crm_log_xml_explicit(xml_obj, "Bad Input");
 
     } else {
         result = getXpathResult(xpathObj, 0);
     }
 
     freeXpathObject(xpathObj);
     free(nodePath);
 
     return result;
 }
 
 const char *
 crm_element_value(xmlNode * data, const char *name)
 {
     xmlAttr *attr = NULL;
 
     if (data == NULL) {
         crm_err("Couldn't find %s in NULL", name ? name : "<null>");
         CRM_LOG_ASSERT(data != NULL);
         return NULL;
 
     } else if (name == NULL) {
         crm_err("Couldn't find NULL in %s", crm_element_name(data));
         return NULL;
     }
 
     attr = xmlHasProp(data, (const xmlChar *)name);
     if (attr == NULL || attr->children == NULL) {
         return NULL;
     }
     return (const char *)attr->children->content;
 }
diff --git a/pengine/group.c b/pengine/group.c
index c1c1d48a62..15c058fc1f 100644
--- a/pengine/group.c
+++ b/pengine/group.c
@@ -1,517 +1,517 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  * 
  * This software 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
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <crm_internal.h>
 
 #include <pengine.h>
 #include <crm/msg_xml.h>
 
 #include <allocate.h>
 #include <utils.h>
 
 #define VARIANT_GROUP 1
 #include <lib/pengine/variant.h>
 
 node_t *
 group_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set)
 {
     node_t *node = NULL;
     node_t *group_node = NULL;
     GListPtr gIter = NULL;
     group_variant_data_t *group_data = NULL;
 
     get_group_variant_data(group_data, rsc);
 
     if (is_not_set(rsc->flags, pe_rsc_provisional)) {
         return rsc->allocated_to;
     }
     pe_rsc_trace(rsc, "Processing %s", rsc->id);
     if (is_set(rsc->flags, pe_rsc_allocating)) {
         pe_rsc_debug(rsc, "Dependency loop detected involving %s", rsc->id);
         return NULL;
     }
 
     if (group_data->first_child == NULL) {
         /* nothign to allocate */
         clear_bit(rsc->flags, pe_rsc_provisional);
         return NULL;
     }
 
     set_bit(rsc->flags, pe_rsc_allocating);
     rsc->role = group_data->first_child->role;
 
     group_data->first_child->rsc_cons =
         g_list_concat(group_data->first_child->rsc_cons, rsc->rsc_cons);
     rsc->rsc_cons = NULL;
 
     group_data->last_child->rsc_cons_lhs =
         g_list_concat(group_data->last_child->rsc_cons_lhs, rsc->rsc_cons_lhs);
     rsc->rsc_cons_lhs = NULL;
 
-    dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __PRETTY_FUNCTION__,
+    dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __FUNCTION__,
                      rsc->allowed_nodes);
 
     gIter = rsc->children;
     for (; gIter != NULL; gIter = gIter->next) {
         resource_t *child_rsc = (resource_t *) gIter->data;
 
         node = child_rsc->cmds->allocate(child_rsc, prefer, data_set);
         if (group_node == NULL) {
             group_node = node;
         }
     }
 
     rsc->next_role = group_data->first_child->next_role;
     clear_bit(rsc->flags, pe_rsc_allocating);
     clear_bit(rsc->flags, pe_rsc_provisional);
 
     if (group_data->colocated) {
         return group_node;
     }
     return NULL;
 }
 
 void group_update_pseudo_status(resource_t * parent, resource_t * child);
 
 void
 group_create_actions(resource_t * rsc, pe_working_set_t * data_set)
 {
     action_t *op = NULL;
     const char *value = NULL;
     GListPtr gIter = rsc->children;
 
     pe_rsc_trace(rsc, "Creating actions for %s", rsc->id);
 
     for (; gIter != NULL; gIter = gIter->next) {
         resource_t *child_rsc = (resource_t *) gIter->data;
 
         child_rsc->cmds->create_actions(child_rsc, data_set);
         group_update_pseudo_status(rsc, child_rsc);
     }
 
     op = start_action(rsc, NULL, TRUE /* !group_data->child_starting */ );
     set_bit(op->flags, pe_action_pseudo | pe_action_runnable);
 
     op = custom_action(rsc, started_key(rsc),
                        RSC_STARTED, NULL, TRUE /* !group_data->child_starting */ , TRUE, data_set);
     set_bit(op->flags, pe_action_pseudo | pe_action_runnable);
 
     op = stop_action(rsc, NULL, TRUE /* !group_data->child_stopping */ );
     set_bit(op->flags, pe_action_pseudo | pe_action_runnable);
 
     op = custom_action(rsc, stopped_key(rsc),
                        RSC_STOPPED, NULL, TRUE /* !group_data->child_stopping */ , TRUE, data_set);
     set_bit(op->flags, pe_action_pseudo | pe_action_runnable);
 
     value = g_hash_table_lookup(rsc->meta, "stateful");
     if (crm_is_true(value)) {
         op = custom_action(rsc, demote_key(rsc), RSC_DEMOTE, NULL, TRUE, TRUE, data_set);
         set_bit(op->flags, pe_action_pseudo);
         set_bit(op->flags, pe_action_runnable);
         op = custom_action(rsc, demoted_key(rsc), RSC_DEMOTED, NULL, TRUE, TRUE, data_set);
         set_bit(op->flags, pe_action_pseudo);
         set_bit(op->flags, pe_action_runnable);
 
         op = custom_action(rsc, promote_key(rsc), RSC_PROMOTE, NULL, TRUE, TRUE, data_set);
         set_bit(op->flags, pe_action_pseudo);
         set_bit(op->flags, pe_action_runnable);
         op = custom_action(rsc, promoted_key(rsc), RSC_PROMOTED, NULL, TRUE, TRUE, data_set);
         set_bit(op->flags, pe_action_pseudo);
         set_bit(op->flags, pe_action_runnable);
     }
 }
 
 void
 group_update_pseudo_status(resource_t * parent, resource_t * child)
 {
     GListPtr gIter = child->actions;
     group_variant_data_t *group_data = NULL;
 
     get_group_variant_data(group_data, parent);
 
     if (group_data->ordered == FALSE) {
         /* If this group is not ordered, then leave the meta-actions as optional */
         return;
     }
 
     if (group_data->child_stopping && group_data->child_starting) {
         return;
     }
 
     for (; gIter != NULL; gIter = gIter->next) {
         action_t *action = (action_t *) gIter->data;
 
         if (is_set(action->flags, pe_action_optional)) {
             continue;
         }
         if (safe_str_eq(RSC_STOP, action->task) && is_set(action->flags, pe_action_runnable)) {
             group_data->child_stopping = TRUE;
             pe_rsc_trace(action->rsc, "Based on %s the group is stopping", action->uuid);
 
         } else if (safe_str_eq(RSC_START, action->task)
                    && is_set(action->flags, pe_action_runnable)) {
             group_data->child_starting = TRUE;
             pe_rsc_trace(action->rsc, "Based on %s the group is starting", action->uuid);
         }
     }
 }
 
 void
 group_internal_constraints(resource_t * rsc, pe_working_set_t * data_set)
 {
     GListPtr gIter = rsc->children;
     resource_t *last_rsc = NULL;
     resource_t *last_active = NULL;
     resource_t *top = uber_parent(rsc);
     group_variant_data_t *group_data = NULL;
 
     get_group_variant_data(group_data, rsc);
 
     new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_START, pe_order_optional, data_set);
     new_rsc_order(rsc, RSC_START, rsc, RSC_STARTED, pe_order_runnable_left, data_set);
     new_rsc_order(rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_runnable_left, data_set);
 
     for (; gIter != NULL; gIter = gIter->next) {
         resource_t *child_rsc = (resource_t *) gIter->data;
         int stop = pe_order_none;
         int stopped = pe_order_implies_then_printed;
         int start = pe_order_implies_then | pe_order_runnable_left;
         int started =
             pe_order_runnable_left | pe_order_implies_then | pe_order_implies_then_printed;
 
         child_rsc->cmds->internal_constraints(child_rsc, data_set);
 
         if (last_rsc == NULL) {
             if (group_data->ordered) {
                 stop |= pe_order_optional;
                 stopped = pe_order_implies_then;
             }
 
         } else if (group_data->colocated) {
             rsc_colocation_new("group:internal_colocation", NULL, INFINITY,
                                child_rsc, last_rsc, NULL, NULL, data_set);
         }
 
         if (top->variant == pe_master) {
             new_rsc_order(rsc, RSC_DEMOTE, child_rsc, RSC_DEMOTE,
                           stop | pe_order_implies_first_printed, data_set);
 
             new_rsc_order(child_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stopped, data_set);
 
             new_rsc_order(child_rsc, RSC_PROMOTE, rsc, RSC_PROMOTED, started, data_set);
 
             new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE,
                           pe_order_implies_first_printed, data_set);
 
         }
 
         order_start_start(rsc, child_rsc, pe_order_implies_first_printed);
         order_stop_stop(rsc, child_rsc, stop | pe_order_implies_first_printed);
 
         new_rsc_order(child_rsc, RSC_STOP, rsc, RSC_STOPPED, stopped, data_set);
 
         new_rsc_order(child_rsc, RSC_START, rsc, RSC_STARTED, started, data_set);
 
         if (group_data->ordered == FALSE) {
             order_start_start(rsc, child_rsc, start | pe_order_implies_first_printed);
             if (top->variant == pe_master) {
                 new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE,
                               start | pe_order_implies_first_printed, data_set);
             }
 
         } else if (last_rsc != NULL) {
             child_rsc->restart_type = pe_restart_restart;
 
             order_start_start(last_rsc, child_rsc, start);
             order_stop_stop(child_rsc, last_rsc, pe_order_optional | pe_order_restart);
 
             if (top->variant == pe_master) {
                 new_rsc_order(last_rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, start, data_set);
                 new_rsc_order(child_rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, pe_order_optional,
                               data_set);
             }
 
         } else {
             /* If anyone in the group is starting, then
              *  pe_order_implies_then will cause _everyone_ in the group
              *  to be sent a start action
              * But this is safe since starting something that is already
              *  started is required to be "safe"
              */
             int flags = pe_order_none;
 
             order_start_start(rsc, child_rsc, flags);
             if (top->variant == pe_master) {
                 new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, flags, data_set);
             }
 
         }
 
         /* Look for partially active groups
          * Make sure they still shut down in sequence
          */
         if (child_rsc->running_on) {
             if (group_data->ordered
                 && last_rsc
                 && last_rsc->running_on == NULL && last_active && last_active->running_on) {
                 order_stop_stop(child_rsc, last_active, pe_order_optional);
             }
             last_active = child_rsc;
         }
 
         last_rsc = child_rsc;
     }
 
     if (group_data->ordered && last_rsc != NULL) {
         int stop_stop_flags = pe_order_implies_then;
         int stop_stopped_flags = pe_order_optional;
 
         order_stop_stop(rsc, last_rsc, stop_stop_flags);
         new_rsc_order(last_rsc, RSC_STOP, rsc, RSC_STOPPED, stop_stopped_flags, data_set);
 
         if (top->variant == pe_master) {
             new_rsc_order(rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, stop_stop_flags, data_set);
             new_rsc_order(last_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stop_stopped_flags, data_set);
         }
     }
 }
 
 void
 group_rsc_colocation_lh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
 {
     GListPtr gIter = NULL;
     group_variant_data_t *group_data = NULL;
 
     if (rsc_lh == NULL) {
         pe_err("rsc_lh was NULL for %s", constraint->id);
         return;
 
     } else if (rsc_rh == NULL) {
         pe_err("rsc_rh was NULL for %s", constraint->id);
         return;
     }
 
     gIter = rsc_lh->children;
     pe_rsc_trace(rsc_lh, "Processing constraints from %s", rsc_lh->id);
 
     get_group_variant_data(group_data, rsc_lh);
 
     if (group_data->colocated) {
         group_data->first_child->cmds->rsc_colocation_lh(group_data->first_child, rsc_rh,
                                                          constraint);
         return;
 
     } else if (constraint->score >= INFINITY) {
         crm_config_err("%s: Cannot perform manditory colocation"
                        " between non-colocated group and %s", rsc_lh->id, rsc_rh->id);
         return;
     }
 
     for (; gIter != NULL; gIter = gIter->next) {
         resource_t *child_rsc = (resource_t *) gIter->data;
 
         child_rsc->cmds->rsc_colocation_lh(child_rsc, rsc_rh, constraint);
     }
 }
 
 void
 group_rsc_colocation_rh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
 {
     GListPtr gIter = rsc_rh->children;
     group_variant_data_t *group_data = NULL;
 
     get_group_variant_data(group_data, rsc_rh);
     CRM_CHECK(rsc_lh->variant == pe_native, return);
 
     pe_rsc_trace(rsc_rh, "Processing RH of constraint %s", constraint->id);
     print_resource(LOG_DEBUG_3, "LHS", rsc_lh, TRUE);
 
     if (is_set(rsc_rh->flags, pe_rsc_provisional)) {
         return;
 
     } else if (group_data->colocated && group_data->first_child) {
         if (constraint->score >= INFINITY) {
             /* Ensure RHS is _fully_ up before can start LHS */
             group_data->last_child->cmds->rsc_colocation_rh(rsc_lh, group_data->last_child,
                                                             constraint);
         } else {
             /* A partially active RHS is fine */
             group_data->first_child->cmds->rsc_colocation_rh(rsc_lh, group_data->first_child,
                                                              constraint);
         }
 
         return;
 
     } else if (constraint->score >= INFINITY) {
         crm_config_err("%s: Cannot perform manditory colocation with"
                        " non-colocated group: %s", rsc_lh->id, rsc_rh->id);
         return;
     }
 
     for (; gIter != NULL; gIter = gIter->next) {
         resource_t *child_rsc = (resource_t *) gIter->data;
 
         child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint);
     }
 }
 
 enum pe_action_flags
 group_action_flags(action_t * action, node_t * node)
 {
     GListPtr gIter = NULL;
     enum pe_action_flags flags = (pe_action_optional | pe_action_runnable | pe_action_pseudo);
 
     for (gIter = action->rsc->children; gIter != NULL; gIter = gIter->next) {
         resource_t *child = (resource_t *) gIter->data;
         enum action_tasks task = get_complex_task(child, action->task, TRUE);
         const char *task_s = task2text(task);
         action_t *child_action = find_first_action(child->actions, NULL, task_s, node);
 
         if (child_action) {
             enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node);
 
             if (is_set(flags, pe_action_optional)
                 && is_set(child_flags, pe_action_optional) == FALSE) {
                 pe_rsc_trace(action->rsc, "%s is manditory because of %s", action->uuid,
                              child_action->uuid);
                 clear_bit(flags, pe_action_optional);
                 pe_clear_action_bit(action, pe_action_optional);
             }
             if (safe_str_neq(task_s, action->task)
                 && is_set(flags, pe_action_runnable)
                 && is_set(child_flags, pe_action_runnable) == FALSE) {
                 pe_rsc_trace(action->rsc, "%s is not runnable because of %s", action->uuid,
                              child_action->uuid);
                 clear_bit(flags, pe_action_runnable);
                 pe_clear_action_bit(action, pe_action_runnable);
             }
 
         } else if (task != stop_rsc && task != action_demote) {
             pe_rsc_trace(action->rsc, "%s is not runnable because of %s (not found in %s)",
                          action->uuid, task_s, child->id);
             clear_bit(flags, pe_action_runnable);
         }
     }
 
     return flags;
 }
 
 enum pe_graph_flags
 group_update_actions(action_t * first, action_t * then, node_t * node, enum pe_action_flags flags,
                      enum pe_action_flags filter, enum pe_ordering type)
 {
     GListPtr gIter = then->rsc->children;
     enum pe_graph_flags changed = pe_graph_none;
 
     CRM_ASSERT(then->rsc != NULL);
     changed |= native_update_actions(first, then, node, flags, filter, type);
 
     for (; gIter != NULL; gIter = gIter->next) {
         resource_t *child = (resource_t *) gIter->data;
         action_t *child_action = find_first_action(child->actions, NULL, then->task, node);
 
         if (child_action) {
             changed |= child->cmds->update_actions(first, child_action, node, flags, filter, type);
         }
     }
 
     return changed;
 }
 
 void
 group_rsc_location(resource_t * rsc, rsc_to_node_t * constraint)
 {
     GListPtr gIter = rsc->children;
     GListPtr saved = constraint->node_list_rh;
     GListPtr zero = node_list_dup(constraint->node_list_rh, TRUE, FALSE);
     gboolean reset_scores = TRUE;
     group_variant_data_t *group_data = NULL;
 
     get_group_variant_data(group_data, rsc);
 
     pe_rsc_debug(rsc, "Processing rsc_location %s for %s", constraint->id, rsc->id);
 
     native_rsc_location(rsc, constraint);
 
     for (; gIter != NULL; gIter = gIter->next) {
         resource_t *child_rsc = (resource_t *) gIter->data;
 
         child_rsc->cmds->rsc_location(child_rsc, constraint);
         if (group_data->colocated && reset_scores) {
             reset_scores = FALSE;
             constraint->node_list_rh = zero;
         }
     }
 
     constraint->node_list_rh = saved;
     g_list_free_full(zero, free);
 }
 
 void
 group_expand(resource_t * rsc, pe_working_set_t * data_set)
 {
     GListPtr gIter = rsc->children;
 
     pe_rsc_trace(rsc, "Processing actions from %s", rsc->id);
 
     CRM_CHECK(rsc != NULL, return);
     native_expand(rsc, data_set);
 
     for (; gIter != NULL; gIter = gIter->next) {
         resource_t *child_rsc = (resource_t *) gIter->data;
 
         child_rsc->cmds->expand(child_rsc, data_set);
     }
 }
 
 GHashTable *
 group_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes, const char *attr,
                     float factor, enum pe_weights flags)
 {
     GListPtr gIter = rsc->rsc_cons_lhs;
     group_variant_data_t *group_data = NULL;
 
     get_group_variant_data(group_data, rsc);
 
     if (is_set(rsc->flags, pe_rsc_merging)) {
         pe_rsc_info(rsc, "Breaking dependency loop with %s at %s", rsc->id, rhs);
         return nodes;
     }
 
     set_bit(rsc->flags, pe_rsc_merging);
 
     nodes =
         group_data->first_child->cmds->merge_weights(group_data->first_child, rhs, nodes, attr,
                                                      factor, flags);
 
     for (; gIter != NULL; gIter = gIter->next) {
         rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
 
         nodes = native_merge_weights(constraint->rsc_lh, rsc->id, nodes,
                                      constraint->node_attribute,
                                      (float)constraint->score / INFINITY, flags);
     }
 
     clear_bit(rsc->flags, pe_rsc_merging);
     return nodes;
 }
 
 void
 group_append_meta(resource_t * rsc, xmlNode * xml)
 {
 }
diff --git a/pengine/native.c b/pengine/native.c
index 0a323fef0e..448335a524 100644
--- a/pengine/native.c
+++ b/pengine/native.c
@@ -1,3309 +1,3309 @@
 /*
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This software 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
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <crm_internal.h>
 
 #include <pengine.h>
 #include <crm/pengine/rules.h>
 #include <crm/msg_xml.h>
 #include <allocate.h>
 #include <utils.h>
 #include <crm/services.h>
 
 /* #define DELETE_THEN_REFRESH 1  // The crmd will remove the resource from the CIB itself, making this redundant */
 #define INFINITY_HACK   (INFINITY * -100)
 
 #define VARIANT_NATIVE 1
 #include <lib/pengine/variant.h>
 
 void native_rsc_colocation_rh_must(resource_t * rsc_lh, gboolean update_lh,
                                    resource_t * rsc_rh, gboolean update_rh);
 
 void native_rsc_colocation_rh_mustnot(resource_t * rsc_lh, gboolean update_lh,
                                       resource_t * rsc_rh, gboolean update_rh);
 
 void Recurring(resource_t * rsc, action_t * start, node_t * node, pe_working_set_t * data_set);
 void RecurringOp(resource_t * rsc, action_t * start, node_t * node,
                  xmlNode * operation, pe_working_set_t * data_set);
 void Recurring_Stopped(resource_t * rsc, action_t * start, node_t * node,
                        pe_working_set_t * data_set);
 void RecurringOp_Stopped(resource_t * rsc, action_t * start, node_t * node,
                          xmlNode * operation, pe_working_set_t * data_set);
 void pe_post_notify(resource_t * rsc, node_t * node, action_t * op,
                     notify_data_t * n_data, pe_working_set_t * data_set);
 
 gboolean DeleteRsc(resource_t * rsc, node_t * node, gboolean optional, pe_working_set_t * data_set);
 gboolean StopRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
 gboolean StartRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
 gboolean DemoteRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
 gboolean PromoteRsc(resource_t * rsc, node_t * next, gboolean optional,
                     pe_working_set_t * data_set);
 gboolean RoleError(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
 gboolean NullOp(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set);
 
 /* *INDENT-OFF* */
 enum rsc_role_e rsc_state_matrix[RSC_ROLE_MAX][RSC_ROLE_MAX] = {
 /* Current State */
 /*       Next State:    Unknown 	  Stopped	     Started	        Slave	          Master */
     /* Unknown */ { RSC_ROLE_UNKNOWN, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, },
     /* Stopped */ { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STARTED, RSC_ROLE_SLAVE,   RSC_ROLE_SLAVE, },
     /* Started */ { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STARTED, RSC_ROLE_SLAVE,   RSC_ROLE_MASTER, },
     /* Slave */	  { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_SLAVE,   RSC_ROLE_MASTER, },
     /* Master */  { RSC_ROLE_STOPPED, RSC_ROLE_SLAVE,   RSC_ROLE_SLAVE,   RSC_ROLE_SLAVE,   RSC_ROLE_MASTER, },
 };
 
 gboolean (*rsc_action_matrix[RSC_ROLE_MAX][RSC_ROLE_MAX])(resource_t*,node_t*,gboolean,pe_working_set_t*) = {
 /* Current State */
 /*       Next State:       Unknown	Stopped		Started		Slave		Master */
     /* Unknown */	{ RoleError,	StopRsc,	RoleError,	RoleError,	RoleError,  },
     /* Stopped */	{ RoleError,	NullOp,		StartRsc,	StartRsc,	RoleError,  },
     /* Started */	{ RoleError,	StopRsc,	NullOp,		NullOp,		PromoteRsc, },
     /* Slave */	        { RoleError,	StopRsc,	StopRsc, 	NullOp,		PromoteRsc, },
     /* Master */	{ RoleError,	DemoteRsc,	DemoteRsc,	DemoteRsc,	NullOp,     },
 };
 /* *INDENT-ON* */
 
 struct capacity_data {
     node_t *node;
     resource_t *rsc;
     gboolean is_enough;
 };
 
 static void
 check_capacity(gpointer key, gpointer value, gpointer user_data)
 {
     int required = 0;
     int remaining = 0;
     struct capacity_data *data = user_data;
 
     required = crm_parse_int(value, "0");
     remaining = crm_parse_int(g_hash_table_lookup(data->node->details->utilization, key), "0");
 
     if (required > remaining) {
         pe_rsc_debug(data->rsc,
                      "Node %s has no enough %s for resource %s: required=%d remaining=%d",
                      data->node->details->uname, (char *)key, data->rsc->id, required, remaining);
         data->is_enough = FALSE;
     }
 }
 
 static gboolean
 have_enough_capacity(node_t * node, resource_t * rsc)
 {
     struct capacity_data data;
 
     data.node = node;
     data.rsc = rsc;
     data.is_enough = TRUE;
 
     g_hash_table_foreach(rsc->utilization, check_capacity, &data);
 
     return data.is_enough;
 }
 
 static gboolean
 native_choose_node(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set)
 {
     /*
        1. Sort by weight
        2. color.chosen_node = the node (of those with the highest wieght)
        with the fewest resources
        3. remove color.chosen_node from all other colors
      */
     int alloc_details = scores_log_level + 1;
 
     GListPtr nodes = NULL;
     node_t *chosen = NULL;
 
     int lpc = 0;
     int multiple = 0;
     int length = 0;
     gboolean result = FALSE;
 
     if (safe_str_neq(data_set->placement_strategy, "default")) {
         GListPtr gIter = NULL;
 
         for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
             node_t *node = (node_t *) gIter->data;
 
             if (have_enough_capacity(node, rsc) == FALSE) {
                 pe_rsc_debug(rsc,
                              "Resource %s cannot be allocated to node %s: none of enough capacity",
                              rsc->id, node->details->uname);
                 resource_location(rsc, node, -INFINITY, "__limit_utilization_", data_set);
             }
         }
         dump_node_scores(alloc_details, rsc, "Post-utilization", rsc->allowed_nodes);
     }
 
     length = g_hash_table_size(rsc->allowed_nodes);
 
     if (is_not_set(rsc->flags, pe_rsc_provisional)) {
         return rsc->allocated_to ? TRUE : FALSE;
     }
 
     if (prefer) {
         chosen = g_hash_table_lookup(rsc->allowed_nodes, prefer->details->id);
         if (chosen && chosen->weight >= 0 && can_run_resources(chosen)) {
             pe_rsc_trace(rsc,
                          "Using preferred node %s for %s instead of choosing from %d candidates",
                          chosen->details->uname, rsc->id, length);
         } else if (chosen && chosen->weight < 0) {
             pe_rsc_trace(rsc, "Preferred node %s for %s was unavailable", chosen->details->uname,
                          rsc->id);
             chosen = NULL;
         } else if (chosen && can_run_resources(chosen)) {
             pe_rsc_trace(rsc, "Preferred node %s for %s was unsuitable", chosen->details->uname,
                          rsc->id);
             chosen = NULL;
         } else {
             pe_rsc_trace(rsc, "Preferred node %s for %s was unknown", prefer->details->uname,
                          rsc->id);
         }
     }
 
     if (chosen == NULL && rsc->allowed_nodes) {
         nodes = g_hash_table_get_values(rsc->allowed_nodes);
         nodes = g_list_sort_with_data(nodes, sort_node_weight, g_list_nth_data(rsc->running_on, 0));
 
         chosen = g_list_nth_data(nodes, 0);
         pe_rsc_trace(rsc, "Chose node %s for %s from %d candidates",
                      chosen ? chosen->details->uname : "<none>", rsc->id, length);
 
         if (chosen && chosen->weight > 0 && can_run_resources(chosen)) {
             node_t *running = g_list_nth_data(rsc->running_on, 0);
 
             if (running && can_run_resources(running) == FALSE) {
                 pe_rsc_trace(rsc, "Current node for %s (%s) can't run resources",
                              rsc->id, running->details->uname);
                 running = NULL;
             }
 
             for (lpc = 1; lpc < length && running; lpc++) {
                 node_t *tmp = g_list_nth_data(nodes, lpc);
 
                 if (tmp->weight == chosen->weight) {
                     multiple++;
                     if (tmp->details == running->details) {
                         /* prefer the existing node if scores are equal */
                         chosen = tmp;
                     }
                 }
             }
         }
     }
 
     if (multiple > 1) {
         int log_level = LOG_INFO;
         char *score = score2char(chosen->weight);
 
         if (chosen->weight >= INFINITY) {
             log_level = LOG_WARNING;
         }
 
         do_crm_log(log_level, "%d nodes with equal score (%s) for"
                    " running %s resources.  Chose %s.",
                    multiple, score, rsc->id, chosen->details->uname);
         free(score);
     }
 
     result = native_assign_node(rsc, nodes, chosen, FALSE);
     g_list_free(nodes);
     return result;
 }
 
 static int
 node_list_attr_score(GHashTable * list, const char *attr, const char *value)
 {
     GHashTableIter iter;
     node_t *node = NULL;
     int best_score = -INFINITY;
     const char *best_node = NULL;
 
     if (attr == NULL) {
         attr = "#" XML_ATTR_UNAME;
     }
 
     g_hash_table_iter_init(&iter, list);
     while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
         int weight = node->weight;
 
         if (can_run_resources(node) == FALSE) {
             weight = -INFINITY;
         }
         if (weight > best_score || best_node == NULL) {
             const char *tmp = g_hash_table_lookup(node->details->attrs, attr);
 
             if (safe_str_eq(value, tmp)) {
                 best_score = weight;
                 best_node = node->details->uname;
             }
         }
     }
 
     if (safe_str_neq(attr, "#" XML_ATTR_UNAME)) {
         crm_info("Best score for %s=%s was %s with %d",
                  attr, value, best_node ? best_node : "<none>", best_score);
     }
 
     return best_score;
 }
 
 static void
 node_hash_update(GHashTable * list1, GHashTable * list2, const char *attr, float factor,
                  gboolean only_positive)
 {
     int score = 0;
     int new_score = 0;
     GHashTableIter iter;
     node_t *node = NULL;
 
     if (attr == NULL) {
         attr = "#" XML_ATTR_UNAME;
     }
 
     g_hash_table_iter_init(&iter, list1);
     while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
         CRM_CHECK(node != NULL, continue);
         score = node_list_attr_score(list2, attr, g_hash_table_lookup(node->details->attrs, attr));
         new_score = merge_weights(factor * score, node->weight);
 
         if (factor < 0 && score < 0) {
             /* Negative preference for a node with a negative score
              * should not become a positive preference
              *
              * TODO - Decide if we want to filter only if weight == -INFINITY
              *
              */
             crm_trace("%s: Filtering %d + %f*%d (factor * score)",
                       node->details->uname, node->weight, factor, score);
 
         } else if (node->weight == INFINITY_HACK) {
             crm_trace("%s: Filtering %d + %f*%d (node < 0)",
                       node->details->uname, node->weight, factor, score);
 
         } else if (only_positive && new_score < 0 && node->weight > 0) {
             node->weight = INFINITY_HACK;
             crm_trace("%s: Filtering %d + %f*%d (score > 0)",
                       node->details->uname, node->weight, factor, score);
 
         } else if (only_positive && new_score < 0 && node->weight == 0) {
             crm_trace("%s: Filtering %d + %f*%d (score == 0)",
                       node->details->uname, node->weight, factor, score);
 
         } else {
             crm_trace("%s: %d + %f*%d", node->details->uname, node->weight, factor, score);
             node->weight = new_score;
         }
     }
 }
 
 GHashTable *
 node_hash_dup(GHashTable * hash)
 {
     /* Hack! */
     GListPtr list = g_hash_table_get_values(hash);
     GHashTable *result = node_hash_from_list(list);
 
     g_list_free(list);
     return result;
 }
 
 GHashTable *
 native_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes, const char *attr,
                      float factor, enum pe_weights flags)
 {
     return rsc_merge_weights(rsc, rhs, nodes, attr, factor, flags);
 }
 
 GHashTable *
 rsc_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes, const char *attr,
                   float factor, enum pe_weights flags)
 {
     GHashTable *work = NULL;
     int multiplier = 1;
 
     if (factor < 0) {
         multiplier = -1;
     }
 
     if (is_set(rsc->flags, pe_rsc_merging)) {
         pe_rsc_info(rsc, "%s: Breaking dependency loop at %s", rhs, rsc->id);
         return nodes;
     }
 
     set_bit(rsc->flags, pe_rsc_merging);
 
     if (is_set(flags, pe_weights_init)) {
         if (rsc->variant == pe_group && rsc->children) {
             GListPtr last = rsc->children;
 
             while (last->next != NULL) {
                 last = last->next;
             }
 
             pe_rsc_trace(rsc, "Merging %s as a group %p %p", rsc->id, rsc->children, last);
             work = rsc_merge_weights(last->data, rhs, NULL, attr, factor, flags);
 
         } else {
             work = node_hash_dup(rsc->allowed_nodes);
         }
         clear_bit(flags, pe_weights_init);
 
     } else if (rsc->variant == pe_group && rsc->children) {
         GListPtr iter = rsc->children;
 
         pe_rsc_trace(rsc, "%s: Combining scores from %d children of %s", rhs, g_list_length(iter), rsc->id);
         work = node_hash_dup(nodes);
         for(iter = rsc->children; iter->next != NULL; iter = iter->next) {
             work = rsc_merge_weights(iter->data, rhs, work, attr, factor, flags);
         }
 
     } else {
         pe_rsc_trace(rsc, "%s: Combining scores from %s", rhs, rsc->id);
         work = node_hash_dup(nodes);
         node_hash_update(work, rsc->allowed_nodes, attr, factor,
                          is_set(flags, pe_weights_positive));
     }
 
     if (is_set(flags, pe_weights_rollback) && can_run_any(work) == FALSE) {
         pe_rsc_info(rsc, "%s: Rolling back scores from %s", rhs, rsc->id);
         g_hash_table_destroy(work);
         clear_bit(rsc->flags, pe_rsc_merging);
         return nodes;
     }
 
     if (can_run_any(work)) {
         GListPtr gIter = NULL;
 
         if (is_set(flags, pe_weights_forward)) {
             gIter = rsc->rsc_cons;
             crm_trace("Checking %d additional colocation constraints", g_list_length(gIter));
 
         } else if(rsc->variant == pe_group && rsc->children) {
             GListPtr last = rsc->children;
 
             while (last->next != NULL) {
                 last = last->next;
             }
 
             gIter = ((resource_t*)last->data)->rsc_cons_lhs;
             crm_trace("Checking %d additional optional group colocation constraints from %s",
                       g_list_length(gIter), ((resource_t*)last->data)->id);
 
         } else {
             gIter = rsc->rsc_cons_lhs;
             crm_trace("Checking %d additional optional colocation constraints %s", g_list_length(gIter), rsc->id);
         }
 
         for (; gIter != NULL; gIter = gIter->next) {
             resource_t *other = NULL;
             rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
 
             if (is_set(flags, pe_weights_forward)) {
                 other = constraint->rsc_rh;
             } else {
                 other = constraint->rsc_lh;
             }
 
             pe_rsc_trace(rsc, "Applying %s (%s)", constraint->id, other->id);
             work = rsc_merge_weights(other, rhs, work, constraint->node_attribute,
                                      multiplier * (float)constraint->score / INFINITY, flags);
             dump_node_scores(LOG_TRACE, NULL, rhs, work);
         }
 
     }
 
     if (is_set(flags, pe_weights_positive)) {
         node_t *node = NULL;
         GHashTableIter iter;
 
         g_hash_table_iter_init(&iter, work);
         while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
             if (node->weight == INFINITY_HACK) {
                 node->weight = 1;
             }
         }
     }
 
     if (nodes) {
         g_hash_table_destroy(nodes);
     }
 
     clear_bit(rsc->flags, pe_rsc_merging);
     return work;
 }
 
 node_t *
 native_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set)
 {
     GListPtr gIter = NULL;
     int alloc_details = scores_log_level + 1;
 
     if (rsc->parent && is_not_set(rsc->parent->flags, pe_rsc_allocating)) {
         /* never allocate children on their own */
         pe_rsc_debug(rsc, "Escalating allocation of %s to its parent: %s", rsc->id,
                      rsc->parent->id);
         rsc->parent->cmds->allocate(rsc->parent, prefer, data_set);
     }
 
     if (is_not_set(rsc->flags, pe_rsc_provisional)) {
         return rsc->allocated_to;
     }
 
     if (is_set(rsc->flags, pe_rsc_allocating)) {
         pe_rsc_debug(rsc, "Dependency loop detected involving %s", rsc->id);
         return NULL;
     }
 
     set_bit(rsc->flags, pe_rsc_allocating);
     print_resource(alloc_details, "Allocating: ", rsc, FALSE);
     dump_node_scores(alloc_details, rsc, "Pre-allloc", rsc->allowed_nodes);
 
     for (gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) {
         rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
 
         GHashTable *archive = NULL;
         resource_t *rsc_rh = constraint->rsc_rh;
 
         pe_rsc_trace(rsc, "%s: Pre-Processing %s (%s, %d, %s)",
                      rsc->id, constraint->id, rsc_rh->id,
                      constraint->score, role2text(constraint->role_lh));
         if (constraint->role_lh >= RSC_ROLE_MASTER
             || (constraint->score < 0 && constraint->score > -INFINITY)) {
             archive = node_hash_dup(rsc->allowed_nodes);
         }
         rsc_rh->cmds->allocate(rsc_rh, NULL, data_set);
         rsc->cmds->rsc_colocation_lh(rsc, rsc_rh, constraint);
         if (archive && can_run_any(rsc->allowed_nodes) == FALSE) {
             pe_rsc_info(rsc, "%s: Rolling back scores from %s", rsc->id, rsc_rh->id);
             g_hash_table_destroy(rsc->allowed_nodes);
             rsc->allowed_nodes = archive;
             archive = NULL;
         }
         if (archive) {
             g_hash_table_destroy(archive);
         }
     }
 
     dump_node_scores(alloc_details, rsc, "Post-coloc", rsc->allowed_nodes);
 
     for (gIter = rsc->rsc_cons_lhs; gIter != NULL; gIter = gIter->next) {
         rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
 
         rsc->allowed_nodes =
             constraint->rsc_lh->cmds->merge_weights(constraint->rsc_lh, rsc->id, rsc->allowed_nodes,
                                                     constraint->node_attribute,
                                                     (float)constraint->score / INFINITY,
                                                     pe_weights_rollback);
     }
 
     print_resource(LOG_DEBUG_2, "Allocating: ", rsc, FALSE);
     if (rsc->next_role == RSC_ROLE_STOPPED) {
         pe_rsc_trace(rsc, "Making sure %s doesn't get allocated", rsc->id);
         /* make sure it doesnt come up again */
         resource_location(rsc, NULL, -INFINITY, XML_RSC_ATTR_TARGET_ROLE, data_set);
     }
 
-    dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __PRETTY_FUNCTION__,
+    dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __FUNCTION__,
                      rsc->allowed_nodes);
     if (is_set(data_set->flags, pe_flag_stonith_enabled)
         && is_set(data_set->flags, pe_flag_have_stonith_resource) == FALSE) {
         clear_bit(rsc->flags, pe_rsc_managed);
     }
 
     if (is_not_set(rsc->flags, pe_rsc_managed)) {
         const char *reason = NULL;
         node_t *assign_to = NULL;
 
         rsc->next_role = rsc->role;
         if (rsc->running_on == NULL) {
             reason = "inactive";
         } else if (rsc->role == RSC_ROLE_MASTER) {
             assign_to = rsc->running_on->data;
             reason = "master";
         } else if (is_set(rsc->flags, pe_rsc_failed)) {
             assign_to = rsc->running_on->data;
             reason = "failed";
         } else {
             assign_to = rsc->running_on->data;
             reason = "active";
         }
         pe_rsc_info(rsc, "Unmanaged resource %s allocated to %s: %s", rsc->id,
                     assign_to ? assign_to->details->uname : "'nowhere'", reason);
         native_assign_node(rsc, NULL, assign_to, TRUE);
 
     } else if (is_set(data_set->flags, pe_flag_stop_everything)) {
         pe_rsc_debug(rsc, "Forcing %s to stop", rsc->id);
         native_assign_node(rsc, NULL, NULL, TRUE);
 
     } else if (is_set(rsc->flags, pe_rsc_provisional)
                && native_choose_node(rsc, prefer, data_set)) {
         pe_rsc_trace(rsc, "Allocated resource %s to %s", rsc->id,
                      rsc->allocated_to->details->uname);
 
     } else if (rsc->allocated_to == NULL) {
         if (is_not_set(rsc->flags, pe_rsc_orphan)) {
             pe_rsc_info(rsc, "Resource %s cannot run anywhere", rsc->id);
         } else if (rsc->running_on != NULL) {
             pe_rsc_info(rsc, "Stopping orphan resource %s", rsc->id);
         }
 
     } else {
         pe_rsc_debug(rsc, "Pre-Allocated resource %s to %s", rsc->id,
                      rsc->allocated_to->details->uname);
     }
 
     clear_bit(rsc->flags, pe_rsc_allocating);
     print_resource(LOG_DEBUG_3, "Allocated ", rsc, TRUE);
 
     if (rsc->is_remote_node) {
         node_t *remote_node = pe_find_node(data_set->nodes, rsc->id);
 
         CRM_ASSERT(remote_node != NULL);
         if (rsc->allocated_to && rsc->next_role != RSC_ROLE_STOPPED) {
             crm_trace("Setting remote node %s to ONLINE", remote_node->details->id);
             remote_node->details->online = TRUE;
             /* We shouldn't consider an unseen remote-node unclean if we are going
              * to try and connect to it. Otherwise we get an unnecessary fence */
             if (remote_node->details->unseen == TRUE) {
                 remote_node->details->unclean = FALSE;
             }
 
         } else {
             crm_trace("Setting remote node %s to SHUTDOWN.  next role = %s, allocated=%s",
                 remote_node->details->id, role2text(rsc->next_role), rsc->allocated_to ? "true" : "false");
             remote_node->details->shutdown = TRUE;
         }
     }
 
     return rsc->allocated_to;
 }
 
 static gboolean
 is_op_dup(resource_t * rsc, const char *name, const char *interval)
 {
     gboolean dup = FALSE;
     const char *id = NULL;
     const char *value = NULL;
     xmlNode *operation = NULL;
 
     for (operation = __xml_first_child(rsc->ops_xml); operation != NULL;
          operation = __xml_next(operation)) {
         if (crm_str_eq((const char *)operation->name, "op", TRUE)) {
             value = crm_element_value(operation, "name");
             if (safe_str_neq(value, name)) {
                 continue;
             }
 
             value = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
             if (value == NULL) {
                 value = "0";
             }
 
             if (safe_str_neq(value, interval)) {
                 continue;
             }
 
             if (id == NULL) {
                 id = ID(operation);
 
             } else {
                 crm_config_err("Operation %s is a duplicate of %s", ID(operation), id);
                 crm_config_err
                     ("Do not use the same (name, interval) combination more than once per resource");
                 dup = TRUE;
             }
         }
     }
 
     return dup;
 }
 
 void
 RecurringOp(resource_t * rsc, action_t * start, node_t * node,
             xmlNode * operation, pe_working_set_t * data_set)
 {
     char *key = NULL;
     const char *name = NULL;
     const char *value = NULL;
     const char *interval = NULL;
     const char *node_uname = NULL;
 
     unsigned long long interval_ms = 0;
     action_t *mon = NULL;
     gboolean is_optional = TRUE;
     GListPtr possible_matches = NULL;
 
     /* Only process for the operations without role="Stopped" */
     value = crm_element_value(operation, "role");
     if (value && text2role(value) == RSC_ROLE_STOPPED) {
         return;
     }
 
     pe_rsc_trace(rsc, "Creating recurring action %s for %s in role %s on %s",
                  ID(operation), rsc->id, role2text(rsc->next_role),
                  node ? node->details->uname : "n/a");
 
     if (node != NULL) {
         node_uname = node->details->uname;
     }
 
     interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
     interval_ms = crm_get_interval(interval);
 
     if (interval_ms == 0) {
         return;
     }
 
     name = crm_element_value(operation, "name");
     if (is_op_dup(rsc, name, interval)) {
         return;
     }
 
     if (safe_str_eq(name, RSC_STOP)
         || safe_str_eq(name, RSC_START)
         || safe_str_eq(name, RSC_DEMOTE)
         || safe_str_eq(name, RSC_PROMOTE)
         ) {
         crm_config_err("Invalid recurring action %s wth name: '%s'", ID(operation), name);
         return;
     }
 
     key = generate_op_key(rsc->id, name, interval_ms);
     if (find_rsc_op_entry(rsc, key) == NULL) {
         /* disabled */
         free(key);
         return;
     }
 
     if (start != NULL) {
         pe_rsc_trace(rsc, "Marking %s %s due to %s",
                      key, is_set(start->flags, pe_action_optional) ? "optional" : "manditory",
                      start->uuid);
         is_optional = (rsc->cmds->action_flags(start, NULL) & pe_action_optional);
     } else {
         pe_rsc_trace(rsc, "Marking %s optional", key);
         is_optional = TRUE;
     }
 
     /* start a monitor for an already active resource */
     possible_matches = find_actions_exact(rsc->actions, key, node);
     if (possible_matches == NULL) {
         is_optional = FALSE;
         pe_rsc_trace(rsc, "Marking %s manditory: not active", key);
     } else {
         g_list_free(possible_matches);
     }
 
     if ((rsc->next_role == RSC_ROLE_MASTER && value == NULL)
         || (value != NULL && text2role(value) != rsc->next_role)) {
         int log_level = LOG_DEBUG_2;
         const char *result = "Ignoring";
 
         if (is_optional) {
             char *local_key = strdup(key);
 
             log_level = LOG_INFO;
             result = "Cancelling";
             /* its running : cancel it */
 
             mon = custom_action(rsc, local_key, RSC_CANCEL, node, FALSE, TRUE, data_set);
 
             free(mon->task);
             mon->task = strdup(RSC_CANCEL);
             add_hash_param(mon->meta, XML_LRM_ATTR_INTERVAL, interval);
             add_hash_param(mon->meta, XML_LRM_ATTR_TASK, name);
 
             local_key = NULL;
 
             switch (rsc->role) {
                 case RSC_ROLE_SLAVE:
                 case RSC_ROLE_STARTED:
                     if (rsc->next_role == RSC_ROLE_MASTER) {
                         local_key = promote_key(rsc);
 
                     } else if (rsc->next_role == RSC_ROLE_STOPPED) {
                         local_key = stop_key(rsc);
                     }
 
                     break;
                 case RSC_ROLE_MASTER:
                     local_key = demote_key(rsc);
                     break;
                 default:
                     break;
             }
 
             if (local_key) {
                 custom_action_order(rsc, NULL, mon, rsc, local_key, NULL,
                                     pe_order_runnable_left, data_set);
             }
 
             mon = NULL;
         }
 
         do_crm_log(log_level, "%s action %s (%s vs. %s)",
                    result, key, value ? value : role2text(RSC_ROLE_SLAVE),
                    role2text(rsc->next_role));
 
         free(key);
         key = NULL;
         return;
     }
 
     mon = custom_action(rsc, key, name, node, is_optional, TRUE, data_set);
     key = mon->uuid;
     if (is_optional) {
         pe_rsc_trace(rsc, "%s\t   %s (optional)", crm_str(node_uname), mon->uuid);
     }
 
     if (start == NULL || is_set(start->flags, pe_action_runnable) == FALSE) {
         pe_rsc_debug(rsc, "%s\t   %s (cancelled : start un-runnable)", crm_str(node_uname),
                      mon->uuid);
         update_action_flags(mon, pe_action_runnable | pe_action_clear);
 
     } else if (node == NULL || node->details->online == FALSE || node->details->unclean) {
         pe_rsc_debug(rsc, "%s\t   %s (cancelled : no node available)", crm_str(node_uname),
                      mon->uuid);
         update_action_flags(mon, pe_action_runnable | pe_action_clear);
 
     } else if (is_set(mon->flags, pe_action_optional) == FALSE) {
         pe_rsc_info(rsc, " Start recurring %s (%llus) for %s on %s", mon->task, interval_ms / 1000,
                     rsc->id, crm_str(node_uname));
     }
 
     if (rsc->next_role == RSC_ROLE_MASTER) {
         char *running_master = crm_itoa(PCMK_OCF_RUNNING_MASTER);
 
         add_hash_param(mon->meta, XML_ATTR_TE_TARGET_RC, running_master);
         free(running_master);
     }
 
     if (node == NULL || is_set(rsc->flags, pe_rsc_managed)) {
         custom_action_order(rsc, start_key(rsc), NULL,
                             NULL, strdup(key), mon,
                             pe_order_implies_then | pe_order_runnable_left, data_set);
 
         if (rsc->next_role == RSC_ROLE_MASTER) {
             custom_action_order(rsc, promote_key(rsc), NULL,
                                 rsc, NULL, mon,
                                 pe_order_optional | pe_order_runnable_left, data_set);
 
         } else if (rsc->role == RSC_ROLE_MASTER) {
             custom_action_order(rsc, demote_key(rsc), NULL,
                                 rsc, NULL, mon,
                                 pe_order_optional | pe_order_runnable_left, data_set);
         }
     }
 }
 
 void
 Recurring(resource_t * rsc, action_t * start, node_t * node, pe_working_set_t * data_set)
 {
     if (is_not_set(data_set->flags, pe_flag_maintenance_mode) &&
         (node == NULL || node->details->maintenance == FALSE)) {
         xmlNode *operation = NULL;
 
         for (operation = __xml_first_child(rsc->ops_xml); operation != NULL;
              operation = __xml_next(operation)) {
             if (crm_str_eq((const char *)operation->name, "op", TRUE)) {
                 RecurringOp(rsc, start, node, operation, data_set);
             }
         }
     }
 }
 
 void
 RecurringOp_Stopped(resource_t * rsc, action_t * start, node_t * node,
                     xmlNode * operation, pe_working_set_t * data_set)
 {
     char *key = NULL;
     const char *name = NULL;
     const char *role = NULL;
     const char *interval = NULL;
     const char *node_uname = NULL;
 
     unsigned long long interval_ms = 0;
     GListPtr possible_matches = NULL;
     GListPtr gIter = NULL;
 
     /* TODO: Support of non-unique clone */
     if (is_set(rsc->flags, pe_rsc_unique) == FALSE) {
         return;
     }
 
     /* Only process for the operations with role="Stopped" */
     role = crm_element_value(operation, "role");
     if (role == NULL || text2role(role) != RSC_ROLE_STOPPED) {
         return;
     }
 
     pe_rsc_trace(rsc,
                  "Creating recurring actions %s for %s in role %s on nodes where it'll not be running",
                  ID(operation), rsc->id, role2text(rsc->next_role));
 
     if (node != NULL) {
         node_uname = node->details->uname;
     }
 
     interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
     interval_ms = crm_get_interval(interval);
 
     if (interval_ms == 0) {
         return;
     }
 
     name = crm_element_value(operation, "name");
     if (is_op_dup(rsc, name, interval)) {
         return;
     }
 
     if (safe_str_eq(name, RSC_STOP)
         || safe_str_eq(name, RSC_START)
         || safe_str_eq(name, RSC_DEMOTE)
         || safe_str_eq(name, RSC_PROMOTE)
         ) {
         crm_config_err("Invalid recurring action %s wth name: '%s'", ID(operation), name);
         return;
     }
 
     key = generate_op_key(rsc->id, name, interval_ms);
     if (find_rsc_op_entry(rsc, key) == NULL) {
         /* disabled */
         free(key);
         return;
     }
 
     /* if the monitor exists on the node where the resource will be running, cancel it */
     if (node != NULL) {
         possible_matches = find_actions_exact(rsc->actions, key, node);
         if (possible_matches) {
             action_t *cancel_op = NULL;
             char *local_key = strdup(key);
 
             g_list_free(possible_matches);
 
             cancel_op = custom_action(rsc, local_key, RSC_CANCEL, node, FALSE, TRUE, data_set);
 
             free(cancel_op->task);
             cancel_op->task = strdup(RSC_CANCEL);
             add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL, interval);
             add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, name);
 
             local_key = NULL;
 
             if (rsc->next_role == RSC_ROLE_STARTED || rsc->next_role == RSC_ROLE_SLAVE) {
                 /* rsc->role == RSC_ROLE_STOPPED: cancel the monitor before start */
                 /* rsc->role == RSC_ROLE_STARTED: for a migration, cancel the monitor on the target node before start */
                 custom_action_order(rsc, NULL, cancel_op, rsc, start_key(rsc), NULL,
                                     pe_order_runnable_left, data_set);
             }
 
             pe_rsc_info(rsc, "Cancel action %s (%s vs. %s) on %s",
                         key, role, role2text(rsc->next_role), crm_str(node_uname));
         }
     }
 
     for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
         node_t *stop_node = (node_t *) gIter->data;
         const char *stop_node_uname = stop_node->details->uname;
         gboolean is_optional = TRUE;
         gboolean probe_is_optional = TRUE;
         gboolean stop_is_optional = TRUE;
         action_t *stopped_mon = NULL;
         char *rc_inactive = NULL;
         GListPtr probe_complete_ops = NULL;
         GListPtr stop_ops = NULL;
         GListPtr local_gIter = NULL;
         char *stop_op_key = NULL;
 
         if (node_uname && safe_str_eq(stop_node_uname, node_uname)) {
             continue;
         }
 
         pe_rsc_trace(rsc, "Creating recurring action %s for %s on %s",
                      ID(operation), rsc->id, crm_str(stop_node_uname));
 
         /* start a monitor for an already stopped resource */
         possible_matches = find_actions_exact(rsc->actions, key, stop_node);
         if (possible_matches == NULL) {
             pe_rsc_trace(rsc, "Marking %s manditory on %s: not active", key,
                          crm_str(stop_node_uname));
             is_optional = FALSE;
         } else {
             pe_rsc_trace(rsc, "Marking %s optional on %s: already active", key,
                          crm_str(stop_node_uname));
             is_optional = TRUE;
             g_list_free(possible_matches);
         }
 
         stopped_mon = custom_action(rsc, strdup(key), name, stop_node, is_optional, TRUE, data_set);
 
         rc_inactive = crm_itoa(PCMK_OCF_NOT_RUNNING);
         add_hash_param(stopped_mon->meta, XML_ATTR_TE_TARGET_RC, rc_inactive);
         free(rc_inactive);
 
         probe_complete_ops = find_actions(data_set->actions, CRM_OP_PROBED, NULL);
         for (local_gIter = probe_complete_ops; local_gIter != NULL; local_gIter = local_gIter->next) {
             action_t *probe_complete = (action_t *) local_gIter->data;
 
             if (probe_complete->node == NULL) {
                 if (is_set(probe_complete->flags, pe_action_optional) == FALSE) {
                     probe_is_optional = FALSE;
                 }
 
                 if (is_set(probe_complete->flags, pe_action_runnable) == FALSE) {
                     crm_debug("%s\t   %s (cancelled : probe un-runnable)",
                               crm_str(stop_node_uname), stopped_mon->uuid);
                     update_action_flags(stopped_mon, pe_action_runnable | pe_action_clear);
                 }
 
                 if (is_set(rsc->flags, pe_rsc_managed)) {
                     custom_action_order(NULL, NULL, probe_complete,
                                         NULL, strdup(key), stopped_mon,
                                         pe_order_optional, data_set);
                 }
                 break;
             }
         }
 
         if (probe_complete_ops) {
             g_list_free(probe_complete_ops);
         }
 
         stop_op_key = stop_key(rsc);
         stop_ops = find_actions_exact(rsc->actions, stop_op_key, stop_node);
 
         for (local_gIter = stop_ops; local_gIter != NULL; local_gIter = local_gIter->next) {
             action_t *stop = (action_t *) local_gIter->data;
 
             if (is_set(stop->flags, pe_action_optional) == FALSE) {
                 stop_is_optional = FALSE;
             }
 
             if (is_set(stop->flags, pe_action_runnable) == FALSE) {
                 crm_debug("%s\t   %s (cancelled : stop un-runnable)",
                           crm_str(stop_node_uname), stopped_mon->uuid);
                 update_action_flags(stopped_mon, pe_action_runnable | pe_action_clear);
             }
 
             if (is_set(rsc->flags, pe_rsc_managed)) {
                 custom_action_order(rsc, strdup(stop_op_key), stop,
                                     NULL, strdup(key), stopped_mon,
                                     pe_order_implies_then | pe_order_runnable_left, data_set);
             }
 
         }
 
         if (stop_ops) {
             g_list_free(stop_ops);
         }
         free(stop_op_key);
 
         if (is_optional == FALSE && probe_is_optional && stop_is_optional
             && is_set(rsc->flags, pe_rsc_managed) == FALSE) {
             pe_rsc_trace(rsc, "Marking %s optional on %s due to unmanaged",
                          key, crm_str(stop_node_uname));
             update_action_flags(stopped_mon, pe_action_optional);
         }
 
         if (is_set(stopped_mon->flags, pe_action_optional)) {
             pe_rsc_trace(rsc, "%s\t   %s (optional)", crm_str(stop_node_uname), stopped_mon->uuid);
         }
 
         if (stop_node->details->online == FALSE || stop_node->details->unclean) {
             pe_rsc_debug(rsc, "%s\t   %s (cancelled : no node available)",
                          crm_str(stop_node_uname), stopped_mon->uuid);
             update_action_flags(stopped_mon, pe_action_runnable | pe_action_clear);
         }
 
         if (is_set(stopped_mon->flags, pe_action_runnable)
             && is_set(stopped_mon->flags, pe_action_optional) == FALSE) {
             crm_notice(" Start recurring %s (%llus) for %s on %s", stopped_mon->task,
                        interval_ms / 1000, rsc->id, crm_str(stop_node_uname));
         }
     }
 
     free(key);
 }
 
 void
 Recurring_Stopped(resource_t * rsc, action_t * start, node_t * node, pe_working_set_t * data_set)
 {
     if (is_not_set(data_set->flags, pe_flag_maintenance_mode) && 
         (node == NULL || node->details->maintenance == FALSE)) {
         xmlNode *operation = NULL;
 
         for (operation = __xml_first_child(rsc->ops_xml); operation != NULL;
              operation = __xml_next(operation)) {
             if (crm_str_eq((const char *)operation->name, "op", TRUE)) {
                 RecurringOp_Stopped(rsc, start, node, operation, data_set);
             }
         }
     }
 }
 
 void
 native_create_actions(resource_t * rsc, pe_working_set_t * data_set)
 {
     action_t *start = NULL;
     node_t *chosen = NULL;
     node_t *current = NULL;
     gboolean need_stop = FALSE;
 
     GListPtr gIter = NULL;
     int num_active_nodes = 0;
     enum rsc_role_e role = RSC_ROLE_UNKNOWN;
     enum rsc_role_e next_role = RSC_ROLE_UNKNOWN;
 
     chosen = rsc->allocated_to;
     if (chosen != NULL && rsc->next_role == RSC_ROLE_UNKNOWN) {
         rsc->next_role = RSC_ROLE_STARTED;
         pe_rsc_trace(rsc, "Fixed next_role: unknown -> %s", role2text(rsc->next_role));
 
     } else if (rsc->next_role == RSC_ROLE_UNKNOWN) {
         rsc->next_role = RSC_ROLE_STOPPED;
         pe_rsc_trace(rsc, "Fixed next_role: unknown -> %s", role2text(rsc->next_role));
     }
 
     pe_rsc_trace(rsc, "Processing state transition for %s %p: %s->%s", rsc->id, rsc,
                  role2text(rsc->role), role2text(rsc->next_role));
 
     if (rsc->running_on) {
         current = rsc->running_on->data;
     }
 
     for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
         /* node_t *n = (node_t *) gIter->data; */
 
         num_active_nodes++;
     }
 
     get_rsc_attributes(rsc->parameters, rsc, chosen, data_set);
 
     for (gIter = rsc->dangling_migrations; gIter != NULL; gIter = gIter->next) {
         node_t *current = (node_t *) gIter->data;
 
         action_t *stop = stop_action(rsc, current, FALSE);
 
         set_bit(stop->flags, pe_action_dangle);
         pe_rsc_trace(rsc, "Forcing a cleanup of %s on %s", rsc->id, current->details->uname);
 
         if (is_set(data_set->flags, pe_flag_remove_after_stop)) {
             DeleteRsc(rsc, current, FALSE, data_set);
         }
     }
 
     if (num_active_nodes > 1) {
 
         if (num_active_nodes == 2
             && chosen
             && rsc->partial_migration_target
             && (chosen->details == rsc->partial_migration_target->details)) {
             /* Here the chosen node is still the migration target from a partial
              * migration. Attempt to continue the migration instead of recovering
              * by stopping the resource everywhere and starting it on a single node. */
             pe_rsc_trace(rsc,
                          "Will attempt to continue with a partial migration to target %s from %s",
                          rsc->partial_migration_target->details->id,
                          rsc->partial_migration_source->details->id);
         } else {
             const char *type = crm_element_value(rsc->xml, XML_ATTR_TYPE);
             const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
 
             pe_proc_err("Resource %s (%s::%s) is active on %d nodes %s",
                         rsc->id, class, type, num_active_nodes, recovery2text(rsc->recovery_type));
             crm_warn("See %s for more information.",
                      "http://clusterlabs.org/wiki/FAQ#Resource_is_Too_Active");
 
             if (rsc->recovery_type == recovery_stop_start) {
                 need_stop = TRUE;
             }
 
             /* If by chance a partial migration is in process,
              * but the migration target is not chosen still, clear all
              * partial migration data.  */
             rsc->partial_migration_source = rsc->partial_migration_target = NULL;
         }
     }
 
     if (is_set(rsc->flags, pe_rsc_start_pending)) {
         start = start_action(rsc, chosen, TRUE);
         set_bit(start->flags, pe_action_print_always);
     }
 
     if (current && chosen && current->details != chosen->details) {
         pe_rsc_trace(rsc, "Moving %s", rsc->id);
         need_stop = TRUE;
 
     } else if (is_set(rsc->flags, pe_rsc_failed)) {
         pe_rsc_trace(rsc, "Recovering %s", rsc->id);
         need_stop = TRUE;
 
     } else if (is_set(rsc->flags, pe_rsc_block)) {
         pe_rsc_trace(rsc, "Block %s", rsc->id);
         need_stop = TRUE;
 
     } else if (rsc->role > RSC_ROLE_STARTED && current != NULL && chosen != NULL) {
         /* Recovery of a promoted resource */
         start = start_action(rsc, chosen, TRUE);
         if (is_set(start->flags, pe_action_optional) == FALSE) {
             pe_rsc_trace(rsc, "Forced start %s", rsc->id);
             need_stop = TRUE;
         }
     }
 
     pe_rsc_trace(rsc, "Creating actions for %s: %s->%s", rsc->id,
                  role2text(rsc->role), role2text(rsc->next_role));
 
     role = rsc->role;
     /* Potentiall optional steps on brining the resource down and back up to the same level */
     while (role != RSC_ROLE_STOPPED) {
         next_role = rsc_state_matrix[role][RSC_ROLE_STOPPED];
         pe_rsc_trace(rsc, "Down: Executing: %s->%s (%s)%s", role2text(role), role2text(next_role),
                      rsc->id, need_stop ? " required" : "");
         if (rsc_action_matrix[role][next_role] (rsc, current, !need_stop, data_set) == FALSE) {
             break;
         }
         role = next_role;
     }
 
 
     while (rsc->role <= rsc->next_role && role != rsc->role && is_not_set(rsc->flags, pe_rsc_block)) {
         next_role = rsc_state_matrix[role][rsc->role];
         pe_rsc_trace(rsc, "Up:   Executing: %s->%s (%s)%s", role2text(role), role2text(next_role),
                      rsc->id, need_stop ? " required" : "");
         if (rsc_action_matrix[role][next_role] (rsc, chosen, !need_stop, data_set) == FALSE) {
             break;
         }
         role = next_role;
     }
     role = rsc->role;
 
     /* Required steps from this role to the next */
     while (role != rsc->next_role) {
         next_role = rsc_state_matrix[role][rsc->next_role];
         pe_rsc_trace(rsc, "Role: Executing: %s->%s = (%s)", role2text(role),
                      role2text(rsc->next_role), role2text(next_role), rsc->id);
         if (rsc_action_matrix[role][next_role] (rsc, chosen, FALSE, data_set) == FALSE) {
             break;
         }
         role = next_role;
     }
 
     if(is_set(rsc->flags, pe_rsc_block)) {
         pe_rsc_trace(rsc, "No monitor additional ops for blocked resource");
 
     } else if (rsc->next_role != RSC_ROLE_STOPPED || is_set(rsc->flags, pe_rsc_managed) == FALSE) {
         pe_rsc_trace(rsc, "Monitor ops for active resource");
         start = start_action(rsc, chosen, TRUE);
         Recurring(rsc, start, chosen, data_set);
         Recurring_Stopped(rsc, start, chosen, data_set);
     } else {
         pe_rsc_trace(rsc, "Monitor ops for in-active resource");
         Recurring_Stopped(rsc, NULL, NULL, data_set);
     }
 }
 
 static void
 rsc_avoids_remote_nodes(resource_t *rsc)
 {
     GHashTableIter iter;
     node_t *node = NULL;
     g_hash_table_iter_init(&iter, rsc->allowed_nodes);
     while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
         if (node->details->remote_rsc) {
             node->weight = -INFINITY;
         }
     }
 }
 
 void
 native_internal_constraints(resource_t * rsc, pe_working_set_t * data_set)
 {
     /* This function is on the critical path and worth optimizing as much as possible */
 
     resource_t *top = uber_parent(rsc);
     int type = pe_order_optional | pe_order_implies_then | pe_order_restart;
     gboolean is_stonith =
         (rsc->xml && safe_str_eq(crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS), "stonith")) ?
         TRUE : FALSE;
 
     custom_action_order(rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL,
                         rsc, generate_op_key(rsc->id, RSC_START, 0), NULL, type, data_set);
 
     if (top->variant == pe_master || rsc->role > RSC_ROLE_SLAVE) {
         custom_action_order(rsc, generate_op_key(rsc->id, RSC_DEMOTE, 0), NULL,
                             rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL,
                             pe_order_implies_first_master, data_set);
 
         custom_action_order(rsc, generate_op_key(rsc->id, RSC_START, 0), NULL,
                             rsc, generate_op_key(rsc->id, RSC_PROMOTE, 0), NULL,
                             pe_order_runnable_left, data_set);
     }
 
     if (is_not_set(rsc->flags, pe_rsc_managed)) {
         pe_rsc_trace(rsc, "Skipping fencing constraints for unmanaged resource: %s", rsc->id);
         return;
     }
 
     {
         action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set);
 
         custom_action_order(rsc, stop_key(rsc), NULL,
                             NULL, strdup(all_stopped->task), all_stopped,
                             pe_order_implies_then | pe_order_runnable_left, data_set);
     }
 
     if (g_hash_table_size(rsc->utilization) > 0
         && safe_str_neq(data_set->placement_strategy, "default")) {
         GHashTableIter iter;
         node_t *next = NULL;
         GListPtr gIter = NULL;
 
         pe_rsc_trace(rsc, "Creating utilization constraints for %s - strategy: %s",
                      rsc->id, data_set->placement_strategy);
 
         for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
             node_t *current = (node_t *) gIter->data;
 
             char *load_stopped_task = crm_concat(LOAD_STOPPED, current->details->uname, '_');
             action_t *load_stopped = get_pseudo_op(load_stopped_task, data_set);
 
             if (load_stopped->node == NULL) {
                 load_stopped->node = node_copy(current);
                 update_action_flags(load_stopped, pe_action_optional | pe_action_clear);
             }
 
             custom_action_order(rsc, stop_key(rsc), NULL,
                                 NULL, load_stopped_task, load_stopped, pe_order_load, data_set);
         }
 
         g_hash_table_iter_init(&iter, rsc->allowed_nodes);
         while (g_hash_table_iter_next(&iter, NULL, (void **)&next)) {
             char *load_stopped_task = crm_concat(LOAD_STOPPED, next->details->uname, '_');
             action_t *load_stopped = get_pseudo_op(load_stopped_task, data_set);
 
             if (load_stopped->node == NULL) {
                 load_stopped->node = node_copy(next);
                 update_action_flags(load_stopped, pe_action_optional | pe_action_clear);
             }
 
             custom_action_order(NULL, strdup(load_stopped_task), load_stopped,
                                 rsc, start_key(rsc), NULL, pe_order_load, data_set);
 
             free(load_stopped_task);
         }
     }
 
     if (rsc->container) {
         crm_trace("Generating order and colocation rules for rsc %s with container %s", rsc->id, rsc->container->id);
         custom_action_order(rsc->container, generate_op_key(rsc->container->id, RSC_START, 0), NULL,
                             rsc, generate_op_key(rsc->id, RSC_START, 0), NULL,
                             pe_order_implies_then | pe_order_runnable_left, data_set);
 
         custom_action_order(rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL,
                             rsc->container, generate_op_key(rsc->container->id, RSC_STOP, 0), NULL,
                             pe_order_implies_first, data_set);
 
         rsc_colocation_new("resource-with-containter", NULL, INFINITY, rsc, rsc->container, NULL,
                            NULL, data_set);
     }
 
     if (rsc->is_remote_node || is_stonith) {
         /* don't allow remote nodes to run stonith devices
          * or remote connection resources.*/
         rsc_avoids_remote_nodes(rsc);
     }
 
     /* If this rsc is a remote connection resource associated
      * with a container ( which will most likely be a virtual guest )
      * do not allow the container to live on any remote-nodes.
      * remote-nodes managing nested remote-nodes should not be allowed. */
     if (rsc->is_remote_node && rsc->container) {
         rsc_avoids_remote_nodes(rsc->container);
     }
 }
 
 void
 native_rsc_colocation_lh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
 {
     if (rsc_lh == NULL) {
         pe_err("rsc_lh was NULL for %s", constraint->id);
         return;
 
     } else if (constraint->rsc_rh == NULL) {
         pe_err("rsc_rh was NULL for %s", constraint->id);
         return;
     }
 
     pe_rsc_trace(rsc_lh, "Processing colocation constraint between %s and %s", rsc_lh->id,
                  rsc_rh->id);
 
     rsc_rh->cmds->rsc_colocation_rh(rsc_lh, rsc_rh, constraint);
 }
 
 enum filter_colocation_res {
     influence_nothing = 0,
     influence_rsc_location,
     influence_rsc_priority,
 };
 
 static enum filter_colocation_res
 filter_colocation_constraint(resource_t * rsc_lh, resource_t * rsc_rh,
                              rsc_colocation_t * constraint)
 {
     if (constraint->score == 0) {
         return influence_nothing;
     }
 
     /* rh side must be allocated before we can process constraint */
     if (is_set(rsc_rh->flags, pe_rsc_provisional)) {
         return influence_nothing;
     }
 
     if ((constraint->role_lh >= RSC_ROLE_SLAVE) &&
         rsc_lh->parent &&
         rsc_lh->parent->variant == pe_master && is_not_set(rsc_lh->flags, pe_rsc_provisional)) {
 
         /* LH and RH resources have already been allocated, place the correct
          * priority oh LH rsc for the given multistate resource role */
         return influence_rsc_priority;
     }
 
     if (is_not_set(rsc_lh->flags, pe_rsc_provisional)) {
         /* error check */
         struct node_shared_s *details_lh;
         struct node_shared_s *details_rh;
 
         if ((constraint->score > -INFINITY) && (constraint->score < INFINITY)) {
             return influence_nothing;
         }
 
         details_rh = rsc_rh->allocated_to ? rsc_rh->allocated_to->details : NULL;
         details_lh = rsc_lh->allocated_to ? rsc_lh->allocated_to->details : NULL;
 
         if (constraint->score == INFINITY && details_lh != details_rh) {
             crm_err("%s and %s are both allocated"
                     " but to different nodes: %s vs. %s",
                     rsc_lh->id, rsc_rh->id,
                     details_lh ? details_lh->uname : "n/a", details_rh ? details_rh->uname : "n/a");
 
         } else if (constraint->score == -INFINITY && details_lh == details_rh) {
             crm_err("%s and %s are both allocated"
                     " but to the SAME node: %s",
                     rsc_lh->id, rsc_rh->id, details_rh ? details_rh->uname : "n/a");
         }
 
         return influence_nothing;
     }
 
     if (constraint->score > 0
         && constraint->role_lh != RSC_ROLE_UNKNOWN && constraint->role_lh != rsc_lh->next_role) {
         crm_trace("LH: Skipping constraint: \"%s\" state filter nextrole is %s",
                   role2text(constraint->role_lh), role2text(rsc_lh->next_role));
         return influence_nothing;
     }
 
     if (constraint->score > 0
         && constraint->role_rh != RSC_ROLE_UNKNOWN && constraint->role_rh != rsc_rh->next_role) {
         crm_trace("RH: Skipping constraint: \"%s\" state filter", role2text(constraint->role_rh));
         return FALSE;
     }
 
     if (constraint->score < 0
         && constraint->role_lh != RSC_ROLE_UNKNOWN && constraint->role_lh == rsc_lh->next_role) {
         crm_trace("LH: Skipping -ve constraint: \"%s\" state filter",
                   role2text(constraint->role_lh));
         return influence_nothing;
     }
 
     if (constraint->score < 0
         && constraint->role_rh != RSC_ROLE_UNKNOWN && constraint->role_rh == rsc_rh->next_role) {
         crm_trace("RH: Skipping -ve constraint: \"%s\" state filter",
                   role2text(constraint->role_rh));
         return influence_nothing;
     }
 
     return influence_rsc_location;
 }
 
 static void
 influence_priority(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
 {
     const char *rh_value = NULL;
     const char *lh_value = NULL;
     const char *attribute = "#id";
     int score_multiplier = 1;
 
     if (constraint->node_attribute != NULL) {
         attribute = constraint->node_attribute;
     }
 
     if (!rsc_rh->allocated_to || !rsc_lh->allocated_to) {
         return;
     }
 
     lh_value = g_hash_table_lookup(rsc_lh->allocated_to->details->attrs, attribute);
     rh_value = g_hash_table_lookup(rsc_rh->allocated_to->details->attrs, attribute);
 
     if (!safe_str_eq(lh_value, rh_value)) {
         return;
     }
 
     if (constraint->role_rh && (constraint->role_rh != rsc_rh->next_role)) {
         return;
     }
 
     if (constraint->role_lh == RSC_ROLE_SLAVE) {
         score_multiplier = -1;
     }
 
     rsc_lh->priority = merge_weights(score_multiplier * constraint->score, rsc_lh->priority);
 }
 
 static void
 colocation_match(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
 {
     const char *tmp = NULL;
     const char *value = NULL;
     const char *attribute = "#id";
 
     GHashTable *work = NULL;
     gboolean do_check = FALSE;
 
     GHashTableIter iter;
     node_t *node = NULL;
 
     if (constraint->node_attribute != NULL) {
         attribute = constraint->node_attribute;
     }
 
     if (rsc_rh->allocated_to) {
         value = g_hash_table_lookup(rsc_rh->allocated_to->details->attrs, attribute);
         do_check = TRUE;
 
     } else if (constraint->score < 0) {
         /* nothing to do:
          *   anti-colocation with something thats not running
          */
         return;
     }
 
     work = node_hash_dup(rsc_lh->allowed_nodes);
 
     g_hash_table_iter_init(&iter, work);
     while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
         tmp = g_hash_table_lookup(node->details->attrs, attribute);
         if (do_check && safe_str_eq(tmp, value)) {
             if (constraint->score < INFINITY) {
                 pe_rsc_trace(rsc_lh, "%s: %s.%s += %d", constraint->id, rsc_lh->id,
                              node->details->uname, constraint->score);
                 node->weight = merge_weights(constraint->score, node->weight);
             }
 
         } else if (do_check == FALSE || constraint->score >= INFINITY) {
             pe_rsc_trace(rsc_lh, "%s: %s.%s -= %d (%s)", constraint->id, rsc_lh->id,
                          node->details->uname, constraint->score,
                          do_check ? "failed" : "unallocated");
             node->weight = merge_weights(-constraint->score, node->weight);
         }
     }
 
     if (can_run_any(work)
         || constraint->score <= -INFINITY || constraint->score >= INFINITY) {
         g_hash_table_destroy(rsc_lh->allowed_nodes);
         rsc_lh->allowed_nodes = work;
         work = NULL;
 
     } else {
         char *score = score2char(constraint->score);
 
         pe_rsc_info(rsc_lh, "%s: Rolling back scores from %s (%d, %s)",
                     rsc_lh->id, rsc_rh->id, do_check, score);
         free(score);
     }
 
     if (work) {
         g_hash_table_destroy(work);
     }
 }
 
 void
 native_rsc_colocation_rh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint)
 {
     enum filter_colocation_res filter_results;
 
     filter_results = filter_colocation_constraint(rsc_lh, rsc_rh, constraint);
 
     switch (filter_results) {
         case influence_rsc_priority:
             influence_priority(rsc_lh, rsc_rh, constraint);
             break;
         case influence_rsc_location:
             pe_rsc_trace(rsc_lh, "%sColocating %s with %s (%s, weight=%d)",
                          constraint->score >= 0 ? "" : "Anti-",
                          rsc_lh->id, rsc_rh->id, constraint->id, constraint->score);
             colocation_match(rsc_lh, rsc_rh, constraint);
             break;
         case influence_nothing:
         default:
             return;
     }
 }
 
 static gboolean
 filter_rsc_ticket(resource_t * rsc_lh, rsc_ticket_t * rsc_ticket)
 {
     if (rsc_ticket->role_lh != RSC_ROLE_UNKNOWN && rsc_ticket->role_lh != rsc_lh->role) {
         pe_rsc_trace(rsc_lh, "LH: Skipping constraint: \"%s\" state filter",
                      role2text(rsc_ticket->role_lh));
         return FALSE;
     }
 
     return TRUE;
 }
 
 void
 rsc_ticket_constraint(resource_t * rsc_lh, rsc_ticket_t * rsc_ticket, pe_working_set_t * data_set)
 {
     if (rsc_ticket == NULL) {
         pe_err("rsc_ticket was NULL");
         return;
     }
 
     if (rsc_lh == NULL) {
         pe_err("rsc_lh was NULL for %s", rsc_ticket->id);
         return;
     }
 
     if (rsc_ticket->ticket->granted && rsc_ticket->ticket->standby == FALSE) {
         return;
     }
 
     if (rsc_lh->children) {
         GListPtr gIter = rsc_lh->children;
 
         pe_rsc_trace(rsc_lh, "Processing ticket dependencies from %s", rsc_lh->id);
 
         for (; gIter != NULL; gIter = gIter->next) {
             resource_t *child_rsc = (resource_t *) gIter->data;
 
             rsc_ticket_constraint(child_rsc, rsc_ticket, data_set);
         }
         return;
     }
 
     pe_rsc_trace(rsc_lh, "%s: Processing ticket dependency on %s (%s, %s)",
                  rsc_lh->id, rsc_ticket->ticket->id, rsc_ticket->id,
                  role2text(rsc_ticket->role_lh));
 
     if (rsc_ticket->ticket->granted == FALSE && g_list_length(rsc_lh->running_on) > 0) {
         GListPtr gIter = NULL;
 
         switch (rsc_ticket->loss_policy) {
             case loss_ticket_stop:
                 resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set);
                 break;
 
             case loss_ticket_demote:
                 /*Promotion score will be set to -INFINITY in master_promotion_order() */
                 if (rsc_ticket->role_lh != RSC_ROLE_MASTER) {
                     resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set);
                 }
                 break;
 
             case loss_ticket_fence:
                 if (filter_rsc_ticket(rsc_lh, rsc_ticket) == FALSE) {
                     return;
                 }
 
                 resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set);
 
                 for (gIter = rsc_lh->running_on; gIter != NULL; gIter = gIter->next) {
                     node_t *node = (node_t *) gIter->data;
 
                     crm_warn("Node %s will be fenced for deadman", node->details->uname);
                     node->details->unclean = TRUE;
                 }
                 break;
 
             case loss_ticket_freeze:
                 if (filter_rsc_ticket(rsc_lh, rsc_ticket) == FALSE) {
                     return;
                 }
                 if (g_list_length(rsc_lh->running_on) > 0) {
                     clear_bit(rsc_lh->flags, pe_rsc_managed);
                     set_bit(rsc_lh->flags, pe_rsc_block);
                 }
                 break;
         }
 
     } else if (rsc_ticket->ticket->granted == FALSE) {
 
         if (rsc_ticket->role_lh != RSC_ROLE_MASTER || rsc_ticket->loss_policy == loss_ticket_stop) {
             resource_location(rsc_lh, NULL, -INFINITY, "__no_ticket__", data_set);
         }
 
     } else if (rsc_ticket->ticket->standby) {
 
         if (rsc_ticket->role_lh != RSC_ROLE_MASTER || rsc_ticket->loss_policy == loss_ticket_stop) {
             resource_location(rsc_lh, NULL, -INFINITY, "__ticket_standby__", data_set);
         }
     }
 }
 
 enum pe_action_flags
 native_action_flags(action_t * action, node_t * node)
 {
     return action->flags;
 }
 
 enum pe_graph_flags
 native_update_actions(action_t * first, action_t * then, node_t * node, enum pe_action_flags flags,
                       enum pe_action_flags filter, enum pe_ordering type)
 {
     /* flags == get_action_flags(first, then_node) called from update_action() */
     enum pe_graph_flags changed = pe_graph_none;
     enum pe_action_flags then_flags = then->flags;
     enum pe_action_flags first_flags = first->flags;
 
     if (type & pe_order_asymmetrical) {
         resource_t *then_rsc = then->rsc;
         enum rsc_role_e then_rsc_role = then_rsc ? then_rsc->fns->state(then_rsc, TRUE) : 0;
 
         if (!then_rsc) {
             /* ignore */
         } else if ((then_rsc_role == RSC_ROLE_STOPPED) && safe_str_eq(then->task, RSC_STOP)) {
             /* ignore... if 'then' is supposed to be stopped after 'first', but
              * then is already stopped, there is nothing to be done when non-symmetrical.  */
         } else if ((then_rsc_role == RSC_ROLE_STARTED) && safe_str_eq(then->task, RSC_START)) {
             /* ignore... if 'then' is supposed to be started after 'first', but
              * then is already started, there is nothing to be done when non-symmetrical.  */
         } else if (!(first->flags & pe_action_runnable)) {
             /* prevent 'then' action from happening if 'first' is not runnable and
              * 'then' has not yet occurred. */
             pe_clear_action_bit(then, pe_action_runnable);
             pe_clear_action_bit(then, pe_action_optional);
             pe_rsc_trace(then->rsc, "Unset optional and runnable on %s", then->uuid);
         } else {
             /* ignore... then is allowed to start/stop if it wants to. */
         }
     }
 
     if (type & pe_order_implies_first) {
         if ((filter & pe_action_optional) && (flags & pe_action_optional) == 0) {
             pe_rsc_trace(first->rsc, "Unset optional on %s because of %s", first->uuid, then->uuid);
             pe_clear_action_bit(first, pe_action_optional);
         }
     }
 
     if (type & pe_order_implies_first_master) {
         if ((filter & pe_action_optional) &&
             ((then->flags & pe_action_optional) == FALSE) &&
             then->rsc && (then->rsc->role == RSC_ROLE_MASTER)) {
             clear_bit(first->flags, pe_action_optional);
         }
     }
 
     if (is_set(type, pe_order_runnable_left)
         && is_set(filter, pe_action_runnable)
         && is_set(then->flags, pe_action_runnable)
         && is_set(flags, pe_action_runnable) == FALSE) {
         pe_rsc_trace(then->rsc, "Unset runnable on %s because of %s", then->uuid, first->uuid);
         pe_clear_action_bit(then, pe_action_runnable);
     }
 
     if (is_set(type, pe_order_implies_then)
         && is_set(filter, pe_action_optional)
         && is_set(then->flags, pe_action_optional)
         && is_set(flags, pe_action_optional) == FALSE) {
         pe_rsc_trace(then->rsc, "Unset optional on %s because of %s", then->uuid, first->uuid);
         pe_clear_action_bit(then, pe_action_optional);
     }
 
     if (is_set(type, pe_order_restart)) {
         const char *reason = NULL;
 
         CRM_ASSERT(first->rsc && first->rsc->variant == pe_native);
         CRM_ASSERT(then->rsc && then->rsc->variant == pe_native);
 
         if ((filter & pe_action_runnable)
             && (then->flags & pe_action_runnable) == 0
             && (then->rsc->flags & pe_rsc_managed)) {
             reason = "shutdown";
         }
 
         if ((filter & pe_action_optional) && (then->flags & pe_action_optional) == 0) {
             reason = "recover";
         }
 
         if (reason && is_set(first->flags, pe_action_optional)
             && is_set(first->flags, pe_action_runnable)) {
             pe_rsc_trace(first->rsc, "Handling %s: %s -> %s", reason, first->uuid, then->uuid);
             pe_clear_action_bit(first, pe_action_optional);
         }
 
         if (reason && is_not_set(first->flags, pe_action_optional)
             && is_not_set(first->flags, pe_action_runnable)) {
             pe_rsc_trace(then->rsc, "Handling %s: %s -> %s", reason, first->uuid, then->uuid);
             pe_clear_action_bit(then, pe_action_runnable);
         }
     }
 
     if (then_flags != then->flags) {
         changed |= pe_graph_updated_then;
         pe_rsc_trace(then->rsc,
                      "Then: Flags for %s on %s are now  0x%.6x (was 0x%.6x) because of %s 0x%.6x",
                      then->uuid, then->node ? then->node->details->uname : "[none]", then->flags,
                      then_flags, first->uuid, first->flags);
     }
 
     if (first_flags != first->flags) {
         changed |= pe_graph_updated_first;
         pe_rsc_trace(first->rsc,
                      "First: Flags for %s on %s are now  0x%.6x (was 0x%.6x) because of %s 0x%.6x",
                      first->uuid, first->node ? first->node->details->uname : "[none]",
                      first->flags, first_flags, then->uuid, then->flags);
     }
 
     return changed;
 }
 
 void
 native_rsc_location(resource_t * rsc, rsc_to_node_t * constraint)
 {
     GListPtr gIter = NULL;
     GHashTableIter iter;
     node_t *node = NULL;
 
     if (constraint == NULL) {
         pe_err("Constraint is NULL");
         return;
 
     } else if (rsc == NULL) {
         pe_err("LHS of rsc_to_node (%s) is NULL", constraint->id);
         return;
     }
 
     pe_rsc_trace(rsc, "Applying %s (%s) to %s", constraint->id,
                  role2text(constraint->role_filter), rsc->id);
 
     /* take "lifetime" into account */
     if (constraint->role_filter > RSC_ROLE_UNKNOWN && constraint->role_filter != rsc->next_role) {
         pe_rsc_debug(rsc, "Constraint (%s) is not active (role : %s vs. %s)",
                      constraint->id, role2text(constraint->role_filter), role2text(rsc->next_role));
         return;
 
     } else if (is_active(constraint) == FALSE) {
         pe_rsc_trace(rsc, "Constraint (%s) is not active", constraint->id);
         return;
     }
 
     if (constraint->node_list_rh == NULL) {
         pe_rsc_trace(rsc, "RHS of constraint %s is NULL", constraint->id);
         return;
     }
 
     for (gIter = constraint->node_list_rh; gIter != NULL; gIter = gIter->next) {
         node_t *node = (node_t *) gIter->data;
         node_t *other_node = NULL;
 
         other_node = (node_t *) pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
 
         if (other_node != NULL) {
             pe_rsc_trace(rsc, "%s + %s: %d + %d",
                          node->details->uname,
                          other_node->details->uname, node->weight, other_node->weight);
             other_node->weight = merge_weights(other_node->weight, node->weight);
 
         } else {
             node_t *new_node = node_copy(node);
 
             g_hash_table_insert(rsc->allowed_nodes, (gpointer) new_node->details->id, new_node);
         }
     }
 
     g_hash_table_iter_init(&iter, rsc->allowed_nodes);
     while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
         pe_rsc_trace(rsc, "%s + %s : %d", rsc->id, node->details->uname, node->weight);
     }
 }
 
 void
 native_expand(resource_t * rsc, pe_working_set_t * data_set)
 {
     GListPtr gIter = NULL;
 
     pe_rsc_trace(rsc, "Processing actions from %s", rsc->id);
 
     for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
         action_t *action = (action_t *) gIter->data;
 
         crm_trace("processing action %d for rsc=%s", action->id, rsc->id);
         graph_element_from_action(action, data_set);
     }
 
     for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
         resource_t *child_rsc = (resource_t *) gIter->data;
 
         child_rsc->cmds->expand(child_rsc, data_set);
     }
 }
 
 void
 #define log_change(fmt, args...)  do {          \
         if(terminal) {                          \
             printf(" * "fmt"\n", ##args);       \
         } else {                                \
             crm_notice(fmt, ##args);            \
         }                                       \
     } while(0)
 LogActions(resource_t * rsc, pe_working_set_t * data_set, gboolean terminal)
 {
     node_t *next = NULL;
     node_t *current = NULL;
 
     action_t *stop = NULL;
     action_t *start = NULL;
     action_t *demote = NULL;
     action_t *promote = NULL;
 
     char *key = NULL;
     gboolean moving = FALSE;
     GListPtr possible_matches = NULL;
 
     if (rsc->children) {
         GListPtr gIter = NULL;
 
         for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
             resource_t *child_rsc = (resource_t *) gIter->data;
 
             LogActions(child_rsc, data_set, terminal);
         }
         return;
     }
 
     next = rsc->allocated_to;
     if (rsc->running_on) {
         if (g_list_length(rsc->running_on) > 1 && rsc->partial_migration_source) {
             current = rsc->partial_migration_source;
         } else {
             current = rsc->running_on->data;
         }
 
         if (rsc->role == RSC_ROLE_STOPPED) {
             /*
              * This can occur when resources are being recovered
              * We fiddle with the current role in native_create_actions()
              */
             rsc->role = RSC_ROLE_STARTED;
         }
     }
 
     if (current == NULL && is_set(rsc->flags, pe_rsc_orphan)) {
         /* Don't log stopped orphans */
         return;
     }
 
     if (is_not_set(rsc->flags, pe_rsc_managed)
         || (current == NULL && next == NULL)) {
         pe_rsc_info(rsc, "Leave   %s\t(%s%s)",
                     rsc->id, role2text(rsc->role), is_not_set(rsc->flags,
                                                               pe_rsc_managed) ? " unmanaged" : "");
         return;
     }
 
     if (current != NULL && next != NULL && safe_str_neq(current->details->id, next->details->id)) {
         moving = TRUE;
     }
 
     key = start_key(rsc);
     possible_matches = find_actions(rsc->actions, key, next);
     free(key);
     if (possible_matches) {
         start = possible_matches->data;
         g_list_free(possible_matches);
     }
 
     key = stop_key(rsc);
     possible_matches = find_actions(rsc->actions, key, next);
     free(key);
     if (possible_matches) {
         stop = possible_matches->data;
         g_list_free(possible_matches);
     }
 
     key = promote_key(rsc);
     possible_matches = find_actions(rsc->actions, key, next);
     free(key);
     if (possible_matches) {
         promote = possible_matches->data;
         g_list_free(possible_matches);
     }
 
     key = demote_key(rsc);
     possible_matches = find_actions(rsc->actions, key, next);
     free(key);
     if (possible_matches) {
         demote = possible_matches->data;
         g_list_free(possible_matches);
     }
 
     if (rsc->role == rsc->next_role) {
         key = generate_op_key(rsc->id, RSC_MIGRATED, 0);
         possible_matches = find_actions(rsc->actions, key, next);
         free(key);
 
         CRM_CHECK(next != NULL,);
         if (next == NULL) {
         } else if (possible_matches && current) {
             log_change("Migrate %s\t(%s %s -> %s)",
                        rsc->id, role2text(rsc->role), current->details->uname,
                        next->details->uname);
             g_list_free(possible_matches);
 
         } else if (is_set(rsc->flags, pe_rsc_reload)) {
             log_change("Reload  %s\t(%s %s)", rsc->id, role2text(rsc->role), next->details->uname);
 
         } else if (start == NULL || is_set(start->flags, pe_action_optional)) {
             pe_rsc_info(rsc, "Leave   %s\t(%s %s)", rsc->id, role2text(rsc->role),
                         next->details->uname);
 
         } else if (start && is_set(start->flags, pe_action_runnable) == FALSE) {
             log_change("Stop    %s\t(%s %s)", rsc->id, role2text(rsc->role), next->details->uname);
 
         } else if (moving && current) {
             log_change("%s %s\t(%s %s -> %s)",
                        is_set(rsc->flags, pe_rsc_failed) ? "Recover" : "Move   ",
                        rsc->id, role2text(rsc->role),
                        current->details->uname, next->details->uname);
 
         } else if (is_set(rsc->flags, pe_rsc_failed)) {
             log_change("Recover %s\t(%s %s)", rsc->id, role2text(rsc->role), next->details->uname);
 
         } else {
             log_change("Restart %s\t(%s %s)", rsc->id, role2text(rsc->role), next->details->uname);
         }
 
         return;
     }
 
     if (rsc->role > RSC_ROLE_SLAVE && rsc->role > rsc->next_role) {
         CRM_CHECK(current != NULL,);
         if (current != NULL) {
             gboolean allowed = FALSE;
 
             if (demote != NULL && (demote->flags & pe_action_runnable)) {
                 allowed = TRUE;
             }
 
             log_change("Demote  %s\t(%s -> %s %s%s)",
                        rsc->id,
                        role2text(rsc->role),
                        role2text(rsc->next_role),
                        current->details->uname, allowed ? "" : " - blocked");
 
             if (stop != NULL && is_not_set(stop->flags, pe_action_optional)
                 && rsc->next_role > RSC_ROLE_STOPPED) {
                 if (is_set(rsc->flags, pe_rsc_failed)) {
                     log_change("Recover %s\t(%s %s)",
                                rsc->id, role2text(rsc->role), next->details->uname);
 
                 } else if (is_set(rsc->flags, pe_rsc_reload)) {
                     log_change("Reload  %s\t(%s %s)", rsc->id, role2text(rsc->role),
                                next->details->uname);
 
                 } else {
                     log_change("Restart %s\t(%s %s)",
                                rsc->id, role2text(rsc->next_role), next->details->uname);
                 }
             }
         }
 
     } else if (rsc->next_role == RSC_ROLE_STOPPED) {
         GListPtr gIter = NULL;
 
         CRM_CHECK(current != NULL,);
 
         key = stop_key(rsc);
         for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
             node_t *node = (node_t *) gIter->data;
             action_t *stop_op = NULL;
             gboolean allowed = FALSE;
 
             possible_matches = find_actions(rsc->actions, key, node);
             if (possible_matches) {
                 stop_op = possible_matches->data;
                 g_list_free(possible_matches);
             }
 
             if (stop_op && (stop_op->flags & pe_action_runnable)) {
                 allowed = TRUE;
             }
 
             log_change("Stop    %s\t(%s%s)", rsc->id, node->details->uname,
                        allowed ? "" : " - blocked");
         }
 
         free(key);
     }
 
     if (moving) {
         log_change("Move    %s\t(%s %s -> %s)",
                    rsc->id, role2text(rsc->next_role), current->details->uname,
                    next->details->uname);
     }
 
     if (rsc->role == RSC_ROLE_STOPPED) {
         gboolean allowed = FALSE;
 
         if (start && (start->flags & pe_action_runnable)) {
             allowed = TRUE;
         }
 
         CRM_CHECK(next != NULL,);
         if (next != NULL) {
             log_change("Start   %s\t(%s%s)", rsc->id, next->details->uname,
                        allowed ? "" : " - blocked");
         }
         if (allowed == FALSE) {
             return;
         }
     }
 
     if (rsc->next_role > RSC_ROLE_SLAVE && rsc->role < rsc->next_role) {
         gboolean allowed = FALSE;
 
         CRM_CHECK(next != NULL,);
         if (stop != NULL && is_not_set(stop->flags, pe_action_optional)
             && rsc->role > RSC_ROLE_STOPPED) {
             if (is_set(rsc->flags, pe_rsc_failed)) {
                 log_change("Recover %s\t(%s %s)",
                            rsc->id, role2text(rsc->role), next->details->uname);
 
             } else if (is_set(rsc->flags, pe_rsc_reload)) {
                 log_change("Reload  %s\t(%s %s)", rsc->id, role2text(rsc->role),
                            next->details->uname);
 
             } else {
                 log_change("Restart %s\t(%s %s)",
                            rsc->id, role2text(rsc->role), next->details->uname);
             }
         }
 
         if (promote && (promote->flags & pe_action_runnable)) {
             allowed = TRUE;
         }
 
         log_change("Promote %s\t(%s -> %s %s%s)",
                    rsc->id,
                    role2text(rsc->role),
                    role2text(rsc->next_role), next->details->uname, allowed ? "" : " - blocked");
     }
 }
 
 gboolean
 StopRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
 {
     GListPtr gIter = NULL;
 
     pe_rsc_trace(rsc, "%s", rsc->id);
 
     for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
         node_t *current = (node_t *) gIter->data;
         action_t *stop;
 
         if (rsc->partial_migration_target) {
             if (rsc->partial_migration_target->details == current->details) {
                 pe_rsc_trace(rsc, "Filtered %s -> %s %s", current->details->uname,
                              next->details->uname, rsc->id);
                 continue;
             } else {
                 pe_rsc_trace(rsc, "Forced on %s %s", current->details->uname, rsc->id);
                 optional = FALSE;
             }
         }
 
         pe_rsc_trace(rsc, "%s on %s", rsc->id, current->details->uname);
         stop = stop_action(rsc, current, optional);
 
         if (is_not_set(rsc->flags, pe_rsc_managed)) {
             update_action_flags(stop, pe_action_runnable | pe_action_clear);
         }
 
         if (is_set(data_set->flags, pe_flag_remove_after_stop)) {
             DeleteRsc(rsc, current, optional, data_set);
         }
     }
 
     return TRUE;
 }
 
 gboolean
 StartRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
 {
     action_t *start = NULL;
 
     pe_rsc_trace(rsc, "%s on %s %d", rsc->id, next ? next->details->uname : "N/A", optional);
     start = start_action(rsc, next, TRUE);
     if (is_set(start->flags, pe_action_runnable) && optional == FALSE) {
         update_action_flags(start, pe_action_optional | pe_action_clear);
     }
     return TRUE;
 }
 
 gboolean
 PromoteRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
 {
     char *key = NULL;
     GListPtr gIter = NULL;
     gboolean runnable = TRUE;
     GListPtr action_list = NULL;
 
     pe_rsc_trace(rsc, "%s on %s", rsc->id, next ? next->details->uname : "N/A");
 
     CRM_CHECK(next != NULL, return FALSE);
 
     key = start_key(rsc);
     action_list = find_actions_exact(rsc->actions, key, next);
     free(key);
 
     for (gIter = action_list; gIter != NULL; gIter = gIter->next) {
         action_t *start = (action_t *) gIter->data;
 
         if (is_set(start->flags, pe_action_runnable) == FALSE) {
             runnable = FALSE;
         }
     }
     g_list_free(action_list);
 
     if (runnable) {
         promote_action(rsc, next, optional);
         return TRUE;
     }
 
     pe_rsc_debug(rsc, "%s\tPromote %s (canceled)", next->details->uname, rsc->id);
 
     key = promote_key(rsc);
     action_list = find_actions_exact(rsc->actions, key, next);
     free(key);
 
     for (gIter = action_list; gIter != NULL; gIter = gIter->next) {
         action_t *promote = (action_t *) gIter->data;
 
         update_action_flags(promote, pe_action_runnable | pe_action_clear);
     }
 
     g_list_free(action_list);
     return TRUE;
 }
 
 gboolean
 DemoteRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
 {
     GListPtr gIter = NULL;
 
     pe_rsc_trace(rsc, "%s", rsc->id);
 
 /* 	CRM_CHECK(rsc->next_role == RSC_ROLE_SLAVE, return FALSE); */
     for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) {
         node_t *current = (node_t *) gIter->data;
 
         pe_rsc_trace(rsc, "%s on %s", rsc->id, next ? next->details->uname : "N/A");
         demote_action(rsc, current, optional);
     }
     return TRUE;
 }
 
 gboolean
 RoleError(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
 {
     crm_err("%s on %s", rsc->id, next ? next->details->uname : "N/A");
     CRM_CHECK(FALSE, return FALSE);
     return FALSE;
 }
 
 gboolean
 NullOp(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set)
 {
     pe_rsc_trace(rsc, "%s", rsc->id);
     return FALSE;
 }
 
 gboolean
 DeleteRsc(resource_t * rsc, node_t * node, gboolean optional, pe_working_set_t * data_set)
 {
     if (is_set(rsc->flags, pe_rsc_failed)) {
         pe_rsc_trace(rsc, "Resource %s not deleted from %s: failed", rsc->id, node->details->uname);
         return FALSE;
 
     } else if (node == NULL) {
         pe_rsc_trace(rsc, "Resource %s not deleted: NULL node", rsc->id);
         return FALSE;
 
     } else if (node->details->unclean || node->details->online == FALSE) {
         pe_rsc_trace(rsc, "Resource %s not deleted from %s: unrunnable", rsc->id,
                      node->details->uname);
         return FALSE;
     }
 
     crm_notice("Removing %s from %s", rsc->id, node->details->uname);
 
     delete_action(rsc, node, optional);
 
     new_rsc_order(rsc, RSC_STOP, rsc, RSC_DELETE,
                   optional ? pe_order_implies_then : pe_order_optional, data_set);
 
     new_rsc_order(rsc, RSC_DELETE, rsc, RSC_START,
                   optional ? pe_order_implies_then : pe_order_optional, data_set);
 
     return TRUE;
 }
 
 #include <../lib/pengine/unpack.h>
 #define set_char(x) last_rsc_id[lpc] = x; complete = TRUE;
 static char *
 increment_clone(char *last_rsc_id)
 {
     int lpc = 0;
     int len = 0;
     char *tmp = NULL;
     gboolean complete = FALSE;
 
     CRM_CHECK(last_rsc_id != NULL, return NULL);
     if (last_rsc_id != NULL) {
         len = strlen(last_rsc_id);
     }
 
     lpc = len - 1;
     while (complete == FALSE && lpc > 0) {
         switch (last_rsc_id[lpc]) {
             case 0:
                 lpc--;
                 break;
             case '0':
                 set_char('1');
                 break;
             case '1':
                 set_char('2');
                 break;
             case '2':
                 set_char('3');
                 break;
             case '3':
                 set_char('4');
                 break;
             case '4':
                 set_char('5');
                 break;
             case '5':
                 set_char('6');
                 break;
             case '6':
                 set_char('7');
                 break;
             case '7':
                 set_char('8');
                 break;
             case '8':
                 set_char('9');
                 break;
             case '9':
                 last_rsc_id[lpc] = '0';
                 lpc--;
                 break;
             case ':':
                 tmp = last_rsc_id;
                 last_rsc_id = calloc(1, len + 2);
                 memcpy(last_rsc_id, tmp, len);
                 last_rsc_id[++lpc] = '1';
                 last_rsc_id[len] = '0';
                 last_rsc_id[len + 1] = 0;
                 complete = TRUE;
                 free(tmp);
                 break;
             default:
                 crm_err("Unexpected char: %c (%d)", last_rsc_id[lpc], lpc);
                 return NULL;
                 break;
         }
     }
     return last_rsc_id;
 }
 
 static node_t *
 probe_grouped_clone(resource_t * rsc, node_t * node, pe_working_set_t * data_set)
 {
     node_t *running = NULL;
     resource_t *top = uber_parent(rsc);
 
     if (running == NULL && is_set(top->flags, pe_rsc_unique) == FALSE) {
         /* Annoyingly we also need to check any other clone instances
          * Clumsy, but it will work.
          *
          * An alternative would be to update known_on for every peer
          * during process_rsc_state()
          *
          * This code desperately needs optimization
          * ptest -x with 100 nodes, 100 clones and clone-max=10:
          *   No probes                          O(25s)
          *   Detection without clone loop               O(3m)
          *   Detection with clone loop                  O(8m)
 
          ptest[32211]: 2010/02/18_14:27:55 CRIT: stage5: Probing for unknown resources
          ptest[32211]: 2010/02/18_14:33:39 CRIT: stage5: Done
          ptest[32211]: 2010/02/18_14:35:05 CRIT: stage7: Updating action states
          ptest[32211]: 2010/02/18_14:35:05 CRIT: stage7: Done
 
          */
         char *clone_id = clone_zero(rsc->id);
         resource_t *peer = pe_find_resource(top->children, clone_id);
 
         while (peer && running == NULL) {
             running = pe_hash_table_lookup(peer->known_on, node->details->id);
             if (running != NULL) {
                 /* we already know the status of the resource on this node */
                 pe_rsc_trace(rsc, "Skipping active clone: %s", rsc->id);
                 free(clone_id);
                 return running;
             }
             clone_id = increment_clone(clone_id);
             peer = pe_find_resource(data_set->resources, clone_id);
         }
 
         free(clone_id);
     }
     return running;
 }
 
 gboolean
 native_create_probe(resource_t * rsc, node_t * node, action_t * complete,
                     gboolean force, pe_working_set_t * data_set)
 {
     char *key = NULL;
     action_t *probe = NULL;
     node_t *running = NULL;
     resource_t *top = uber_parent(rsc);
 
     static const char *rc_master = NULL;
     static const char *rc_inactive = NULL;
 
     if (rc_inactive == NULL) {
         rc_inactive = crm_itoa(PCMK_OCF_NOT_RUNNING);
         rc_master = crm_itoa(PCMK_OCF_RUNNING_MASTER);
     }
 
     CRM_CHECK(node != NULL, return FALSE);
     if (force == FALSE && is_not_set(data_set->flags, pe_flag_startup_probes)) {
         pe_rsc_trace(rsc, "Skipping active resource detection for %s", rsc->id);
         return FALSE;
     } else if (force == FALSE && is_container_remote_node(node)) {
         pe_rsc_trace(rsc, "Skipping active resource detection for %s on container %s",
                      rsc->id, node->details->id);
         return FALSE;
     }
 
     if (is_remote_node(node)) {
         const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
 
         if (safe_str_eq(class, "stonith")) {
             pe_rsc_trace(rsc, "Skipping probe for %s on node %s, remote-nodes do not run stonith agents.", rsc->id, node->details->id);
             return FALSE;
         } else if (rsc_contains_remote_node(data_set, rsc)) {
             pe_rsc_trace(rsc, "Skipping probe for %s on node %s, remote-nodes can not run resources that contain connection resources.", rsc->id, node->details->id);
             return FALSE;
         } else if (rsc->is_remote_node) {
             pe_rsc_trace(rsc, "Skipping probe for %s on node %s, remote-nodes can not run connection resources", rsc->id, node->details->id);
             return FALSE;
         }
     }
 
     if (rsc->children) {
         GListPtr gIter = NULL;
         gboolean any_created = FALSE;
 
         for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
             resource_t *child_rsc = (resource_t *) gIter->data;
 
             any_created = child_rsc->cmds->create_probe(child_rsc, node, complete, force, data_set)
                 || any_created;
         }
 
         return any_created;
 
     } else if (rsc->container) {
         pe_rsc_trace(rsc, "Skipping %s: it is within container %s", rsc->id, rsc->container->id);
         return FALSE;
     }
 
     if (is_set(rsc->flags, pe_rsc_orphan)) {
         pe_rsc_trace(rsc, "Skipping orphan: %s", rsc->id);
         return FALSE;
     }
 
     running = g_hash_table_lookup(rsc->known_on, node->details->id);
     if (running == NULL && is_set(rsc->flags, pe_rsc_unique) == FALSE) {
         /* Anonymous clones */
         if (rsc->parent == top) {
             running = g_hash_table_lookup(rsc->parent->known_on, node->details->id);
 
         } else {
             /* Grouped anonymous clones need extra special handling */
             running = probe_grouped_clone(rsc, node, data_set);
         }
     }
 
     if (force == FALSE && running != NULL) {
         /* we already know the status of the resource on this node */
         pe_rsc_trace(rsc, "Skipping active: %s on %s", rsc->id, node->details->uname);
         return FALSE;
     }
 
     key = generate_op_key(rsc->id, RSC_STATUS, 0);
     probe = custom_action(rsc, key, RSC_STATUS, node, FALSE, TRUE, data_set);
     update_action_flags(probe, pe_action_optional | pe_action_clear);
 
     /* Check if the node needs to be unfenced first */
     if (is_set(rsc->flags, pe_rsc_needs_unfencing)) {
         action_t *unfence = pe_fence_op(node, "on", data_set);
 
         crm_notice("Unfencing %s for %s", node->details->uname, rsc->id);
         order_actions(unfence, probe, pe_order_implies_then);
 
         /* The lack of ordering constraints on STONITH_UP would
          * traditionally mean unfencing is initiated /before/ the
          * devices are started.
          *
          * However this is a non-issue as stonithd is now smart
          * enough to be able to use devices directly from the cib
          */
     }
 
     /*
      * We need to know if it's running_on (not just known_on) this node
      * to correctly determine the target rc.
      */
     running = pe_find_node_id(rsc->running_on, node->details->id);
     if (running == NULL) {
         add_hash_param(probe->meta, XML_ATTR_TE_TARGET_RC, rc_inactive);
 
     } else if (rsc->role == RSC_ROLE_MASTER) {
         add_hash_param(probe->meta, XML_ATTR_TE_TARGET_RC, rc_master);
     }
 
     pe_rsc_debug(rsc, "Probing %s on %s (%s)", rsc->id, node->details->uname, role2text(rsc->role));
     order_actions(probe, complete, pe_order_implies_then);
 
     return TRUE;
 }
 
 static void
 native_start_constraints(resource_t * rsc, action_t * stonith_op, gboolean is_stonith,
                          pe_working_set_t * data_set)
 {
     node_t *target = stonith_op ? stonith_op->node : NULL;
 
     GListPtr gIter = NULL;
     action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set);
     action_t *stonith_done = get_pseudo_op(STONITH_DONE, data_set);
 
     for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
         action_t *action = (action_t *) gIter->data;
 
         if (action->needs == rsc_req_stonith) {
             order_actions(stonith_done, action, pe_order_optional);
 
         } else if (target != NULL && safe_str_eq(action->task, RSC_START)
                    && NULL == pe_hash_table_lookup(rsc->known_on, target->details->id)) {
             /* if known == NULL, then we dont know if
              *   the resource is active on the node
              *   we're about to shoot
              *
              * in this case, regardless of action->needs,
              *   the only safe option is to wait until
              *   the node is shot before doing anything
              *   to with the resource
              *
              * its analogous to waiting for all the probes
              *   for rscX to complete before starting rscX
              *
              * the most likely explaination is that the
              *   DC died and took its status with it
              */
 
             pe_rsc_debug(rsc, "Ordering %s after %s recovery", action->uuid,
                          target->details->uname);
             order_actions(all_stopped, action, pe_order_optional | pe_order_runnable_left);
         }
     }
 }
 
 static void
 native_stop_constraints(resource_t * rsc, action_t * stonith_op, gboolean is_stonith,
                         pe_working_set_t * data_set)
 {
     char *key = NULL;
     GListPtr gIter = NULL;
     GListPtr action_list = NULL;
     resource_t *top = uber_parent(rsc);
 
     key = stop_key(rsc);
     action_list = find_actions(rsc->actions, key, stonith_op->node);
     free(key);
 
     /* add the stonith OP as a stop pre-req and the mark the stop
      * as a pseudo op - since its now redundant
      */
 
     for (gIter = action_list; gIter != NULL; gIter = gIter->next) {
         action_t *action = (action_t *) gIter->data;
 
         if (action->node->details->online
             && action->node->details->unclean == FALSE && is_set(rsc->flags, pe_rsc_failed)) {
             continue;
         }
 
         if (is_set(rsc->flags, pe_rsc_failed)) {
             crm_notice("Stop of failed resource %s is"
                        " implicit after %s is fenced", rsc->id, action->node->details->uname);
         } else {
             crm_info("%s is implicit after %s is fenced",
                      action->uuid, action->node->details->uname);
         }
 
         /* the stop would never complete and is
          * now implied by the stonith operation
          */
         update_action_flags(action, pe_action_pseudo);
         update_action_flags(action, pe_action_runnable);
         update_action_flags(action, pe_action_implied_by_stonith);
 
         {
             action_t *parent_stop = find_first_action(top->actions, NULL, RSC_STOP, NULL);
 
             order_actions(stonith_op, action, pe_order_optional);
             order_actions(stonith_op, parent_stop, pe_order_optional);
         }
 
         if (is_set(rsc->flags, pe_rsc_notify)) {
             /* Create a second notification that will be delivered
              *   immediately after the node is fenced
              *
              * Basic problem:
              * - C is a clone active on the node to be shot and stopping on another
              * - R is a resource that depends on C
              *
              * + C.stop depends on R.stop
              * + C.stopped depends on STONITH
              * + C.notify depends on C.stopped
              * + C.healthy depends on C.notify
              * + R.stop depends on C.healthy
              *
              * The extra notification here changes
              *  + C.healthy depends on C.notify
              * into:
              *  + C.healthy depends on C.notify'
              *  + C.notify' depends on STONITH'
              * thus breaking the loop
              */
             notify_data_t *n_data =
                 create_notification_boundaries(rsc, RSC_STOP, NULL, stonith_op, data_set);
             crm_info("Creating secondary notification for %s", action->uuid);
 
             collect_notification_data(rsc, TRUE, FALSE, n_data);
             g_hash_table_insert(n_data->keys, strdup("notify_stop_resource"), strdup(rsc->id));
             g_hash_table_insert(n_data->keys, strdup("notify_stop_uname"),
                                 strdup(action->node->details->uname));
             create_notifications(uber_parent(rsc), n_data, data_set);
             free_notification_data(n_data);
         }
 
 /* From Bug #1601, successful fencing must be an input to a failed resources stop action.
 
    However given group(rA, rB) running on nodeX and B.stop has failed,
    A := stop healthy resource (rA.stop)
    B := stop failed resource (pseudo operation B.stop)
    C := stonith nodeX
    A requires B, B requires C, C requires A
    This loop would prevent the cluster from making progress.
 
    This block creates the "C requires A" dependency and therefore must (at least
    for now) be disabled.
 
    Instead, run the block above and treat all resources on nodeX as B would be
    (marked as a pseudo op depending on the STONITH).
 
    TODO: Break the "A requires B" dependency in update_action() and re-enable this block
 
    } else if(is_stonith == FALSE) {
    crm_info("Moving healthy resource %s"
    " off %s before fencing",
    rsc->id, node->details->uname);
 
    * stop healthy resources before the
    * stonith op
    *
    custom_action_order(
    rsc, stop_key(rsc), NULL,
    NULL,strdup(CRM_OP_FENCE),stonith_op,
    pe_order_optional, data_set);
 */
     }
 
     g_list_free(action_list);
 
     key = demote_key(rsc);
     action_list = find_actions(rsc->actions, key, stonith_op->node);
     free(key);
 
     for (gIter = action_list; gIter != NULL; gIter = gIter->next) {
         action_t *action = (action_t *) gIter->data;
 
         if (action->node->details->online == FALSE || action->node->details->unclean == TRUE
             || is_set(rsc->flags, pe_rsc_failed)) {
             if (is_set(rsc->flags, pe_rsc_failed)) {
                 pe_rsc_info(rsc, "Demote of failed resource %s is"
                             " implict after %s is fenced", rsc->id, action->node->details->uname);
             } else {
                 pe_rsc_info(rsc, "%s is implicit after %s is fenced",
                             action->uuid, action->node->details->uname);
             }
             /* the stop would never complete and is
              * now implied by the stonith operation
              */
             crm_trace("here - 1");
             update_action_flags(action, pe_action_pseudo);
             update_action_flags(action, pe_action_runnable);
             if (is_stonith == FALSE) {
                 order_actions(stonith_op, action, pe_order_optional);
             }
         }
     }
 
     g_list_free(action_list);
 }
 
 void
 rsc_stonith_ordering(resource_t * rsc, action_t * stonith_op, pe_working_set_t * data_set)
 {
     gboolean is_stonith = FALSE;
 
     if (rsc->children) {
         GListPtr gIter = NULL;
 
         for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
             resource_t *child_rsc = (resource_t *) gIter->data;
 
             rsc_stonith_ordering(child_rsc, stonith_op, data_set);
         }
         return;
     }
 
     if (is_not_set(rsc->flags, pe_rsc_managed)) {
         pe_rsc_trace(rsc, "Skipping fencing constraints for unmanaged resource: %s", rsc->id);
         return;
     }
 
     /* Start constraints */
     native_start_constraints(rsc, stonith_op, is_stonith, data_set);
 
     /* Stop constraints */
     if (stonith_op) {
         native_stop_constraints(rsc, stonith_op, is_stonith, data_set);
     }
 }
 
 enum stack_activity {
     stack_stable = 0,
     stack_starting = 1,
     stack_stopping = 2,
     stack_middle = 4,
 };
 
 static enum stack_activity
 find_clone_activity_on(resource_t * rsc, resource_t * target, node_t * node, const char *type)
 {
     int mode = stack_stable;
     action_t *active = NULL;
 
     if (target->children) {
         GListPtr gIter = NULL;
 
         for (gIter = target->children; gIter != NULL; gIter = gIter->next) {
             resource_t *child = (resource_t *) gIter->data;
 
             mode |= find_clone_activity_on(rsc, child, node, type);
         }
         return mode;
     }
 
     active = find_first_action(target->actions, NULL, RSC_START, NULL);
     if (active && is_set(active->flags, pe_action_optional) == FALSE
         && is_set(active->flags, pe_action_pseudo) == FALSE) {
         pe_rsc_debug(rsc, "%s: found scheduled %s action (%s)", rsc->id, active->uuid, type);
         mode |= stack_starting;
     }
 
     active = find_first_action(target->actions, NULL, RSC_STOP, node);
     if (active && is_set(active->flags, pe_action_optional) == FALSE
         && is_set(active->flags, pe_action_pseudo) == FALSE) {
         pe_rsc_debug(rsc, "%s: found scheduled %s action (%s)", rsc->id, active->uuid, type);
         mode |= stack_stopping;
     }
 
     return mode;
 }
 
 static enum stack_activity
 check_stack_element(resource_t * rsc, resource_t * other_rsc, const char *type)
 {
     resource_t *other_p = uber_parent(other_rsc);
 
     if (other_rsc == NULL || other_rsc == rsc) {
         return stack_stable;
 
     } else if (other_p->variant == pe_native) {
         crm_notice("Cannot migrate %s due to dependency on %s (%s)", rsc->id, other_rsc->id, type);
         return stack_middle;
 
     } else if (other_rsc == rsc->parent) {
         int mode = 0;
         GListPtr gIter = NULL;
 
         for (gIter = other_rsc->rsc_cons; gIter != NULL; gIter = gIter->next) {
             rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
 
             if (constraint->score > 0) {
                 mode |= check_stack_element(rsc, constraint->rsc_rh, type);
             }
         }
         return mode;
 
     } else if (other_p->variant == pe_group) {
         crm_notice("Cannot migrate %s due to dependency on group %s (%s)",
                    rsc->id, other_rsc->id, type);
         return stack_middle;
 
     }
 
     /* else: >= clone */
     /*
 
        ## Assumption
        A depends on clone(B)
 
        ## Resource Activity During Move
 
        N1          N2              N3
        ---             ---         ---
        t0  A.stop
        t1  B.stop                          B.stop
        t2                  B.start         B.start
        t3                  A.start
 
        ## Resource Activity During Migration
 
        N1          N2              N3
        ---             ---         ---
        t0                  B.start         B.start
        t1  A.stop (1)
        t2                  A.start (2)
        t3  B.stop                          B.stop
 
        Node 1: Rewritten to be a migrate-to operation
        Node 2: Rewritten to be a migrate-from operation
 
        # Constraints
 
        The following constraints already exist in the system.
        The 'ok' and 'fail' column refers to whether they still hold for migration.
 
        a) A.stop  -> A.start - ok
        b) B.stop  -> B.start - fail
 
        c) A.stop  -> B.stop  - ok
        d) B.start -> A.start - ok
 
        e) B.stop  -> A.start - fail
        f) A.stop  -> B.start - fail
 
        ## Scenarios
        B unchanged             - ok
        B stopping only         - fail - possible after fixing 'e'
        B starting only         - fail - possible after fixing 'f'
        B stoping and starting  - fail - constraint 'b' is unfixable
        B restarting only on N2 - fail - as-per previous only rarer
 
      */
     /* Only allow migration when the clone is either stable, only starting or only stopping */
     return find_clone_activity_on(rsc, other_rsc, NULL, type);
 }
 
 static gboolean
 at_stack_bottom(resource_t * rsc)
 {
     char *key = NULL;
     action_t *start = NULL;
     action_t *other = NULL;
     int mode = stack_stable;
     GListPtr action_list = NULL;
     GListPtr gIter = NULL;
     GHashTable *coloc_list = NULL;
 
     key = start_key(rsc);
     action_list = find_actions(rsc->actions, key, NULL);
     free(key);
 
     pe_rsc_trace(rsc, "%s: processing", rsc->id);
     CRM_CHECK(action_list != NULL, return FALSE);
 
     start = action_list->data;
     g_list_free(action_list);
 
     coloc_list = g_hash_table_new(crm_str_hash, g_str_equal);
     for (gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) {
         rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
         resource_t *target = constraint->rsc_rh;
 
         pe_rsc_trace(rsc, "Checking %s: %s == %s (%d)", constraint->id, rsc->id, target->id,
                      constraint->score);
         if (constraint->score > 0) {
             mode |= check_stack_element(rsc, target, "coloc");
             if (mode & stack_middle) {
                 goto bail;
 
             } else if ((mode & stack_stopping) && (mode & stack_starting)) {
                 crm_notice("Cannot migrate %s due to colocation activity (last was %s)",
                            rsc->id, target->id);
                 goto bail;
             }
             g_hash_table_insert(coloc_list, target->id, target);
         }
     }
 
     for (gIter = start->actions_before; gIter != NULL; gIter = gIter->next) {
         action_wrapper_t *other_w = (action_wrapper_t *) gIter->data;
 
         other = other_w->action;
 
         if (other_w->type & pe_order_serialize_only) {
             pe_rsc_trace(rsc, "%s: depends on %s (serialize ordering)", rsc->id, other->uuid);
             continue;
         }
 
         pe_rsc_trace(rsc, "%s: Checking %s ordering", rsc->id, other->uuid);
 
         if(other->rsc == NULL) {
             /* No colocation involved */
             crm_trace("%s: No colocation for %s", rsc->id, other->uuid);
             continue;
 
         } else if (is_set(other->flags, pe_action_optional) == FALSE) {
             mode |= check_stack_element(rsc, other->rsc, "order");
             if ((mode & stack_middle) && g_hash_table_lookup(coloc_list, other->rsc->id)) {
                 crm_trace("%s: Stack middle: %s", rsc->id, other->rsc->id);
                 goto bail;
 
             } else if ((mode & stack_stopping) && (mode & stack_starting)) {
                 crm_notice("Cannot migrate %s due to ordering activity (last was %s)",
                            rsc->id, other->rsc->id);
                 goto bail;
             }
         }
     }
 
     g_hash_table_destroy(coloc_list);
     return TRUE;
 
   bail:
     g_hash_table_destroy(coloc_list);
     return FALSE;
 }
 
 static action_t *
 get_first_named_action(resource_t * rsc, const char *action, gboolean only_valid, node_t * current)
 {
     action_t *a = NULL;
     GListPtr action_list = NULL;
     char *key = generate_op_key(rsc->id, action, 0);
 
     action_list = find_actions(rsc->actions, key, current);
 
     if (action_list == NULL || action_list->data == NULL) {
         crm_trace("%s: no %s action", rsc->id, action);
         free(key);
         return NULL;
     }
 
     a = action_list->data;
     g_list_free(action_list);
 
     if (only_valid && is_set(a->flags, pe_action_pseudo)) {
         crm_trace("%s: pseudo", key);
         a = NULL;
 
     } else if (only_valid && is_not_set(a->flags, pe_action_runnable)) {
         crm_trace("%s: runnable", key);
         a = NULL;
     }
 
     free(key);
     return a;
 }
 
 static void
 MigrateRsc(resource_t * rsc, action_t * stop, action_t * start, pe_working_set_t * data_set,
            gboolean partial)
 {
     action_t *to = NULL;
     action_t *from = NULL;
     action_t *then = NULL;
     action_t *other = NULL;
     action_t *done = get_pseudo_op(STONITH_DONE, data_set);
 
     GListPtr gIter = NULL;
     const char *value = g_hash_table_lookup(rsc->meta, XML_OP_ATTR_ALLOW_MIGRATE);
 
     if(is_set(rsc->flags, pe_rsc_migrating)) {
         /* Already taken care of or in progress */
         return;
     }
 
     if (crm_is_true(value) == FALSE) {
         return;
     }
 
     if (rsc->next_role > RSC_ROLE_SLAVE) {
         pe_rsc_trace(rsc, "%s: resource role: role=%s", rsc->id, role2text(rsc->next_role));
         return;
     }
 
     if (start == NULL || stop == NULL) {
         pe_rsc_trace(rsc, "%s: not exists %p -> %p", rsc->id, stop, start);
         return;
 
     } else if (start->node == NULL || stop->node == NULL) {
         pe_rsc_trace(rsc, "%s: no node %p -> %p", rsc->id, stop->node, start->node);
         return;
 
     } else if (is_set(stop->flags, pe_action_optional)) {
         pe_rsc_trace(rsc, "%s: stop action", rsc->id);
         return;
 
     } else if (is_set(start->flags, pe_action_optional)) {
         pe_rsc_trace(rsc, "%s: start action", rsc->id);
         return;
 
     } else if (stop->node->details == start->node->details) {
         pe_rsc_trace(rsc, "%s: not moving %p -> %p", rsc->id, stop->node, start->node);
         return;
 
     } else if (at_stack_bottom(rsc) == FALSE) {
         pe_rsc_trace(rsc, "%s: not at stack bottom", rsc->id);
         return;
     }
 
     pe_rsc_trace(rsc, "%s %s -> %s", rsc->id, stop->node->details->uname,
                  start->node->details->uname);
 
     if (partial) {
         pe_rsc_info(rsc, "Completing partial migration of %s from %s to %s", rsc->id,
                     stop->node ? stop->node->details->uname : "unknown",
                     start->node ? start->node->details->uname : "unknown");
     } else {
         pe_rsc_info(rsc, "Migrating %s from %s to %s", rsc->id,
                     stop->node ? stop->node->details->uname : "unknown",
                     start->node ? start->node->details->uname : "unknown");
     }
 
     /* Preserve the stop to ensure the end state is sane on that node,
      * Make the start a pseudo op
      * Create migrate_to, have it depend on everything the stop did
      * Create migrate_from
      *  *-> migrate_to -> migrate_from -> stop -> start
      */
 
     set_bit(rsc->flags, pe_rsc_migrating);
     update_action_flags(start, pe_action_pseudo);       /* easier than trying to delete it from the graph
                                                          * but perhaps we should have it run anyway
                                                          */
 
     if (!partial) {
         to = custom_action(rsc, generate_op_key(rsc->id, RSC_MIGRATE, 0), RSC_MIGRATE, stop->node,
                            FALSE, TRUE, data_set);
 
         for (gIter = rsc->dangling_migrations; gIter != NULL; gIter = gIter->next) {
             node_t *current = (node_t *) gIter->data;
             action_t *stop = stop_action(rsc, current, FALSE);
 
             order_actions(stop, to, pe_order_optional);
             pe_rsc_trace(rsc, "Ordering migration after cleanup of %s on %s", rsc->id,
                          current->details->uname);
         }
     }
     from = custom_action(rsc, generate_op_key(rsc->id, RSC_MIGRATED, 0), RSC_MIGRATED, start->node,
                          FALSE, TRUE, data_set);
 
     /* This is slightly sub-optimal if 'to' fails, but always
      * run both halves of the migration before terminating the
      * transition.
      *
      * This can be removed if/when we update unpack_rsc_op() to
      * 'correctly' handle partial migrations.
      *
      * Without this, we end up stopping both sides
      */
     from->priority = INFINITY;
 
     if (!partial) {
         order_actions(to, from, pe_order_optional);
         add_hash_param(to->meta, XML_LRM_ATTR_MIGRATE_SOURCE, stop->node->details->uname);
         add_hash_param(to->meta, XML_LRM_ATTR_MIGRATE_TARGET, start->node->details->uname);
     }
 
     then = to ? to : from;
     order_actions(from, stop, pe_order_optional);
     order_actions(done, then, pe_order_optional);
     add_hash_param(from->meta, XML_LRM_ATTR_MIGRATE_SOURCE, stop->node->details->uname);
     add_hash_param(from->meta, XML_LRM_ATTR_MIGRATE_TARGET, start->node->details->uname);
 
     /* Create the correct ordering ajustments based on find_clone_activity_on(); */
 
     for (gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) {
         rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data;
         resource_t *target = constraint->rsc_rh;
 
         pe_rsc_info(rsc, "Repairing %s: %s == %s (%d)", constraint->id, rsc->id, target->id,
                     constraint->score);
 
         if (constraint->score > 0) {
             int mode = check_stack_element(rsc, target, "coloc");
             action_t *clone_stop = find_first_action(target->actions, NULL, RSC_STOP, NULL);
             action_t *clone_start = find_first_action(target->actions, NULL, RSC_STARTED, NULL);
 
             CRM_ASSERT(clone_stop != NULL);
             CRM_ASSERT(clone_start != NULL);
             CRM_ASSERT((mode & stack_middle) == 0);
             CRM_ASSERT(((mode & stack_stopping) && (mode & stack_starting)) == 0);
 
             if (mode & stack_stopping) {
 #if 0
                 crm_debug("Creating %s.start -> %s.stop ordering", rsc->id, target->id);
                 order_actions(from, clone_stop, pe_order_optional);
 #endif
                 GListPtr lpc2 = NULL;
 
                 for (lpc2 = start->actions_before; lpc2 != NULL; lpc2 = lpc2->next) {
                     action_wrapper_t *other_w = (action_wrapper_t *) lpc2->data;
 
                     /* Needed if the clone's started pseudo-action ever gets printed in the graph */
                     if (other_w->action == clone_start) {
                         crm_debug("Breaking %s -> %s ordering", other_w->action->uuid, start->uuid);
                         other_w->type = pe_order_none;
                     }
                 }
 
             } else if (mode & stack_starting) {
 #if 0
                 crm_debug("Creating %s.started -> %s.stop ordering", target->id, rsc->id);
                 order_actions(clone_start, to, pe_order_optional);
 #endif
                 GListPtr lpc2 = NULL;
 
                 for (lpc2 = clone_stop->actions_before; lpc2 != NULL; lpc2 = lpc2->next) {
                     action_wrapper_t *other_w = (action_wrapper_t *) lpc2->data;
 
                     /* Needed if the clone's stop pseudo-action ever gets printed in the graph */
                     if (other_w->action == stop) {
                         crm_debug("Breaking %s -> %s ordering", other_w->action->uuid,
                                   clone_stop->uuid);
                         other_w->type = pe_order_none;
                     }
                 }
             }
         }
     }
 
     /* Anything that needed stop to complete, now also needs start to have completed
      * However, this is implied now that start/stop are not morphed into migrate ops
      */
 
     /* The migrate_to action (aka 'then') also needs to depend on anything that the stop needed to have completed */
     for (gIter = stop->actions_before; gIter != NULL; gIter = gIter->next) {
         action_wrapper_t *other_w = (action_wrapper_t *) gIter->data;
 
         other = other_w->action;
         if (other->rsc == NULL) {
             /* nothing */
 
         } else if (is_set(other->flags, pe_action_optional) || other->rsc == rsc
                    || other->rsc == rsc->parent) {
             continue;
 
         } else {
             /* First check if they need to migrate too */
             crm_debug("Checking %s first", other->rsc->id);
             rsc_migrate_reload(other->rsc, data_set);
         }
 
         if(other->rsc && is_set(other->rsc->flags, pe_rsc_migrating)) {
             crm_debug("Breaking %s before %s (migrating)", other_w->action->uuid, stop->uuid);
             other_w->type = pe_order_none;
             continue;
         }
 
         crm_debug("Ordering %s before %s (stop)", other_w->action->uuid, then->uuid);
         order_actions(other, then, other_w->type);
     }
 
     /* The migrate_to action (aka 'then') also needs to depend on anything that the start needed to have completed */
     for (gIter = start->actions_before; gIter != NULL; gIter = gIter->next) {
         action_wrapper_t *other_w = (action_wrapper_t *) gIter->data;
 
         other = other_w->action;
         if (other->rsc == NULL) {
             /* nothing */
         } else if (is_set(other->flags, pe_action_optional) || other->rsc == rsc
                    || other->rsc == rsc->parent) {
             continue;
         }
         crm_debug("Ordering %s before %s (start)", other_w->action->uuid, then->uuid);
         order_actions(other, then, other_w->type);
     }
 }
 
 static void
 ReloadRsc(resource_t * rsc, action_t * stop, action_t * start, pe_working_set_t * data_set)
 {
     action_t *action = NULL;
     action_t *rewrite = NULL;
 
     if (is_not_set(rsc->flags, pe_rsc_try_reload)) {
         return;
 
     } else if (is_not_set(stop->flags, pe_action_optional)) {
         pe_rsc_trace(rsc, "%s: stop action", rsc->id);
         return;
 
     } else if (is_not_set(start->flags, pe_action_optional)) {
         pe_rsc_trace(rsc, "%s: start action", rsc->id);
         return;
     }
 
     pe_rsc_trace(rsc, "%s on %s", rsc->id, stop->node->details->uname);
 
     action = get_first_named_action(rsc, RSC_PROMOTE, TRUE, NULL);
     if (action && is_set(action->flags, pe_action_optional) == FALSE) {
         update_action_flags(action, pe_action_pseudo);
     }
 
     action = get_first_named_action(rsc, RSC_DEMOTE, TRUE, NULL);
     if (action && is_set(action->flags, pe_action_optional) == FALSE) {
         rewrite = action;
         update_action_flags(stop, pe_action_pseudo);
 
     } else {
         rewrite = start;
     }
 
     pe_rsc_info(rsc, "Rewriting %s of %s on %s as a reload",
                 rewrite->task, rsc->id, stop->node->details->uname);
     set_bit(rsc->flags, pe_rsc_reload);
     update_action_flags(rewrite, pe_action_optional | pe_action_clear);
 
     free(rewrite->uuid);
     free(rewrite->task);
     rewrite->task = strdup("reload");
     rewrite->uuid = generate_op_key(rsc->id, rewrite->task, 0);
 }
 
 void
 rsc_migrate_reload(resource_t * rsc, pe_working_set_t * data_set)
 {
     GListPtr gIter = NULL;
     action_t *stop = NULL;
     action_t *start = NULL;
     gboolean partial = FALSE;
 
     if(is_set(rsc->flags, pe_rsc_munging)) {
         return;
     }
     set_bit(rsc->flags, pe_rsc_munging);
 
     if (rsc->children) {
         for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
             resource_t *child_rsc = (resource_t *) gIter->data;
 
             rsc_migrate_reload(child_rsc, data_set);
         }
         return;
 
     } else if (rsc->variant > pe_native) {
         return;
     }
 
     pe_rsc_trace(rsc, "Processing %s", rsc->id);
 
     if (rsc->partial_migration_target) {
         start = get_first_named_action(rsc, RSC_START, TRUE, rsc->partial_migration_target);
         stop = get_first_named_action(rsc, RSC_STOP, TRUE, rsc->partial_migration_source);
         if (start && stop) {
             partial = TRUE;
         }
     }
 
     pe_rsc_trace(rsc, "%s %s %p", rsc->id, partial ? "partial" : "full", stop);
 
     if (!partial) {
         stop =
             get_first_named_action(rsc, RSC_STOP, TRUE,
                                    rsc->running_on ? rsc->running_on->data : NULL);
         start = get_first_named_action(rsc, RSC_START, TRUE, NULL);
     }
 
     if (is_not_set(rsc->flags, pe_rsc_managed)
         || is_set(rsc->flags, pe_rsc_failed)
         || is_set(rsc->flags, pe_rsc_start_pending)
         || rsc->next_role < RSC_ROLE_STARTED || ((g_list_length(rsc->running_on) != 1) && !partial)) {
         pe_rsc_trace(rsc, "%s: general resource state: flags=0x%.16llx", rsc->id, rsc->flags);
         return;
     }
 
     if (stop != NULL && is_set(stop->flags, pe_action_optional) && is_set(rsc->flags, pe_rsc_try_reload)) {
         ReloadRsc(rsc, stop, start, data_set);
 
     } else if (stop == NULL || is_not_set(stop->flags, pe_action_optional)) {
         MigrateRsc(rsc, stop, start, data_set, partial);
     }
 }
 
 void
 native_append_meta(resource_t * rsc, xmlNode * xml)
 {
     char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION);
 
     if (value) {
         char *name = NULL;
 
         name = crm_meta_name(XML_RSC_ATTR_INCARNATION);
         crm_xml_add(xml, name, value);
         free(name);
     }
 }