diff --git a/crmd/control.c b/crmd/control.c
index 99ef6592ff..6c40372146 100644
--- a/crmd/control.c
+++ b/crmd/control.c
@@ -1,1060 +1,1060 @@
 /*
  * 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 <crm/crm.h>
 
 #include <crm/msg_xml.h>
 
 #include <crm/pengine/rules.h>
 #include <crm/cluster/internal.h>
 #include <crm/cluster/election.h>
 #include <crm/common/ipcs.h>
 
 #include <crmd.h>
 #include <crmd_fsa.h>
 #include <fsa_proto.h>
 #include <crmd_messages.h>
 #include <crmd_callbacks.h>
 #include <crmd_lrm.h>
 #include <tengine.h>
 #include <throttle.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
 qb_ipcs_service_t *ipcs = NULL;
 
 extern gboolean crm_connect_corosync(crm_cluster_t * cluster);
 extern void crmd_ha_connection_destroy(gpointer user_data);
 
 void crm_shutdown(int nsig);
 gboolean crm_read_options(gpointer user_data);
 
 gboolean fsa_has_quorum = FALSE;
 crm_trigger_t *fsa_source = NULL;
 crm_trigger_t *config_read = NULL;
 bool no_quorum_suicide_escalation = FALSE;
 
 static gboolean
 election_timeout_popped(gpointer data)
 {
     /* Not everyone voted */
     crm_info("Election failed: Declaring ourselves the winner");
     register_fsa_input(C_TIMER_POPPED, I_ELECTION_DC, NULL);
     return FALSE;
 }
 
 /*	 A_HA_CONNECT	*/
 void
 do_ha_control(long long action,
               enum crmd_fsa_cause cause,
               enum crmd_fsa_state cur_state,
               enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     gboolean registered = FALSE;
     static crm_cluster_t *cluster = NULL;
 
     if (cluster == NULL) {
         cluster = calloc(1, sizeof(crm_cluster_t));
     }
 
     if (action & A_HA_DISCONNECT) {
         crm_cluster_disconnect(cluster);
         crm_info("Disconnected from the cluster");
 
         set_bit(fsa_input_register, R_HA_DISCONNECTED);
     }
 
     if (action & A_HA_CONNECT) {
         crm_set_status_callback(&peer_update_callback);
 
         if (is_openais_cluster()) {
 #if SUPPORT_COROSYNC
             registered = crm_connect_corosync(cluster);
 #endif
         } else if (is_heartbeat_cluster()) {
 #if SUPPORT_HEARTBEAT
             cluster->destroy = crmd_ha_connection_destroy;
             cluster->hb_dispatch = crmd_ha_msg_callback;
 
             registered = crm_cluster_connect(cluster);
             fsa_cluster_conn = cluster->hb_conn;
 
             crm_trace("Be informed of Node Status changes");
             if (registered &&
                 fsa_cluster_conn->llc_ops->set_nstatus_callback(fsa_cluster_conn,
                                                                 crmd_ha_status_callback,
                                                                 fsa_cluster_conn) != HA_OK) {
 
                 crm_err("Cannot set nstatus callback: %s",
                         fsa_cluster_conn->llc_ops->errmsg(fsa_cluster_conn));
                 registered = FALSE;
             }
 
             crm_trace("Be informed of CRM Client Status changes");
             if (registered &&
                 fsa_cluster_conn->llc_ops->set_cstatus_callback(fsa_cluster_conn,
                                                                 crmd_client_status_callback,
                                                                 fsa_cluster_conn) != HA_OK) {
 
                 crm_err("Cannot set cstatus callback: %s",
                         fsa_cluster_conn->llc_ops->errmsg(fsa_cluster_conn));
                 registered = FALSE;
             }
 
             if (registered) {
                 crm_trace("Requesting an initial dump of CRMD client_status");
                 fsa_cluster_conn->llc_ops->client_status(fsa_cluster_conn, NULL, CRM_SYSTEM_CRMD,
                                                          -1);
             }
 #endif
         }
         fsa_election = election_init(NULL, cluster->uname, 60000/*60s*/, election_timeout_popped);
         fsa_our_uname = cluster->uname;
         fsa_our_uuid = cluster->uuid;
         if(cluster->uuid == NULL) {
             crm_err("Could not obtain local uuid");
             registered = FALSE;
         }
 
         if (registered == FALSE) {
             set_bit(fsa_input_register, R_HA_DISCONNECTED);
             register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
             return;
         }
 
         populate_cib_nodes(node_update_none, __FUNCTION__);
         clear_bit(fsa_input_register, R_HA_DISCONNECTED);
         crm_info("Connected to the cluster");
     }
 
     if (action & ~(A_HA_CONNECT | A_HA_DISCONNECT)) {
         crm_err("Unexpected action %s in %s", fsa_action2string(action), __FUNCTION__);
     }
 }
 
 /*	 A_SHUTDOWN	*/
 void
 do_shutdown(long long action,
             enum crmd_fsa_cause cause,
             enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     /* just in case */
     set_bit(fsa_input_register, R_SHUTDOWN);
 
     if (is_heartbeat_cluster()) {
         if (is_set(fsa_input_register, pe_subsystem->flag_connected)) {
             crm_info("Terminating the %s", pe_subsystem->name);
             if (stop_subsystem(pe_subsystem, TRUE) == FALSE) {
                 /* its gone... */
                 crm_err("Faking %s exit", pe_subsystem->name);
                 clear_bit(fsa_input_register, pe_subsystem->flag_connected);
             } else {
                 crm_info("Waiting for subsystems to exit");
                 crmd_fsa_stall(FALSE);
             }
         }
         crm_info("All subsystems stopped, continuing");
     }
 
     if (stonith_api) {
         /* Prevent it from comming up again */
         clear_bit(fsa_input_register, R_ST_REQUIRED);
 
         crm_info("Disconnecting STONITH...");
         stonith_api->cmds->disconnect(stonith_api);
     }
 }
 
 /*	 A_SHUTDOWN_REQ	*/
 void
 do_shutdown_req(long long action,
                 enum crmd_fsa_cause cause,
                 enum crmd_fsa_state cur_state,
                 enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     xmlNode *msg = NULL;
 
     crm_info("Sending shutdown request to %s", crm_str(fsa_our_dc));
     msg = create_request(CRM_OP_SHUTDOWN_REQ, NULL, NULL, CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL);
 
 /* 	set_bit(fsa_input_register, R_STAYDOWN); */
     if (send_cluster_message(NULL, crm_msg_crmd, msg, TRUE) == FALSE) {
         register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
     }
     free_xml(msg);
 }
 
 extern crm_ipc_t *attrd_ipc;
 extern char *max_generation_from;
 extern xmlNode *max_generation_xml;
 extern GHashTable *resource_history;
 extern GHashTable *voted;
 extern GHashTable *reload_hash;
 extern char *te_client_id;
 
 void log_connected_client(gpointer key, gpointer value, gpointer user_data);
 
 void
 log_connected_client(gpointer key, gpointer value, gpointer user_data)
 {
     crm_client_t *client = value;
 
     crm_err("%s is still connected at exit", crm_client_name(client));
 }
 
 int
 crmd_fast_exit(int rc) 
 {
     if (is_set(fsa_input_register, R_STAYDOWN)) {
         crm_warn("Inhibiting respawn: %d -> %d", rc, 100);
         rc = 100;
     }
 
     if (rc == pcmk_ok && is_set(fsa_input_register, R_IN_RECOVERY)) {
         crm_err("Could not recover from internal error");
         rc = pcmk_err_generic;
     }
     return crm_exit(rc);
 }
 
 int
 crmd_exit(int rc)
 {
     GListPtr gIter = NULL;
     GMainLoop *mloop = crmd_mainloop;
 
     static bool in_progress = FALSE;
 
     if(in_progress && rc == 0) {
         crm_debug("Exit is already in progress");
         return rc;
 
     } else if(in_progress) {
         crm_notice("Error during shutdown process, terminating now: %s (%d)", pcmk_strerror(rc), rc);
         crm_write_blackbox(SIGTRAP, NULL);
         crmd_fast_exit(rc);
     }
 
     in_progress = TRUE;
     crm_trace("Preparing to exit: %d", rc);
 
     /* Suppress secondary errors resulting from us disconnecting everything */
     set_bit(fsa_input_register, R_HA_DISCONNECTED);
 
 /* Close all IPC servers and clients to ensure any and all shared memory files are cleaned up */
 
     if(ipcs) {
         crm_trace("Closing IPC server");
         mainloop_del_ipc_server(ipcs);
         ipcs = NULL;
     }
 
     if (attrd_ipc) {
         crm_trace("Closing attrd connection");
         crm_ipc_close(attrd_ipc);
         crm_ipc_destroy(attrd_ipc);
         attrd_ipc = NULL;
     }
 
     if (pe_subsystem && pe_subsystem->client && pe_subsystem->client->ipcs) {
         crm_trace("Disconnecting Policy Engine");
         qb_ipcs_disconnect(pe_subsystem->client->ipcs);
     }
 
     if(stonith_api) {
         crm_trace("Disconnecting fencing API");
         clear_bit(fsa_input_register, R_ST_REQUIRED);
         stonith_api->cmds->free(stonith_api); stonith_api = NULL;
     }
 
     if (rc == pcmk_ok && crmd_mainloop == NULL) {
         crm_debug("No mainloop detected");
         rc = EPROTO;
     }
 
     /* On an error, just get out.
      *
      * Otherwise, make the effort to have mainloop exit gracefully so
      * that it (mostly) cleans up after itself and valgrind has less
      * to report on - allowing real errors stand out
      */
     if(rc != pcmk_ok) {
         crm_notice("Forcing immediate exit: %s (%d)", pcmk_strerror(rc), rc);
         crm_write_blackbox(SIGTRAP, NULL);
         return crmd_fast_exit(rc);
     }
 
 /* Clean up as much memory as possible for valgrind */
 
     for (gIter = fsa_message_queue; gIter != NULL; gIter = gIter->next) {
         fsa_data_t *fsa_data = gIter->data;
 
         crm_info("Dropping %s: [ state=%s cause=%s origin=%s ]",
                  fsa_input2string(fsa_data->fsa_input),
                  fsa_state2string(fsa_state),
                  fsa_cause2string(fsa_data->fsa_cause), fsa_data->origin);
         delete_fsa_input(fsa_data);
     }
 
     clear_bit(fsa_input_register, R_MEMBERSHIP);
     g_list_free(fsa_message_queue); fsa_message_queue = NULL;
 
     free(pe_subsystem); pe_subsystem = NULL;
     free(te_subsystem); te_subsystem = NULL;
     free(cib_subsystem); cib_subsystem = NULL;
 
     if (reload_hash) {
         crm_trace("Destroying reload cache with %d members", g_hash_table_size(reload_hash));
         g_hash_table_destroy(reload_hash); reload_hash = NULL;
     }
 
     election_fini(fsa_election);
     fsa_election = NULL;
 
     cib_delete(fsa_cib_conn);
     fsa_cib_conn = NULL;
 
     verify_stopped(fsa_state, LOG_WARNING);
     clear_bit(fsa_input_register, R_LRM_CONNECTED);
     lrm_state_destroy_all();
 
     /* This basically will not work, since mainloop has a reference to it */
     mainloop_destroy_trigger(fsa_source); fsa_source = NULL;
 
     mainloop_destroy_trigger(config_read); config_read = NULL;
     mainloop_destroy_trigger(stonith_reconnect); stonith_reconnect = NULL;
     mainloop_destroy_trigger(transition_trigger); transition_trigger = NULL;
 
     crm_client_cleanup();
     crm_peer_destroy();
 
     crm_timer_stop(transition_timer);
     crm_timer_stop(integration_timer);
     crm_timer_stop(finalization_timer);
     crm_timer_stop(election_trigger);
     election_timeout_stop(fsa_election);
     crm_timer_stop(shutdown_escalation_timer);
     crm_timer_stop(wait_timer);
     crm_timer_stop(recheck_timer);
 
     free(transition_timer); transition_timer = NULL;
     free(integration_timer); integration_timer = NULL;
     free(finalization_timer); finalization_timer = NULL;
     free(election_trigger); election_trigger = NULL;
     election_fini(fsa_election);
     free(shutdown_escalation_timer); shutdown_escalation_timer = NULL;
     free(wait_timer); wait_timer = NULL;
     free(recheck_timer); recheck_timer = NULL;
 
     free(fsa_our_dc_version); fsa_our_dc_version = NULL;
     free(fsa_our_uname); fsa_our_uname = NULL;
     free(fsa_our_uuid); fsa_our_uuid = NULL;
     free(fsa_our_dc); fsa_our_dc = NULL;
 
     free(fsa_cluster_name); fsa_cluster_name = NULL;
 
     free(te_uuid); te_uuid = NULL;
     free(te_client_id); te_client_id = NULL;
     free(fsa_pe_ref); fsa_pe_ref = NULL;
     free(failed_stop_offset); failed_stop_offset = NULL;
     free(failed_start_offset); failed_start_offset = NULL;
 
     free(max_generation_from); max_generation_from = NULL;
     free_xml(max_generation_xml); max_generation_xml = NULL;
 
     mainloop_destroy_signal(SIGPIPE);
     mainloop_destroy_signal(SIGUSR1);
     mainloop_destroy_signal(SIGTERM);
     mainloop_destroy_signal(SIGTRAP);
     mainloop_destroy_signal(SIGCHLD);
 
     if (mloop) {
         int lpc = 0;
         GMainContext *ctx = g_main_loop_get_context(crmd_mainloop);
 
         /* Don't re-enter this block */
         crmd_mainloop = NULL;
 
         crm_trace("Draining mainloop %d %d", g_main_loop_is_running(mloop), g_main_context_pending(ctx));
 
         while(g_main_context_pending(ctx) && lpc < 10) {
             lpc++;
             crm_trace("Iteration %d", lpc);
             g_main_context_dispatch(ctx);
         }
 
         crm_trace("Closing mainloop %d %d", g_main_loop_is_running(mloop), g_main_context_pending(ctx));
         g_main_loop_quit(mloop);
 
 #if SUPPORT_HEARTBEAT
         /* Do this only after g_main_loop_quit().
          *
          * This interface was broken (incomplete) since it was introduced.
          * ->delete() does cleanup and free most of it, but it does not
          * actually remove and destroy the corresponding GSource, so the next
          * prepare/check iteratioin would find a corrupt (because partially
          * freed) GSource, and segfault.
          *
          * Apparently one was supposed to store the GSource as returned by
          * G_main_add_ll_cluster(), and g_source_destroy() that "by hand".
          *
          * But no-one ever did this, not even in the old hb code when this was
          * introduced.
          *
          * Note that fsa_cluster_conn was set as an "alias" to cluster->hb_conn
          * in do_ha_control() right after crm_cluster_connect(), and only
          * happens to still point at that object, because do_ha_control() does
          * not reset it to NULL after crm_cluster_disconnect() above does
          * reset cluster->hb_conn to NULL.
          * Not sure if that's something to cleanup, too.
          *
          * I'll try to fix this up in heartbeat proper, so ->delete
          * will actually remove, and destroy, and unref, and free this thing.
          * Doing so after g_main_loop_quit() is valid with both old,
          * and eventually fixed heartbeat.
          *
          * If we introduce the "by hand" destroy/remove/unref,
          * this may break again once heartbeat is fixed :-(
          *
          *                                              -- Lars Ellenberg
          */
         if (fsa_cluster_conn) {
             crm_trace("Deleting heartbeat api object");
             fsa_cluster_conn->llc_ops->delete(fsa_cluster_conn);
             fsa_cluster_conn = NULL;
         }
 #endif
 
         /* Won't do anything yet, since we're inside it now */
         g_main_loop_unref(mloop);
 
         crm_trace("Done %d", rc);
     }
 
     /* Graceful */
     return rc;
 }
 
 /*	 A_EXIT_0, A_EXIT_1	*/
 void
 do_exit(long long action,
         enum crmd_fsa_cause cause,
         enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     int exit_code = pcmk_ok;
     int log_level = LOG_INFO;
     const char *exit_type = "gracefully";
 
     if (action & A_EXIT_1) {
         /* exit_code = pcmk_err_generic; */
         log_level = LOG_ERR;
         exit_type = "forcefully";
         exit_code = pcmk_err_generic;
     }
 
     verify_stopped(cur_state, LOG_ERR);
     do_crm_log(log_level, "Performing %s - %s exiting the CRMd",
                fsa_action2string(action), exit_type);
 
     crm_info("[%s] stopped (%d)", crm_system_name, exit_code);
     crmd_exit(exit_code);
 }
 
 static void sigpipe_ignore(int nsig) { return; }
 
 /*	 A_STARTUP	*/
 void
 do_startup(long long action,
            enum crmd_fsa_cause cause,
            enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     int was_error = 0;
 
     crm_debug("Registering Signal Handlers");
     mainloop_add_signal(SIGTERM, crm_shutdown);
     mainloop_add_signal(SIGPIPE, sigpipe_ignore);
 
     fsa_source = mainloop_add_trigger(G_PRIORITY_HIGH, crm_fsa_trigger, NULL);
     config_read = mainloop_add_trigger(G_PRIORITY_HIGH, crm_read_options, NULL);
     transition_trigger = mainloop_add_trigger(G_PRIORITY_LOW, te_graph_trigger, NULL);
 
     crm_debug("Creating CIB and LRM objects");
     fsa_cib_conn = cib_new();
 
     lrm_state_init_local();
 
     /* set up the timers */
     transition_timer = calloc(1, sizeof(fsa_timer_t));
     integration_timer = calloc(1, sizeof(fsa_timer_t));
     finalization_timer = calloc(1, sizeof(fsa_timer_t));
     election_trigger = calloc(1, sizeof(fsa_timer_t));
     shutdown_escalation_timer = calloc(1, sizeof(fsa_timer_t));
     wait_timer = calloc(1, sizeof(fsa_timer_t));
     recheck_timer = calloc(1, sizeof(fsa_timer_t));
 
     if (election_trigger != NULL) {
         election_trigger->source_id = 0;
         election_trigger->period_ms = -1;
         election_trigger->fsa_input = I_DC_TIMEOUT;
         election_trigger->callback = crm_timer_popped;
         election_trigger->repeat = FALSE;
     } else {
         was_error = TRUE;
     }
 
     if (transition_timer != NULL) {
         transition_timer->source_id = 0;
         transition_timer->period_ms = -1;
         transition_timer->fsa_input = I_PE_CALC;
         transition_timer->callback = crm_timer_popped;
         transition_timer->repeat = FALSE;
     } else {
         was_error = TRUE;
     }
 
     if (integration_timer != NULL) {
         integration_timer->source_id = 0;
         integration_timer->period_ms = -1;
         integration_timer->fsa_input = I_INTEGRATED;
         integration_timer->callback = crm_timer_popped;
         integration_timer->repeat = FALSE;
     } else {
         was_error = TRUE;
     }
 
     if (finalization_timer != NULL) {
         finalization_timer->source_id = 0;
         finalization_timer->period_ms = -1;
         finalization_timer->fsa_input = I_FINALIZED;
         finalization_timer->callback = crm_timer_popped;
         finalization_timer->repeat = FALSE;
         /* for possible enabling... a bug in the join protocol left
          *    a slave in S_PENDING while we think its in S_NOT_DC
          *
          * raising I_FINALIZED put us into a transition loop which is
          *    never resolved.
          * in this loop we continually send probes which the node
          *    NACK's because its in S_PENDING
          *
          * if we have nodes where heartbeat is active but the
          *    CRM is not... then this will be handled in the
          *    integration phase
          */
         finalization_timer->fsa_input = I_ELECTION;
 
     } else {
         was_error = TRUE;
     }
 
     if (shutdown_escalation_timer != NULL) {
         shutdown_escalation_timer->source_id = 0;
         shutdown_escalation_timer->period_ms = -1;
         shutdown_escalation_timer->fsa_input = I_STOP;
         shutdown_escalation_timer->callback = crm_timer_popped;
         shutdown_escalation_timer->repeat = FALSE;
     } else {
         was_error = TRUE;
     }
 
     if (wait_timer != NULL) {
         wait_timer->source_id = 0;
         wait_timer->period_ms = 2000;
         wait_timer->fsa_input = I_NULL;
         wait_timer->callback = crm_timer_popped;
         wait_timer->repeat = FALSE;
     } else {
         was_error = TRUE;
     }
 
     if (recheck_timer != NULL) {
         recheck_timer->source_id = 0;
         recheck_timer->period_ms = -1;
         recheck_timer->fsa_input = I_PE_CALC;
         recheck_timer->callback = crm_timer_popped;
         recheck_timer->repeat = FALSE;
     } else {
         was_error = TRUE;
     }
 
     /* set up the sub systems */
     cib_subsystem = calloc(1, sizeof(struct crm_subsystem_s));
     te_subsystem = calloc(1, sizeof(struct crm_subsystem_s));
     pe_subsystem = calloc(1, sizeof(struct crm_subsystem_s));
 
     if (cib_subsystem != NULL) {
         cib_subsystem->pid = -1;
         cib_subsystem->name = CRM_SYSTEM_CIB;
         cib_subsystem->flag_connected = R_CIB_CONNECTED;
         cib_subsystem->flag_required = R_CIB_REQUIRED;
 
     } else {
         was_error = TRUE;
     }
 
     if (te_subsystem != NULL) {
         te_subsystem->pid = -1;
         te_subsystem->name = CRM_SYSTEM_TENGINE;
         te_subsystem->flag_connected = R_TE_CONNECTED;
         te_subsystem->flag_required = R_TE_REQUIRED;
 
     } else {
         was_error = TRUE;
     }
 
     if (pe_subsystem != NULL) {
         pe_subsystem->pid = -1;
         pe_subsystem->path = CRM_DAEMON_DIR;
         pe_subsystem->name = CRM_SYSTEM_PENGINE;
         pe_subsystem->command = CRM_DAEMON_DIR "/" CRM_SYSTEM_PENGINE;
         pe_subsystem->args = NULL;
         pe_subsystem->flag_connected = R_PE_CONNECTED;
         pe_subsystem->flag_required = R_PE_REQUIRED;
 
     } else {
         was_error = TRUE;
     }
 
     if (was_error == FALSE && is_heartbeat_cluster()) {
         if (start_subsystem(pe_subsystem) == FALSE) {
             was_error = TRUE;
         }
     }
 
     if (was_error) {
         register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
     }
 
 }
 
 static int32_t
 crmd_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 {
     crm_trace("Connection %p", c);
     if (crm_client_new(c, uid, gid) == NULL) {
         return -EIO;
     }
     return 0;
 }
 
 static void
 crmd_ipc_created(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p", c);
 }
 
 static int32_t
 crmd_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_trace("Invoked: %s", crm_client_name(client));
     crm_ipcs_send_ack(client, id, flags, "ack", __FUNCTION__, __LINE__);
 
     if (msg == NULL) {
         return 0;
     }
 
 #if ENABLE_ACL
     CRM_ASSERT(client->user != NULL);
     crm_acl_get_set_user(msg, F_CRM_USER, client->user);
 #endif
 
     crm_trace("Processing msg from %s", crm_client_name(client));
     crm_log_xml_trace(msg, "CRMd[inbound]");
 
     crm_xml_add(msg, F_CRM_SYS_FROM, client->id);
     if (crmd_authorize_message(msg, client, NULL)) {
         route_message(C_IPC_MESSAGE, msg);
     }
 
     trigger_fsa(fsa_source);
     free_xml(msg);
     return 0;
 }
 
 static int32_t
 crmd_ipc_closed(qb_ipcs_connection_t * c)
 {
     crm_client_t *client = crm_client_get(c);
     struct crm_subsystem_s *the_subsystem = NULL;
 
     if (client == NULL) {
         return 0;
     }
 
     crm_trace("Connection %p", c);
 
     if (client->userdata == NULL) {
         crm_trace("Client hadn't registered with us yet");
 
     } else if (strcasecmp(CRM_SYSTEM_PENGINE, client->userdata) == 0) {
         the_subsystem = pe_subsystem;
 
     } else if (strcasecmp(CRM_SYSTEM_TENGINE, client->userdata) == 0) {
         the_subsystem = te_subsystem;
 
     } else if (strcasecmp(CRM_SYSTEM_CIB, client->userdata) == 0) {
         the_subsystem = cib_subsystem;
     }
 
     if (the_subsystem != NULL) {
         the_subsystem->source = NULL;
         the_subsystem->client = NULL;
         crm_info("Received HUP from %s:[%d]", the_subsystem->name, the_subsystem->pid);
 
     } else {
         /* else that was a transient client */
         crm_trace("Received HUP from transient client");
     }
 
     crm_trace("Disconnecting client %s (%p)", crm_client_name(client), client);
     free(client->userdata);
     crm_client_destroy(client);
 
     trigger_fsa(fsa_source);
     return 0;
 }
 
 static void
 crmd_ipc_destroy(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p", c);
     crmd_ipc_closed(c);
 }
 
 /*	 A_STOP	*/
 void
 do_stop(long long action,
         enum crmd_fsa_cause cause,
         enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     crm_trace("Closing IPC server");
     mainloop_del_ipc_server(ipcs); ipcs = NULL;
     register_fsa_input(C_FSA_INTERNAL, I_TERMINATE, NULL);
 }
 
 /*	 A_STARTED	*/
 void
 do_started(long long action,
            enum crmd_fsa_cause cause,
            enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     static struct qb_ipcs_service_handlers crmd_callbacks = {
         .connection_accept = crmd_ipc_accept,
         .connection_created = crmd_ipc_created,
         .msg_process = crmd_ipc_dispatch,
         .connection_closed = crmd_ipc_closed,
         .connection_destroyed = crmd_ipc_destroy
     };
 
     if (cur_state != S_STARTING) {
         crm_err("Start cancelled... %s", fsa_state2string(cur_state));
         return;
 
     } else if (is_set(fsa_input_register, R_MEMBERSHIP) == FALSE) {
         crm_info("Delaying start, no membership data (%.16llx)", R_MEMBERSHIP);
 
         crmd_fsa_stall(TRUE);
         return;
 
     } else if (is_set(fsa_input_register, R_LRM_CONNECTED) == FALSE) {
         crm_info("Delaying start, LRM not connected (%.16llx)", R_LRM_CONNECTED);
 
         crmd_fsa_stall(TRUE);
         return;
 
     } else if (is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) {
         crm_info("Delaying start, CIB not connected (%.16llx)", R_CIB_CONNECTED);
 
         crmd_fsa_stall(TRUE);
         return;
 
     } else if (is_set(fsa_input_register, R_READ_CONFIG) == FALSE) {
         crm_info("Delaying start, Config not read (%.16llx)", R_READ_CONFIG);
 
         crmd_fsa_stall(TRUE);
         return;
 
     } else if (is_set(fsa_input_register, R_PEER_DATA) == FALSE) {
 
         /* try reading from HA */
         crm_info("Delaying start, No peer data (%.16llx)", R_PEER_DATA);
 
 #if SUPPORT_HEARTBEAT
         if (is_heartbeat_cluster()) {
             HA_Message *msg = NULL;
 
             crm_trace("Looking for a HA message");
             msg = fsa_cluster_conn->llc_ops->readmsg(fsa_cluster_conn, 0);
             if (msg != NULL) {
                 crm_trace("There was a HA message");
                 ha_msg_del(msg);
             }
         }
 #endif
         crmd_fsa_stall(TRUE);
         return;
     }
 
     crm_debug("Init server comms");
     ipcs = crmd_ipc_server_init(&crmd_callbacks);
     if (ipcs == NULL) {
         crm_err("Failed to create IPC server: shutting down and inhibiting respawn");
         register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
     }
 
     if (stonith_reconnect == NULL) {
         int dummy;
 
         stonith_reconnect = mainloop_add_trigger(G_PRIORITY_LOW, te_connect_stonith, &dummy);
     }
     set_bit(fsa_input_register, R_ST_REQUIRED);
     mainloop_set_trigger(stonith_reconnect);
 
     crm_notice("The local CRM is operational");
     clear_bit(fsa_input_register, R_STARTING);
     register_fsa_input(msg_data->fsa_cause, I_PENDING, NULL);
 }
 
 /*	 A_RECOVER	*/
 void
 do_recover(long long action,
            enum crmd_fsa_cause cause,
            enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     set_bit(fsa_input_register, R_IN_RECOVERY);
     crm_warn("Fast-tracking shutdown in response to errors");
 
     register_fsa_input(C_FSA_INTERNAL, I_TERMINATE, NULL);
 }
 
 /* *INDENT-OFF* */
 pe_cluster_option crmd_opts[] = {
 	/* name, old-name, validate, default, description */
 	{ "dc-version", NULL, "string", NULL, "none", NULL, "Version of Pacemaker on the cluster's DC.", "Includes the hash which identifies the exact Mercurial changeset it was built from.  Used for diagnostic purposes." },
 	{ "cluster-infrastructure", NULL, "string", NULL, "heartbeat", NULL, "The messaging stack on which Pacemaker is currently running.", "Used for informational and diagnostic purposes." },
 	{ XML_CONFIG_ATTR_DC_DEADTIME, "dc_deadtime", "time", NULL, "20s", &check_time, "How long to wait for a response from other nodes during startup.", "The \"correct\" value will depend on the speed/load of your network and the type of switches used." },
 	{ XML_CONFIG_ATTR_RECHECK, "cluster_recheck_interval", "time",
 	  "Zero disables polling.  Positive values are an interval in seconds (unless other SI units are specified. eg. 5min)", "15min", &check_timer,
 	  "Polling interval for time based changes to options, resource parameters and constraints.",
 	  "The Cluster is primarily event driven, however the configuration can have elements that change based on time."
 	  "  To ensure these changes take effect, we can optionally poll the cluster's status for changes." },
 	{ "load-threshold", NULL, "percentage", NULL, "80%", &check_utilization,
 	  "The maximum amount of system resources that should be used by nodes in the cluster",
 	  "The cluster will slow down its recovery process when the amount of system resources used"
           " (currently CPU) approaches this limit", },
 	{ "node-action-limit", NULL, "integer", NULL, "0", &check_number,
           "The maximum number of jobs that can be scheduled per node. Defaults to 2x cores"},
 	{ XML_CONFIG_ATTR_ELECTION_FAIL, "election_timeout", "time", NULL, "2min", &check_timer, "*** Advanced Use Only ***.", "If need to adjust this value, it probably indicates the presence of a bug." },
 	{ XML_CONFIG_ATTR_FORCE_QUIT, "shutdown_escalation", "time", NULL, "20min", &check_timer, "*** Advanced Use Only ***.", "If need to adjust this value, it probably indicates the presence of a bug." },
 	{ "crmd-integration-timeout", NULL, "time", NULL, "3min", &check_timer, "*** Advanced Use Only ***.", "If need to adjust this value, it probably indicates the presence of a bug." },
 	{ "crmd-finalization-timeout", NULL, "time", NULL, "30min", &check_timer, "*** Advanced Use Only ***.", "If you need to adjust this value, it probably indicates the presence of a bug." },
 	{ "crmd-transition-delay", NULL, "time", NULL, "0s", &check_timer, "*** Advanced Use Only ***\nEnabling this option will slow down cluster recovery under all conditions", "Delay cluster recovery for the configured interval to allow for additional/related events to occur.\nUseful if your configuration is sensitive to the order in which ping updates arrive." },
 	{ "stonith-watchdog-timeout", NULL, "time", NULL, "0s", &check_timer,
 	  "How long to wait before we can assume nodes are safely down", NULL },
 	{ "no-quorum-policy", "no_quorum_policy", "enum", "stop, freeze, ignore, suicide", "stop", &check_quorum, NULL, NULL },
 
 #if SUPPORT_PLUGIN
 	{ XML_ATTR_EXPECTED_VOTES, NULL, "integer", NULL, "2", &check_number, "The number of nodes expected to be in the cluster", "Used to calculate quorum in openais based clusters." },
 #endif
 };
 /* *INDENT-ON* */
 
 void
 crmd_metadata(void)
 {
     config_metadata("CRM Daemon", "1.0",
                     "CRM Daemon Options",
                     "This is a fake resource that details the options that can be configured for the CRM Daemon.",
                     crmd_opts, DIMOF(crmd_opts));
 }
 
 static void
 verify_crmd_options(GHashTable * options)
 {
     verify_all_options(options, crmd_opts, DIMOF(crmd_opts));
 }
 
 static const char *
 crmd_pref(GHashTable * options, const char *name)
 {
     return get_cluster_pref(options, crmd_opts, DIMOF(crmd_opts), name);
 }
 
 static void
 config_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
 {
     const char *value = NULL;
     GHashTable *config_hash = NULL;
     crm_time_t *now = crm_time_new(NULL);
 
     if (rc != pcmk_ok) {
         fsa_data_t *msg_data = NULL;
 
         crm_err("Local CIB query resulted in an error: %s", pcmk_strerror(rc));
         register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
 
         if (rc == -EACCES || rc == -pcmk_err_schema_validation) {
             crm_err("The cluster is mis-configured - shutting down and staying down");
             set_bit(fsa_input_register, R_STAYDOWN);
         }
         goto bail;
     }
 
     crm_debug("Call %d : Parsing CIB options", call_id);
     config_hash =
         g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
 
     unpack_instance_attributes(output, output, XML_CIB_TAG_PROPSET, NULL, config_hash,
                                CIB_OPTIONS_FIRST, FALSE, now);
 
     verify_crmd_options(config_hash);
 
     value = crmd_pref(config_hash, XML_CONFIG_ATTR_DC_DEADTIME);
     election_trigger->period_ms = crm_get_msec(value);
 
     value = crmd_pref(config_hash, "node-action-limit"); /* Also checks migration-limit */
     throttle_update_job_max(value);
 
     value = crmd_pref(config_hash, "load-threshold");
     if(value) {
         throttle_load_target = strtof(value, NULL) / 100;
     }
 
     value = crmd_pref(config_hash, "stonith-watchdog-timeout");
-    if(crm_get_msec(value) > 0 && daemon_option("watchdog") == NULL) {
+    if(crm_get_msec(value) > 0 && !daemon_option_enabled(crm_system_name, "watchdog")) {
         do_crm_log_always(LOG_EMERG, "Shutting down pacemaker, no watchdog device configured");
         crmd_exit(DAEMON_RESPAWN_STOP);
 
-    } else if(crm_get_msec(value) <= 0 && daemon_option("watchdog")) {
+    } else if(crm_get_msec(value) <= 0 && daemon_option_enabled(crm_system_name, "watchdog")) {
         crm_warn("Watchdog enabled but no stonith-watchdog-timeout configured");
     }
 
     value = crmd_pref(config_hash, "no-quorum-policy");
-    if (safe_str_eq(value, "suicide") && daemon_option("watchdog")) {
+    if (safe_str_eq(value, "suicide") && daemon_option_enabled(crm_system_name, "watchdog")) {
         no_quorum_suicide_escalation = TRUE;
     }
 
     value = crmd_pref(config_hash, XML_CONFIG_ATTR_FORCE_QUIT);
     shutdown_escalation_timer->period_ms = crm_get_msec(value);
     /* How long to declare an election over - even if not everyone voted */
     crm_debug("Shutdown escalation occurs after: %dms", shutdown_escalation_timer->period_ms);
 
     value = crmd_pref(config_hash, XML_CONFIG_ATTR_ELECTION_FAIL);
     election_timeout_set_period(fsa_election, crm_get_msec(value));
 
     value = crmd_pref(config_hash, XML_CONFIG_ATTR_RECHECK);
     recheck_timer->period_ms = crm_get_msec(value);
     crm_debug("Checking for expired actions every %dms", recheck_timer->period_ms);
 
     value = crmd_pref(config_hash, "crmd-transition-delay");
     transition_timer->period_ms = crm_get_msec(value);
 
     value = crmd_pref(config_hash, "crmd-integration-timeout");
     integration_timer->period_ms = crm_get_msec(value);
 
     value = crmd_pref(config_hash, "crmd-finalization-timeout");
     finalization_timer->period_ms = crm_get_msec(value);
 
 #if SUPPORT_COROSYNC
     if (is_classic_ais_cluster()) {
         value = crmd_pref(config_hash, XML_ATTR_EXPECTED_VOTES);
         crm_debug("Sending expected-votes=%s to corosync", value);
         send_cluster_text(crm_class_quorum, value, TRUE, NULL, crm_msg_ais);
     }
 #endif
 
     free(fsa_cluster_name);
     fsa_cluster_name = NULL;
 
     value = g_hash_table_lookup(config_hash, "cluster-name");
     if (value) {
         fsa_cluster_name = strdup(value);
     }
 
     set_bit(fsa_input_register, R_READ_CONFIG);
     crm_trace("Triggering FSA: %s", __FUNCTION__);
     mainloop_set_trigger(fsa_source);
 
     g_hash_table_destroy(config_hash);
   bail:
     crm_time_free(now);
 }
 
 gboolean
 crm_read_options(gpointer user_data)
 {
     int call_id =
         fsa_cib_conn->cmds->query(fsa_cib_conn, XML_CIB_TAG_CRMCONFIG, NULL, cib_scope_local);
 
     fsa_register_cib_callback(call_id, FALSE, NULL, config_query_callback);
     crm_trace("Querying the CIB... call %d", call_id);
     return TRUE;
 }
 
 /*	 A_READCONFIG	*/
 void
 do_read_config(long long action,
                enum crmd_fsa_cause cause,
                enum crmd_fsa_state cur_state,
                enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     throttle_init();
     mainloop_set_trigger(config_read);
 }
 
 void
 crm_shutdown(int nsig)
 {
     if (crmd_mainloop != NULL && g_main_is_running(crmd_mainloop)) {
         if (is_set(fsa_input_register, R_SHUTDOWN)) {
             crm_err("Escalating the shutdown");
             register_fsa_input_before(C_SHUTDOWN, I_ERROR, NULL);
 
         } else {
             set_bit(fsa_input_register, R_SHUTDOWN);
             register_fsa_input(C_SHUTDOWN, I_SHUTDOWN, NULL);
 
             if (shutdown_escalation_timer->period_ms < 1) {
                 const char *value = crmd_pref(NULL, XML_CONFIG_ATTR_FORCE_QUIT);
                 int msec = crm_get_msec(value);
 
                 crm_debug("Using default shutdown escalation: %dms", msec);
                 shutdown_escalation_timer->period_ms = msec;
             }
 
             /* cant rely on this... */
             crm_notice("Requesting shutdown, upper limit is %dms",
                        shutdown_escalation_timer->period_ms);
             crm_timer_start(shutdown_escalation_timer);
         }
 
     } else {
         crm_info("exit from shutdown");
         crmd_exit(pcmk_ok);
     }
 }
diff --git a/fencing/main.c b/fencing/main.c
index b03659e05d..a331a71fe5 100644
--- a/fencing/main.c
+++ b/fencing/main.c
@@ -1,1393 +1,1393 @@
 /*
  * 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/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/common/ipcs.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>
 
 #include <crm/cib/internal.h>
 #include <crm/pengine/status.h>
 #include <allocate.h>
 
 #include <internal.h>
 
 #include <standalone_config.h>
 
 char *stonith_our_uname = NULL;
 char *stonith_our_uuid = NULL;
 long stonith_watchdog_timeout_ms = 0;
 
 GMainLoop *mainloop = NULL;
 
 gboolean stand_alone = FALSE;
 gboolean no_cib_connect = FALSE;
 gboolean stonith_shutdown_flag = FALSE;
 
 qb_ipcs_service_t *ipcs = NULL;
 xmlNode *local_cib = NULL;
 
 static cib_t *cib_api = NULL;
 static void *cib_library = NULL;
 
 static void stonith_shutdown(int nsig);
 static void stonith_cleanup(void);
 
 static int32_t
 st_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 {
     if (stonith_shutdown_flag) {
         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
 st_ipc_created(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection created for %p", c);
 }
 
 /* Exit code means? */
 static int32_t
 st_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
 {
     uint32_t id = 0;
     uint32_t flags = 0;
     int call_options = 0;
     xmlNode *request = NULL;
     crm_client_t *c = crm_client_get(qbc);
 
     if (c == NULL) {
         crm_info("Invalid client: %p", qbc);
         return 0;
     }
 
     request = crm_ipcs_recv(c, data, size, &id, &flags);
     if (request == NULL) {
         crm_ipcs_send_ack(c, id, flags, "nack", __FUNCTION__, __LINE__);
         return 0;
     }
 
     if (c->name == NULL) {
         const char *value = crm_element_value(request, F_STONITH_CLIENTNAME);
 
         if (value == NULL) {
             value = "unknown";
         }
         c->name = g_strdup_printf("%s.%u", value, c->pid);
     }
 
     crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options);
     crm_trace("Flags %u/%u for command %u from %s", flags, call_options, id, crm_client_name(c));
 
     if (is_set(call_options, st_opt_sync_call)) {
         CRM_ASSERT(flags & crm_ipc_client_response);
         CRM_LOG_ASSERT(c->request_id == 0);     /* This means the client has two synchronous events in-flight */
         c->request_id = id;     /* Reply only to the last one */
     }
 
     crm_xml_add(request, F_STONITH_CLIENTID, c->id);
     crm_xml_add(request, F_STONITH_CLIENTNAME, crm_client_name(c));
     crm_xml_add(request, F_STONITH_CLIENTNODE, stonith_our_uname);
 
     crm_log_xml_trace(request, "Client[inbound]");
     stonith_command(c, id, flags, request, NULL);
 
     free_xml(request);
     return 0;
 }
 
 /* Error code means? */
 static int32_t
 st_ipc_closed(qb_ipcs_connection_t * c)
 {
     crm_client_t *client = crm_client_get(c);
 
     if (client == NULL) {
         return 0;
     }
 
     crm_trace("Connection %p closed", c);
     crm_client_destroy(client);
 
     /* 0 means: yes, go ahead and destroy the connection */
     return 0;
 }
 
 static void
 st_ipc_destroy(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p destroyed", c);
     st_ipc_closed(c);
 }
 
 static void
 stonith_peer_callback(xmlNode * msg, void *private_data)
 {
     const char *remote_peer = crm_element_value(msg, F_ORIG);
     const char *op = crm_element_value(msg, F_STONITH_OPERATION);
 
     if (crm_str_eq(op, "poke", TRUE)) {
         return;
     }
 
     crm_log_xml_trace(msg, "Peer[inbound]");
     stonith_command(NULL, 0, 0, msg, remote_peer);
 }
 
 #if SUPPORT_HEARTBEAT
 static void
 stonith_peer_hb_callback(HA_Message * msg, void *private_data)
 {
     xmlNode *xml = convert_ha_message(NULL, msg, __FUNCTION__);
 
     stonith_peer_callback(xml, private_data);
     free_xml(xml);
 }
 
 static void
 stonith_peer_hb_destroy(gpointer user_data)
 {
     if (stonith_shutdown_flag) {
         crm_info("Heartbeat disconnection complete... exiting");
     } else {
         crm_err("Heartbeat connection lost!  Exiting.");
     }
     stonith_shutdown(0);
 }
 #endif
 
 #if SUPPORT_COROSYNC
 static void
 stonith_peer_ais_callback(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("Invalid XML: '%.120s'", data);
             free(data);
             return;
         }
         crm_xml_add(xml, F_ORIG, from);
         /* crm_xml_add_int(xml, F_SEQ, wrapper->id); */
         stonith_peer_callback(xml, NULL);
     }
 
     free_xml(xml);
     free(data);
     return;
 }
 
 static void
 stonith_peer_cs_destroy(gpointer user_data)
 {
     crm_err("Corosync connection terminated");
     stonith_shutdown(0);
 }
 #endif
 
 void
 do_local_reply(xmlNode * notify_src, const char *client_id, gboolean sync_reply, gboolean from_peer)
 {
     /* send callback to originating child */
     crm_client_t *client_obj = NULL;
     int local_rc = pcmk_ok;
 
     crm_trace("Sending response");
     client_obj = crm_client_get_by_id(client_id);
 
     crm_trace("Sending callback to request originator");
     if (client_obj == NULL) {
         local_rc = -1;
         crm_trace("No client to sent the response to.  F_STONITH_CLIENTID not set.");
 
     } else {
         int rid = 0;
 
         if (sync_reply) {
             CRM_LOG_ASSERT(client_obj->request_id);
 
             rid = client_obj->request_id;
             client_obj->request_id = 0;
 
             crm_trace("Sending response %d to %s %s",
                       rid, client_obj->name, from_peer ? "(originator of delegated request)" : "");
 
         } else {
             crm_trace("Sending an event to %s %s",
                       client_obj->name, from_peer ? "(originator of delegated request)" : "");
         }
 
         local_rc = crm_ipcs_send(client_obj, rid, notify_src, sync_reply?crm_ipc_flags_none:crm_ipc_server_event);
     }
 
     if (local_rc < pcmk_ok && client_obj != NULL) {
         crm_warn("%sSync reply to %s failed: %s",
                  sync_reply ? "" : "A-",
                  client_obj ? client_obj->name : "<unknown>", pcmk_strerror(local_rc));
     }
 }
 
 long long
 get_stonith_flag(const char *name)
 {
     if (safe_str_eq(name, T_STONITH_NOTIFY_FENCE)) {
         return 0x01;
 
     } else if (safe_str_eq(name, STONITH_OP_DEVICE_ADD)) {
         return 0x04;
 
     } else if (safe_str_eq(name, STONITH_OP_DEVICE_DEL)) {
         return 0x10;
     }
     return 0;
 }
 
 static void
 stonith_notify_client(gpointer key, gpointer value, gpointer user_data)
 {
 
     xmlNode *update_msg = user_data;
     crm_client_t *client = value;
     const char *type = NULL;
 
     CRM_CHECK(client != NULL, return);
     CRM_CHECK(update_msg != NULL, return);
 
     type = crm_element_value(update_msg, F_SUBTYPE);
     CRM_CHECK(type != NULL, crm_log_xml_err(update_msg, "notify"); return);
 
     if (client->ipcs == NULL) {
         crm_trace("Skipping client with NULL channel");
         return;
     }
 
     if (client->options & get_stonith_flag(type)) {
         int rc = crm_ipcs_send(client, 0, update_msg, crm_ipc_server_event | crm_ipc_server_error);
 
         if (rc <= 0) {
             crm_warn("%s notification of client %s.%.6s failed: %s (%d)",
                      type, crm_client_name(client), client->id, pcmk_strerror(rc), rc);
         } else {
             crm_trace("Sent %s notification to client %s.%.6s", type, crm_client_name(client),
                       client->id);
         }
     }
 }
 
 void
 do_stonith_async_timeout_update(const char *client_id, const char *call_id, int timeout)
 {
     crm_client_t *client = NULL;
     xmlNode *notify_data = NULL;
 
     if (!timeout || !call_id || !client_id) {
         return;
     }
 
     client = crm_client_get_by_id(client_id);
     if (!client) {
         return;
     }
 
     notify_data = create_xml_node(NULL, T_STONITH_TIMEOUT_VALUE);
     crm_xml_add(notify_data, F_TYPE, T_STONITH_TIMEOUT_VALUE);
     crm_xml_add(notify_data, F_STONITH_CALLID, call_id);
     crm_xml_add_int(notify_data, F_STONITH_TIMEOUT, timeout);
 
     crm_trace("timeout update is %d for client %s and call id %s", timeout, client_id, call_id);
 
     if (client) {
         crm_ipcs_send(client, 0, notify_data, crm_ipc_server_event);
     }
 
     free_xml(notify_data);
 }
 
 void
 do_stonith_notify(int options, const char *type, int result, xmlNode * data)
 {
     /* TODO: Standardize the contents of data */
     xmlNode *update_msg = create_xml_node(NULL, "notify");
 
     CRM_CHECK(type != NULL,;);
 
     crm_xml_add(update_msg, F_TYPE, T_STONITH_NOTIFY);
     crm_xml_add(update_msg, F_SUBTYPE, type);
     crm_xml_add(update_msg, F_STONITH_OPERATION, type);
     crm_xml_add_int(update_msg, F_STONITH_RC, result);
 
     if (data != NULL) {
         add_message_xml(update_msg, F_STONITH_CALLDATA, data);
     }
 
     crm_trace("Notifying clients");
     g_hash_table_foreach(client_connections, stonith_notify_client, update_msg);
     free_xml(update_msg);
     crm_trace("Notify complete");
 }
 
 static stonith_key_value_t *
 parse_device_list(const char *devices)
 {
     int lpc = 0;
     int max = 0;
     int last = 0;
     stonith_key_value_t *output = NULL;
 
     if (devices == NULL) {
         return output;
     }
 
     max = strlen(devices);
     for (lpc = 0; lpc <= max; lpc++) {
         if (devices[lpc] == ',' || devices[lpc] == 0) {
             char *line = NULL;
 
             line = calloc(1, 2 + lpc - last);
             snprintf(line, 1 + lpc - last, "%s", devices + last);
             output = stonith_key_value_add(output, NULL, line);
             free(line);
 
             last = lpc + 1;
         }
     }
 
     return output;
 }
 
 static void
 topology_remove_helper(const char *node, int level)
 {
     int rc;
     char *desc = NULL;
     xmlNode *data = create_xml_node(NULL, F_STONITH_LEVEL);
     xmlNode *notify_data = create_xml_node(NULL, STONITH_OP_LEVEL_DEL);
 
     crm_xml_add(data, F_STONITH_ORIGIN, __FUNCTION__);
     crm_xml_add_int(data, XML_ATTR_ID, level);
     crm_xml_add(data, F_STONITH_TARGET, node);
 
     rc = stonith_level_remove(data, &desc);
 
     crm_xml_add(notify_data, F_STONITH_DEVICE, desc);
     crm_xml_add_int(notify_data, F_STONITH_ACTIVE, g_hash_table_size(topology));
 
     do_stonith_notify(0, STONITH_OP_LEVEL_DEL, rc, notify_data);
 
     free_xml(notify_data);
     free_xml(data);
     free(desc);
 }
 
 static void
 topology_register_helper(const char *node, int level, stonith_key_value_t * device_list)
 {
     int rc;
     char *desc = NULL;
     xmlNode *notify_data = create_xml_node(NULL, STONITH_OP_LEVEL_ADD);
     xmlNode *data = create_level_registration_xml(node, level, device_list);
 
     rc = stonith_level_register(data, &desc);
 
     crm_xml_add(notify_data, F_STONITH_DEVICE, desc);
     crm_xml_add_int(notify_data, F_STONITH_ACTIVE, g_hash_table_size(topology));
 
     do_stonith_notify(0, STONITH_OP_LEVEL_ADD, rc, notify_data);
 
     free_xml(notify_data);
     free_xml(data);
     free(desc);
 }
 
 static void
 remove_cib_device(xmlXPathObjectPtr xpathObj)
 {
     int max = numXpathResults(xpathObj), lpc = 0;
 
     for (lpc = 0; lpc < max; lpc++) {
         const char *rsc_id = NULL;
         const char *standard = NULL;
         xmlNode *match = getXpathResult(xpathObj, lpc);
 
         CRM_LOG_ASSERT(match != NULL);
         if(match != NULL) {
             standard = crm_element_value(match, XML_AGENT_ATTR_CLASS);
         }
 
         if (safe_str_neq(standard, "stonith")) {
             continue;
         }
 
         rsc_id = crm_element_value(match, XML_ATTR_ID);
 
         stonith_device_remove(rsc_id, TRUE);
     }
 }
 
 static void
 handle_topology_change(xmlNode *match, bool remove) 
 {
     CRM_LOG_ASSERT(match != NULL);
     if(match) {
         int index = 0;
         const char *target;
         const char *dev_list;
         stonith_key_value_t *devices = NULL;
 
         crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index);
         target = crm_element_value(match, XML_ATTR_STONITH_TARGET);
         dev_list = crm_element_value(match, XML_ATTR_STONITH_DEVICES);
         devices = parse_device_list(dev_list);
 
         crm_trace("Updating %s[%d] (%s) to %s", target, index, ID(match), dev_list);
 
         if(remove) {
             topology_remove_helper(target, index);
         }
         topology_register_helper(target, index, devices);
         stonith_key_value_freeall(devices, 1, 1);
     }
 }
 
 static void
 remove_fencing_topology(xmlXPathObjectPtr xpathObj)
 {
     int max = numXpathResults(xpathObj), lpc = 0;
 
     for (lpc = 0; lpc < max; lpc++) {
         xmlNode *match = getXpathResult(xpathObj, lpc);
 
         CRM_LOG_ASSERT(match != NULL);
         if (match && crm_element_value(match, XML_DIFF_MARKER)) {
             /* Deletion */
             int index = 0;
             const char *target = crm_element_value(match, XML_ATTR_STONITH_TARGET);
 
             crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index);
             if (target == NULL) {
                 crm_err("Invalid fencing target in element %s", ID(match));
 
             } else if (index <= 0) {
                 crm_err("Invalid level for %s in element %s", target, ID(match));
 
             } else {
                 topology_remove_helper(target, index);
             }
             /* } else { Deal with modifications during the 'addition' stage */
         }
     }
 }
 
 static void
 register_fencing_topology(xmlXPathObjectPtr xpathObj, gboolean force)
 {
     int max = numXpathResults(xpathObj), lpc = 0;
 
     for (lpc = 0; lpc < max; lpc++) {
         xmlNode *match = getXpathResult(xpathObj, lpc);
 
         handle_topology_change(match, TRUE);
     }
 }
 
 /* Fencing
 <diff crm_feature_set="3.0.6">
   <diff-removed>
     <fencing-topology>
       <fencing-level id="f-p1.1" target="pcmk-1" index="1" devices="poison-pill" __crm_diff_marker__="removed:top"/>
       <fencing-level id="f-p1.2" target="pcmk-1" index="2" devices="power" __crm_diff_marker__="removed:top"/>
       <fencing-level devices="disk,network" id="f-p2.1"/>
     </fencing-topology>
   </diff-removed>
   <diff-added>
     <fencing-topology>
       <fencing-level id="f-p.1" target="pcmk-1" index="1" devices="poison-pill" __crm_diff_marker__="added:top"/>
       <fencing-level id="f-p2.1" target="pcmk-2" index="1" devices="disk,something"/>
       <fencing-level id="f-p3.1" target="pcmk-2" index="2" devices="power" __crm_diff_marker__="added:top"/>
     </fencing-topology>
   </diff-added>
 </diff>
 */
 
 static void
 fencing_topology_init(xmlNode * msg)
 {
     xmlXPathObjectPtr xpathObj = NULL;
     const char *xpath = "//" XML_TAG_FENCING_LEVEL;
 
     crm_trace("Full topology refresh");
 
     if(topology) {
         g_hash_table_destroy(topology);
         topology = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_topology_entry);
     }
 
     /* Grab everything */
     xpathObj = xpath_search(local_cib, xpath);
     register_fencing_topology(xpathObj, TRUE);
 
     freeXpathObject(xpathObj);
 }
 
 #define rsc_name(x) x->clone_name?x->clone_name:x->id
 
 static void cib_device_update(resource_t *rsc, pe_working_set_t *data_set)
 {
     node_t *node = NULL;
     const char *value = NULL;
     const char *rclass = NULL;
     node_t *parent = NULL;
     gboolean remove = TRUE;
 
     /* TODO: Mark each installed device and remove if untouched when this process finishes */
     if(rsc->children) {
         GListPtr gIter = NULL;
         for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
             cib_device_update(gIter->data, data_set);
             if(rsc->variant == pe_clone || rsc->variant == pe_master) {
                 crm_trace("Only processing one copy of the clone %s", rsc->id);
                 break;
             }
         }
         return;
     }
 
     rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
     if(safe_str_neq(rclass, "stonith")) {
         return;
     }
 
     value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
     if(value && strcmp(RSC_STOPPED, value) == 0) {
         crm_info("Device %s has been disabled", rsc->id);
         goto update_done;
 
     } else if(stonith_our_uname) {
         GHashTableIter iter;
 
         g_hash_table_iter_init(&iter, rsc->allowed_nodes);
         while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
             if(node && strcmp(node->details->uname, stonith_our_uname) == 0) {
                 break;
             }
             node = NULL;
         }
     }
 
     if (rsc->parent && rsc->parent->variant == pe_group && stonith_our_uname) {
         GHashTableIter iter;
 
         g_hash_table_iter_init(&iter, rsc->parent->allowed_nodes);
         while (g_hash_table_iter_next(&iter, NULL, (void **)&parent)) {
             if(parent && strcmp(parent->details->uname, stonith_our_uname) == 0) {
                 break;
             }
             parent = NULL;
         }
     }
 
     if(node == NULL) {
         GHashTableIter iter;
 
         crm_info("Device %s has been disabled on %s: unknown", rsc->id, stonith_our_uname);
         g_hash_table_iter_init(&iter, rsc->allowed_nodes);
         while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
             crm_trace("Available: %s = %d", node->details->uname, node->weight);
         }
 
         goto update_done;
 
     } else if(node->weight < 0 || (parent && parent->weight < 0)) {
         char *score = score2char((node->weight < 0) ? node->weight : parent->weight);
 
         crm_info("Device %s has been disabled on %s: score=%s", rsc->id, stonith_our_uname, score);
         free(score);
 
         goto update_done;
 
     } else {
         xmlNode *data;
         GHashTableIter gIter;
         stonith_key_value_t *params = NULL;
 
         const char *name = NULL;
         const char *agent = crm_element_value(rsc->xml, XML_EXPR_ATTR_TYPE);
         const char *provider = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
         const char *rsc_provides = NULL;
 
         crm_debug("Device %s is allowed on %s: score=%d", rsc->id, stonith_our_uname, node->weight);
         get_rsc_attributes(rsc->parameters, rsc, node, data_set);
         get_meta_attributes(rsc->meta, rsc, node, data_set);
 
         rsc_provides = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_PROVIDES);
 
         g_hash_table_iter_init(&gIter, rsc->parameters);
         while (g_hash_table_iter_next(&gIter, (gpointer *) & name, (gpointer *) & value)) {
             if (!name || !value) {
                 continue;
             }
             params = stonith_key_value_add(params, name, value);
             crm_trace(" %s=%s", name, value);
         }
 
         remove = FALSE;
         data = create_device_registration_xml(rsc_name(rsc), provider, agent, params, rsc_provides);
         stonith_device_register(data, NULL, TRUE);
 
         stonith_key_value_freeall(params, 1, 1);
         free_xml(data);
     }
 
 update_done:
 
     if(remove && g_hash_table_lookup(device_list, rsc_name(rsc))) {
         stonith_device_remove(rsc_name(rsc), TRUE);
     }
 }
 
 extern xmlNode *do_calculations(pe_working_set_t * data_set, xmlNode * xml_input, crm_time_t * now);
 extern node_t *create_node(const char *id, const char *uname, const char *type, const char *score, pe_working_set_t * data_set);
 
 static void
 cib_devices_update(void)
 {
     GListPtr gIter = NULL;
     pe_working_set_t data_set;
 
     crm_info("Updating devices to version %s.%s.%s",
              crm_element_value(local_cib, XML_ATTR_GENERATION_ADMIN),
              crm_element_value(local_cib, XML_ATTR_GENERATION),
              crm_element_value(local_cib, XML_ATTR_NUMUPDATES));
 
     set_working_set_defaults(&data_set);
     data_set.input = local_cib;
     data_set.now = crm_time_new(NULL);
     data_set.flags |= pe_flag_quick_location;
     data_set.localhost = stonith_our_uname;
 
     cluster_status(&data_set);
     do_calculations(&data_set, NULL, NULL);
 
     for (gIter = data_set.resources; gIter != NULL; gIter = gIter->next) {
         cib_device_update(gIter->data, &data_set);
     }
     data_set.input = NULL; /* Wasn't a copy */
     cleanup_alloc_calculations(&data_set);
 }
 
 static void
 update_cib_stonith_devices_v2(const char *event, xmlNode * msg)
 {
     xmlNode *change = NULL;
     char *reason = NULL;
     bool needs_update = FALSE;
     xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
 
     for (change = __xml_first_child(patchset); change != NULL; change = __xml_next(change)) {
         const char *op = crm_element_value(change, XML_DIFF_OP);
         const char *xpath = crm_element_value(change, XML_DIFF_PATH);
         const char *shortpath = NULL;
 
         if(op == NULL || strcmp(op, "move") == 0) {
             continue;
 
         } else if(safe_str_eq(op, "delete") && strstr(xpath, XML_CIB_TAG_RESOURCE)) {
             const char *rsc_id = NULL;
             char *search = NULL;
             char *mutable = strdup(xpath);
 
             rsc_id = strstr(mutable, "primitive[@id=\'") + strlen("primitive[@id=\'");
             search = strchr(rsc_id, '\'');
             search[0] = 0;
 
             stonith_device_remove(rsc_id, TRUE);
             free(mutable);
 
         } else if(strstr(xpath, "/"XML_CIB_TAG_RESOURCES)) {
             shortpath = strrchr(xpath, '/'); CRM_ASSERT(shortpath);
             reason = g_strdup_printf("%s %s", op, shortpath+1);
             needs_update = TRUE;
             break;
 
         } else if(strstr(xpath, XML_CONS_TAG_RSC_LOCATION)) {
             shortpath = strrchr(xpath, '/'); CRM_ASSERT(shortpath);
             reason = g_strdup_printf("%s %s", op, shortpath+1);
             needs_update = TRUE;
             break;
         }
     }
 
     if(needs_update) {
         crm_info("Updating device list from the cib: %s", reason);
         cib_devices_update();
     }
     free(reason);
 }
 
 
 static void
 update_cib_stonith_devices_v1(const char *event, xmlNode * msg)
 {
     const char *reason = "none";
     gboolean needs_update = FALSE;
     xmlXPathObjectPtr xpath_obj = NULL;
 
     /* process new constraints */
     xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_CONS_TAG_RSC_LOCATION);
     if (numXpathResults(xpath_obj) > 0) {
         int max = numXpathResults(xpath_obj), lpc = 0;
 
         /* Safest and simplest to always recompute */
         needs_update = TRUE;
         reason = "new location constraint";
 
         for (lpc = 0; lpc < max; lpc++) {
             xmlNode *match = getXpathResult(xpath_obj, lpc);
 
             crm_log_xml_trace(match, "new constraint");
         }
     }
     freeXpathObject(xpath_obj);
 
     /* process deletions */
     xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_CIB_TAG_RESOURCE);
     if (numXpathResults(xpath_obj) > 0) {
         remove_cib_device(xpath_obj);
     }
     freeXpathObject(xpath_obj);
 
     /* process additions */
     xpath_obj = xpath_search(msg, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_CIB_TAG_RESOURCE);
     if (numXpathResults(xpath_obj) > 0) {
         int max = numXpathResults(xpath_obj), lpc = 0;
 
         for (lpc = 0; lpc < max; lpc++) {
             const char *rsc_id = NULL;
             const char *standard = NULL;
             xmlNode *match = getXpathResult(xpath_obj, lpc);
 
             rsc_id = crm_element_value(match, XML_ATTR_ID);
             standard = crm_element_value(match, XML_AGENT_ATTR_CLASS);
 
             if (safe_str_neq(standard, "stonith")) {
                 continue;
             }
 
             crm_trace("Fencing resource %s was added or modified", rsc_id);
             reason = "new resource";
             needs_update = TRUE;
         }
     }
     freeXpathObject(xpath_obj);
 
     if(needs_update) {
         crm_info("Updating device list from the cib: %s", reason);
         cib_devices_update();
     }
 }
 
 static void
 update_cib_stonith_devices(const char *event, xmlNode * msg)
 {
     int format = 1;
     xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
 
     CRM_ASSERT(patchset);
     crm_element_value_int(patchset, "format", &format);
     switch(format) {
         case 1:
             update_cib_stonith_devices_v1(event, msg);
             break;
         case 2:
             update_cib_stonith_devices_v2(event, msg);
             break;
         default:
             crm_warn("Unknown patch format: %d", format);
     }
 }
 
 static void
 update_fencing_topology(const char *event, xmlNode * msg)
 {
     int format = 1;
     const char *xpath;
     xmlXPathObjectPtr xpathObj = NULL;
     xmlNode *patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
 
     CRM_ASSERT(patchset);
     crm_element_value_int(patchset, "format", &format);
 
     if(format == 1) {
         /* Process deletions (only) */
         xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_TAG_FENCING_LEVEL;
         xpathObj = xpath_search(msg, xpath);
 
         remove_fencing_topology(xpathObj);
         freeXpathObject(xpathObj);
 
         /* Process additions and changes */
         xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_TAG_FENCING_LEVEL;
         xpathObj = xpath_search(msg, xpath);
 
         register_fencing_topology(xpathObj, FALSE);
         freeXpathObject(xpathObj);
 
     } else if(format == 2) {
         xmlNode *change = NULL;
 
         for (change = __xml_first_child(patchset); change != NULL; change = __xml_next(change)) {
             const char *op = crm_element_value(change, XML_DIFF_OP);
             const char *xpath = crm_element_value(change, XML_DIFF_PATH);
             xmlNode *f_topology = get_message_xml(change, XML_TAG_FENCING_TOPOLOGY);
 
             if(op == NULL) {
                 continue;
             } else if (strstr(xpath, "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION) && f_topology != NULL) {
                 if(strcmp(op, "delete") == 0 || strcmp(op, "create") == 0) {
                     crm_info("Re-initializing fencing topology after top-level %s operation", op);
                     fencing_topology_init(NULL);
                 }
                 return;
             } else if (strstr(xpath, "/" XML_TAG_FENCING_TOPOLOGY "/") == NULL) {
                 continue;
             } else if(strstr(xpath, "/" XML_TAG_FENCING_LEVEL "/") == NULL) {
                 if(strcmp(op, "delete") == 0 || strcmp(op, "create") == 0) {
                     crm_info("Re-initializing fencing topology after top-level %s operation", op);
                     fencing_topology_init(NULL);
                 }
                 return;
             }
 
             crm_trace("Handling %s operation for %s", op, xpath);
             if(strcmp(op, "move") == 0) {
                 continue;
 
             } else if(strcmp(op, "create") == 0) {
                 handle_topology_change(change->children, FALSE);
 
             } else if(strcmp(op, "modify") == 0) {
                 xmlNode *match = first_named_child(change, XML_DIFF_RESULT);
 
                 if(match) {
                     handle_topology_change(match->children, TRUE);
                 }
 
             } else if(strcmp(op, "delete") == 0) {
                 /* Nuclear option, all we have is the path and an id... not enough to remove a specific entry */
                 crm_info("Re-initializing fencing topology after %s operation", op);
                 fencing_topology_init(NULL);
                 return;
             }
         }
 
     } else {
         crm_warn("Unknown patch format: %d", format);
     }
 }
 static bool have_cib_devices = FALSE;
 
 static void
 update_cib_cache_cb(const char *event, xmlNode * msg)
 {
     int rc = pcmk_ok;
     xmlNode *stonith_enabled_xml = NULL;
     xmlNode *stonith_watchdog_xml = NULL;
     const char *stonith_enabled_s = NULL;
     static gboolean stonith_enabled_saved = TRUE;
 
     if(!have_cib_devices) {
         crm_trace("Skipping updates until we get a full dump");
         return;
 
     } else if(msg == NULL) {
         crm_trace("Missing %s update", event);
         return;
     }
 
     /* Maintain a local copy of the CIB so that we have full access to the device definitions and location constraints */
     if (local_cib != NULL) {
         int rc = pcmk_ok;
         xmlNode *patchset = NULL;
 
         crm_element_value_int(msg, F_CIB_RC, &rc);
         if (rc != pcmk_ok) {
             return;
         }
 
         patchset = get_message_xml(msg, F_CIB_UPDATE_RESULT);
         xml_log_patchset(LOG_TRACE, "Config update", patchset);
         rc = xml_apply_patchset(local_cib, patchset, TRUE);
         switch (rc) {
             case pcmk_ok:
             case -pcmk_err_old_data:
                 break;
             case -pcmk_err_diff_resync:
             case -pcmk_err_diff_failed:
                 crm_notice("[%s] Patch aborted: %s (%d)", event, pcmk_strerror(rc), rc);
                 free_xml(local_cib);
                 local_cib = NULL;
                 break;
             default:
                 crm_warn("[%s] ABORTED: %s (%d)", event, pcmk_strerror(rc), rc);
                 free_xml(local_cib);
                 local_cib = NULL;
         }
     }
 
     if (local_cib == NULL) {
         crm_trace("Re-requesting the full cib");
         rc = cib_api->cmds->query(cib_api, NULL, &local_cib, cib_scope_local | cib_sync_call);
         if(rc != pcmk_ok) {
             crm_err("Couldnt retrieve the CIB: %s (%d)", pcmk_strerror(rc), rc);
             return;
         }
         CRM_ASSERT(local_cib != NULL);
         stonith_enabled_saved = FALSE; /* Trigger a full refresh below */
     }
 
     stonith_enabled_xml = get_xpath_object("//nvpair[@name='stonith-enabled']", local_cib, LOG_TRACE);
     if (stonith_enabled_xml) {
         stonith_enabled_s = crm_element_value(stonith_enabled_xml, XML_NVPAIR_ATTR_VALUE);
     }
 
-    if(daemon_option("watchdog")) {
+    if(daemon_option_enabled(crm_system_name, "watchdog")) {
         stonith_watchdog_xml = get_xpath_object("//nvpair[@name='stonith-watchdog-timeout']", local_cib, LOG_TRACE);
     }
 
     if (stonith_watchdog_xml) {
         const char *value = crm_element_value(stonith_watchdog_xml, XML_NVPAIR_ATTR_VALUE);
         stonith_watchdog_timeout_ms = crm_get_msec(value);
     } else {
         stonith_watchdog_timeout_ms = 0;
     }
 
     if (stonith_enabled_s && crm_is_true(stonith_enabled_s) == FALSE) {
         crm_trace("Ignoring cib updates while stonith is disabled");
         stonith_enabled_saved = FALSE;
         return;
 
     } else if (stonith_enabled_saved == FALSE) {
         crm_info("Updating stonith device and topology lists now that stonith is enabled");
         stonith_enabled_saved = TRUE;
         fencing_topology_init(NULL);
         cib_devices_update();
 
     } else {
         update_fencing_topology(event, msg);
         update_cib_stonith_devices(event, msg);
     }
 }
 
 static void
 init_cib_cache_cb(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
 {
     crm_info("Updating device list from the cib: init");
     have_cib_devices = TRUE;
     local_cib = copy_xml(output);
 
     fencing_topology_init(msg);
     cib_devices_update();
 }
 
 static void
 stonith_shutdown(int nsig)
 {
     stonith_shutdown_flag = TRUE;
     crm_info("Terminating with  %d clients", crm_hash_table_size(client_connections));
     if (mainloop != NULL && g_main_is_running(mainloop)) {
         g_main_quit(mainloop);
     } else {
         stonith_cleanup();
         crm_exit(pcmk_ok);
     }
 }
 
 static void
 cib_connection_destroy(gpointer user_data)
 {
     if (stonith_shutdown_flag) {
         crm_info("Connection to the CIB closed.");
         return;
     } else {
         crm_notice("Connection to the CIB terminated. Shutting down.");
     }
     if (cib_api) {
         cib_api->cmds->signoff(cib_api);
     }
     stonith_shutdown(0);
 }
 
 static void
 stonith_cleanup(void)
 {
     if (cib_api) {
         cib_api->cmds->signoff(cib_api);
     }
 
     if (ipcs) {
         qb_ipcs_destroy(ipcs);
     }
     crm_peer_destroy();
     crm_client_cleanup();
     free(stonith_our_uname);
     free_xml(local_cib);
 }
 
 /* *INDENT-OFF* */
 static struct crm_option long_options[] = {
     {"stand-alone",         0, 0, 's'},
     {"stand-alone-w-cpg",   0, 0, 'c'},
     {"verbose",     0, 0, 'V'},
     {"version",     0, 0, '$'},
     {"help",        0, 0, '?'},
 
     {0, 0, 0, 0}
 };
 /* *INDENT-ON* */
 
 static void
 setup_cib(void)
 {
     int rc, retries = 0;
     static cib_t *(*cib_new_fn) (void) = NULL;
 
     if (cib_new_fn == NULL) {
         cib_new_fn = find_library_function(&cib_library, CIB_LIBRARY, "cib_new", TRUE);
     }
 
     if (cib_new_fn != NULL) {
         cib_api = (*cib_new_fn) ();
     }
 
     if (cib_api == NULL) {
         crm_err("No connection to the CIB");
         return;
     }
 
     do {
         sleep(retries);
         rc = cib_api->cmds->signon(cib_api, CRM_SYSTEM_CRMD, cib_command);
     } while (rc == -ENOTCONN && ++retries < 5);
 
     if (rc != pcmk_ok) {
         crm_err("Could not connect to the CIB service: %s (%d)", pcmk_strerror(rc), rc);
 
     } else if (pcmk_ok !=
                cib_api->cmds->add_notify_callback(cib_api, T_CIB_DIFF_NOTIFY, update_cib_cache_cb)) {
         crm_err("Could not set CIB notification callback");
 
     } else {
         rc = cib_api->cmds->query(cib_api, NULL, NULL, cib_scope_local);
         cib_api->cmds->register_callback(cib_api, rc, 120, FALSE, NULL, "init_cib_cache_cb",
                                          init_cib_cache_cb);
         cib_api->cmds->set_connection_dnotify(cib_api, cib_connection_destroy);
         crm_notice("Watching for stonith topology changes");
     }
 }
 
 struct qb_ipcs_service_handlers ipc_callbacks = {
     .connection_accept = st_ipc_accept,
     .connection_created = st_ipc_created,
     .msg_process = st_ipc_dispatch,
     .connection_closed = st_ipc_closed,
     .connection_destroyed = st_ipc_destroy
 };
 
 static void
 st_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void *data)
 {
     /*
      * This is a hack until we can send to a nodeid and/or we fix node name lookups
      * These messages are ignored in stonith_peer_callback()
      */
     xmlNode *query = create_xml_node(NULL, "stonith_command");
 
     crm_xml_add(query, F_XML_TAGNAME, "stonith_command");
     crm_xml_add(query, F_TYPE, T_STONITH_NG);
     crm_xml_add(query, F_STONITH_OPERATION, "poke");
 
     crm_debug("Broadcasting our uname because of node %u", node->id);
     send_cluster_message(NULL, crm_msg_stonith_ng, query, FALSE);
 
     free_xml(query);
 }
 
 int
 main(int argc, char **argv)
 {
     int flag;
     int rc = 0;
     int lpc = 0;
     int argerr = 0;
     int option_index = 0;
     crm_cluster_t cluster;
     const char *actions[] = { "reboot", "off", "list", "monitor", "status" };
 
     crm_log_preinit("stonith-ng", argc, argv);
     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':
                 crm_bump_log_level(argc, argv);
                 break;
             case 's':
                 stand_alone = TRUE;
                 break;
             case 'c':
                 stand_alone = FALSE;
                 no_cib_connect = TRUE;
                 break;
             case '$':
             case '?':
                 crm_help(flag, EX_OK);
                 break;
             default:
                 ++argerr;
                 break;
         }
     }
 
     if (argc - optind == 1 && safe_str_eq("metadata", argv[optind])) {
         printf("<?xml version=\"1.0\"?><!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n");
         printf("<resource-agent name=\"stonithd\">\n");
         printf(" <version>1.0</version>\n");
         printf
             (" <longdesc lang=\"en\">This is a fake resource that details the instance attributes handled by stonithd.</longdesc>\n");
         printf(" <shortdesc lang=\"en\">Options available for all stonith resources</shortdesc>\n");
         printf(" <parameters>\n");
 
         printf("  <parameter name=\"stonith-timeout\" unique=\"0\">\n");
         printf
             ("    <shortdesc lang=\"en\">How long to wait for the STONITH action to complete per a stonith device.</shortdesc>\n");
         printf
             ("    <longdesc lang=\"en\">Overrides the stonith-timeout cluster property</longdesc>\n");
         printf("    <content type=\"time\" default=\"60s\"/>\n");
         printf("  </parameter>\n");
 
         printf("  <parameter name=\"priority\" unique=\"0\">\n");
         printf
             ("    <shortdesc lang=\"en\">The priority of the stonith resource. Devices are tried in order of highest priority to lowest.</shortdesc>\n");
         printf("    <content type=\"integer\" default=\"0\"/>\n");
         printf("  </parameter>\n");
 
         printf("  <parameter name=\"%s\" unique=\"0\">\n", STONITH_ATTR_HOSTARG);
         printf
             ("    <shortdesc lang=\"en\">Advanced use only: An alternate parameter to supply instead of 'port'</shortdesc>\n");
         printf
             ("    <longdesc lang=\"en\">Some devices do not support the standard 'port' parameter or may provide additional ones.\n"
              "Use this to specify an alternate, device-specific, parameter that should indicate the machine to be fenced.\n"
              "A value of 'none' can be used to tell the cluster not to supply any additional parameters.\n"
              "     </longdesc>\n");
         printf("    <content type=\"string\" default=\"port\"/>\n");
         printf("  </parameter>\n");
 
         printf("  <parameter name=\"%s\" unique=\"0\">\n", STONITH_ATTR_HOSTMAP);
         printf
             ("    <shortdesc lang=\"en\">A mapping of host names to ports numbers for devices that do not support host names.</shortdesc>\n");
         printf
             ("    <longdesc lang=\"en\">Eg. node1:1;node2:2,3 would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2</longdesc>\n");
         printf("    <content type=\"string\" default=\"\"/>\n");
         printf("  </parameter>\n");
 
         printf("  <parameter name=\"%s\" unique=\"0\">\n", STONITH_ATTR_HOSTLIST);
         printf
             ("    <shortdesc lang=\"en\">A list of machines controlled by this device (Optional unless %s=static-list).</shortdesc>\n",
              STONITH_ATTR_HOSTCHECK);
         printf("    <content type=\"string\" default=\"\"/>\n");
         printf("  </parameter>\n");
 
         printf("  <parameter name=\"%s\" unique=\"0\">\n", STONITH_ATTR_HOSTCHECK);
         printf
             ("    <shortdesc lang=\"en\">How to determine which machines are controlled by the device.</shortdesc>\n");
         printf
             ("    <longdesc lang=\"en\">Allowed values: dynamic-list (query the device), static-list (check the %s attribute), none (assume every device can fence every machine)</longdesc>\n",
              STONITH_ATTR_HOSTLIST);
         printf("    <content type=\"string\" default=\"dynamic-list\"/>\n");
         printf("  </parameter>\n");
 
         for (lpc = 0; lpc < DIMOF(actions); lpc++) {
             printf("  <parameter name=\"pcmk_%s_action\" unique=\"0\">\n", actions[lpc]);
             printf
                 ("    <shortdesc lang=\"en\">Advanced use only: An alternate command to run instead of '%s'</shortdesc>\n",
                  actions[lpc]);
             printf
                 ("    <longdesc lang=\"en\">Some devices do not support the standard commands or may provide additional ones.\n"
                  "Use this to specify an alternate, device-specific, command that implements the '%s' action.</longdesc>\n",
                  actions[lpc]);
             printf("    <content type=\"string\" default=\"%s\"/>\n", actions[lpc]);
             printf("  </parameter>\n");
 
             printf("  <parameter name=\"pcmk_%s_timeout\" unique=\"0\">\n", actions[lpc]);
             printf
                 ("    <shortdesc lang=\"en\">Advanced use only: Specify an alternate timeout to use for %s actions instead of stonith-timeout</shortdesc>\n",
                  actions[lpc]);
             printf
                 ("    <longdesc lang=\"en\">Some devices need much more/less time to complete than normal.\n"
                  "Use this to specify an alternate, device-specific, timeout for '%s' actions.</longdesc>\n",
                  actions[lpc]);
             printf("    <content type=\"time\" default=\"60s\"/>\n");
             printf("  </parameter>\n");
 
             printf("  <parameter name=\"pcmk_%s_retries\" unique=\"0\">\n", actions[lpc]);
             printf
                 ("    <shortdesc lang=\"en\">Advanced use only: The maximum number of times to retry the '%s' command within the timeout period</shortdesc>\n",
                  actions[lpc]);
             printf("    <longdesc lang=\"en\">Some devices do not support multiple connections."
                    " Operations may 'fail' if the device is busy with another task so Pacemaker will automatically retry the operation, if there is time remaining."
                    " Use this option to alter the number of times Pacemaker retries '%s' actions before giving up."
                    "</longdesc>\n", actions[lpc]);
             printf("    <content type=\"integer\" default=\"2\"/>\n");
             printf("  </parameter>\n");
         }
 
         printf(" </parameters>\n");
         printf("</resource-agent>\n");
         return 0;
     }
 
     if (optind != argc) {
         ++argerr;
     }
 
     if (argerr) {
         crm_help('?', EX_USAGE);
     }
 
     crm_log_init("stonith-ng", LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
     mainloop_add_signal(SIGTERM, stonith_shutdown);
 
     crm_peer_init();
 
     if (stand_alone == FALSE) {
 #if SUPPORT_HEARTBEAT
         cluster.hb_conn = NULL;
         cluster.hb_dispatch = stonith_peer_hb_callback;
         cluster.destroy = stonith_peer_hb_destroy;
 #endif
 
         if (is_openais_cluster()) {
 #if SUPPORT_COROSYNC
             cluster.destroy = stonith_peer_cs_destroy;
             cluster.cpg.cpg_deliver_fn = stonith_peer_ais_callback;
             cluster.cpg.cpg_confchg_fn = pcmk_cpg_membership;
 #endif
         }
 
         if (crm_cluster_connect(&cluster) == FALSE) {
             crm_crit("Cannot sign in to the cluster... terminating");
             crm_exit(DAEMON_RESPAWN_STOP);
         }
         stonith_our_uname = cluster.uname;
         stonith_our_uuid = cluster.uuid;
 
         if (no_cib_connect == FALSE) {
             setup_cib();
         }
 
     } else {
         stonith_our_uname = strdup("localhost");
     }
 
     crm_set_status_callback(&st_peer_update_callback);
 
     device_list = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_device);
 
     topology = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_topology_entry);
 
-    if(daemon_option("watchdog")) {
+    if(daemon_option_enabled(crm_system_name, "watchdog")) {
         xmlNode *xml;
         stonith_key_value_t *params = NULL;
 
         stonith_key_value_add(params, STONITH_ATTR_HOSTLIST, stonith_our_uname);
         xml = create_device_registration_xml("watchdog", "internal", STONITH_WATCHDOG_AGENT, params, NULL);
         stonith_device_register(xml, NULL, FALSE);
 
         stonith_key_value_freeall(params, 1, 1);
         free_xml(xml);
     }
 
     stonith_ipc_server_init(&ipcs, &ipc_callbacks);
 
 #if SUPPORT_STONITH_CONFIG
     if (((stand_alone == TRUE)) && !(standalone_cfg_read_file(STONITH_NG_CONF_FILE))) {
         standalone_cfg_commit();
     }
 #endif
 
     /* Create the mainloop and run it... */
     mainloop = g_main_new(FALSE);
     crm_info("Starting %s mainloop", crm_system_name);
 
     g_main_run(mainloop);
     stonith_cleanup();
 
 #if SUPPORT_HEARTBEAT
     if (cluster.hb_conn) {
         cluster.hb_conn->llc_ops->delete(cluster.hb_conn);
     }
 #endif
 
     crm_info("Done");
 
     return crm_exit(rc);
 }
diff --git a/mcp/pacemaker.c b/mcp/pacemaker.c
index ba3c88f47e..c7852c3464 100644
--- a/mcp/pacemaker.c
+++ b/mcp/pacemaker.c
@@ -1,1087 +1,1091 @@
 /*
  * Copyright (C) 2010 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 <pacemaker.h>
 
 #include <pwd.h>
 #include <grp.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/reboot.h>
 
 #include <crm/msg_xml.h>
 #include <crm/common/ipcs.h>
 #include <crm/common/mainloop.h>
 #include <crm/cluster/internal.h>
 #include <crm/cluster.h>
 
 #include <dirent.h>
 #include <ctype.h>
 gboolean fatal_error = FALSE;
 GMainLoop *mainloop = NULL;
 
 #define PCMK_PROCESS_CHECK_INTERVAL 5
 
 const char *local_name = NULL;
 uint32_t local_nodeid = 0;
 crm_trigger_t *shutdown_trigger = NULL;
 const char *pid_file = "/var/run/pacemaker.pid";
 
 typedef struct pcmk_child_s {
     int pid;
     long flag;
     int start_seq;
     int respawn_count;
     gboolean respawn;
     const char *name;
     const char *uid;
     const char *command;
 
     gboolean active_before_startup;
 } pcmk_child_t;
 
 /* Index into the array below */
 #define pcmk_child_crmd  4
 #define pcmk_child_mgmtd 8
 /* *INDENT-OFF* */
 static pcmk_child_t pcmk_children[] = {
     { 0, crm_proc_none,       0, 0, FALSE, "none",       NULL,            NULL },
     { 0, crm_proc_plugin,     0, 0, FALSE, "ais",        NULL,            NULL },
     { 0, crm_proc_lrmd,       3, 0, TRUE,  "lrmd",       NULL,            CRM_DAEMON_DIR"/lrmd" },
     { 0, crm_proc_cib,        1, 0, TRUE,  "cib",        CRM_DAEMON_USER, CRM_DAEMON_DIR"/cib" },
     { 0, crm_proc_crmd,       6, 0, TRUE,  "crmd",       CRM_DAEMON_USER, CRM_DAEMON_DIR"/crmd" },
     { 0, crm_proc_attrd,      4, 0, TRUE,  "attrd",      CRM_DAEMON_USER, CRM_DAEMON_DIR"/attrd" },
     { 0, crm_proc_stonithd,   0, 0, TRUE,  "stonithd",   NULL,            NULL },
     { 0, crm_proc_pe,         5, 0, TRUE,  "pengine",    CRM_DAEMON_USER, CRM_DAEMON_DIR"/pengine" },
     { 0, crm_proc_mgmtd,      0, 0, TRUE,  "mgmtd",      NULL,            HB_DAEMON_DIR"/mgmtd" },
     { 0, crm_proc_stonith_ng, 2, 0, TRUE,  "stonith-ng", NULL,            CRM_DAEMON_DIR"/stonithd" },
 };
 /* *INDENT-ON* */
 
 static gboolean start_child(pcmk_child_t * child);
 static gboolean check_active_before_startup_processes(gpointer user_data);
 void update_process_clients(crm_client_t *client);
 void update_process_peers(void);
 
 void
 enable_crmd_as_root(gboolean enable)
 {
     if (enable) {
         pcmk_children[pcmk_child_crmd].uid = NULL;
     } else {
         pcmk_children[pcmk_child_crmd].uid = CRM_DAEMON_USER;
     }
 }
 
 void
 enable_mgmtd(gboolean enable)
 {
     if (enable) {
         pcmk_children[pcmk_child_mgmtd].start_seq = 7;
     } else {
         pcmk_children[pcmk_child_mgmtd].start_seq = 0;
     }
 }
 
 static uint32_t
 get_process_list(void)
 {
     int lpc = 0;
     uint32_t procs = 0;
 
     if(is_classic_ais_cluster()) {
         procs |= crm_proc_plugin;
     }
 
     for (lpc = 0; lpc < SIZEOF(pcmk_children); lpc++) {
         if (pcmk_children[lpc].pid != 0) {
             procs |= pcmk_children[lpc].flag;
         }
     }
     return procs;
 }
 
 static void
 pcmk_process_exit(pcmk_child_t * child)
 {
     child->pid = 0;
     child->active_before_startup = FALSE;
 
     /* Broadcast the fact that one of our processes died ASAP
      *
      * 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
      */
     update_node_processes(local_nodeid, NULL, get_process_list());
 
     child->respawn_count += 1;
     if (child->respawn_count > MAX_RESPAWN) {
         crm_err("Child respawn count exceeded by %s", child->name);
         child->respawn = FALSE;
     }
 
     if (shutdown_trigger) {
         mainloop_set_trigger(shutdown_trigger);
         update_node_processes(local_nodeid, NULL, get_process_list());
 
     } else if (child->respawn && crm_is_true(getenv("PCMK_fail_fast"))) {
         crm_err("Rebooting system because of %s", child->name);
         pcmk_panic(__FUNCTION__);
 
     } else if (child->respawn) {
         crm_notice("Respawning failed child process: %s", child->name);
         start_child(child);
     }
 }
 
 static void
 pcmk_child_exit(mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode)
 {
     pcmk_child_t *child = mainloop_child_userdata(p);
     const char *name = mainloop_child_name(p);
 
     if (signo && signo == SIGKILL) {
         crm_warn("The %s process (%d) terminated with signal %d (core=%d)", name, pid, signo, core);
 
     } else if (signo) {
         crm_err("The %s process (%d) terminated with signal %d (core=%d)", name, pid, signo, core);
 
     } else {
         switch(exitcode) {
             case pcmk_ok:
                 crm_info("The %s process (%d) exited: %s (%d)", name, pid, pcmk_strerror(exitcode), exitcode);
                 break;
 
             case DAEMON_RESPAWN_STOP:
                 crm_warn("The %s process (%d) can no longer be respawned, shutting the cluster down.", name, pid);
                 child->respawn = FALSE;
                 fatal_error = TRUE;
                 pcmk_shutdown(SIGTERM);
                 break;
 
             case pcmk_err_panic:
                 do_crm_log_always(LOG_EMERG, "The %s process (%d) instructed the machine to reset", name, pid);
                 child->respawn = FALSE;
                 fatal_error = TRUE;
                 pcmk_panic(__FUNCTION__);
                 pcmk_shutdown(SIGTERM);
                 break;
 
             default:
                 crm_err("The %s process (%d) exited: %s (%d)", name, pid, pcmk_strerror(exitcode), exitcode);
                 break;
         }
     }
 
     pcmk_process_exit(child);
 }
 
 static gboolean
 stop_child(pcmk_child_t * child, int signal)
 {
     if (signal == 0) {
         signal = SIGTERM;
     }
 
     if (child->command == NULL) {
         crm_debug("Nothing to do for child \"%s\"", child->name);
         return TRUE;
     }
 
     if (child->pid <= 0) {
         crm_trace("Client %s not running", child->name);
         return TRUE;
     }
 
     errno = 0;
     if (kill(child->pid, signal) == 0) {
         crm_notice("Stopping %s: Sent -%d to process %d", child->name, signal, child->pid);
 
     } else {
         crm_perror(LOG_ERR, "Stopping %s: Could not send -%d to process %d failed",
                    child->name, signal, child->pid);
     }
 
     return TRUE;
 }
 
 static char *opts_default[] = { NULL, NULL };
 static char *opts_vgrind[] = { NULL, NULL, NULL, NULL, NULL };
 
 static gboolean
 start_child(pcmk_child_t * child)
 {
     int lpc = 0;
     uid_t uid = 0;
     gid_t gid = 0;
     struct rlimit oflimits;
     gboolean use_valgrind = FALSE;
     gboolean use_callgrind = FALSE;
     const char *devnull = "/dev/null";
     const char *env_valgrind = getenv("PCMK_valgrind_enabled");
     const char *env_callgrind = getenv("PCMK_callgrind_enabled");
     enum cluster_type_e stack = get_cluster_type();
 
     child->active_before_startup = FALSE;
 
     if (child->command == NULL) {
         crm_info("Nothing to do for child \"%s\"", child->name);
         return TRUE;
     }
 
     if (env_callgrind != NULL && crm_is_true(env_callgrind)) {
         use_callgrind = TRUE;
         use_valgrind = TRUE;
 
     } else if (env_callgrind != NULL && strstr(env_callgrind, child->name)) {
         use_callgrind = TRUE;
         use_valgrind = TRUE;
 
     } else if (env_valgrind != NULL && crm_is_true(env_valgrind)) {
         use_valgrind = TRUE;
 
     } else if (env_valgrind != NULL && strstr(env_valgrind, child->name)) {
         use_valgrind = TRUE;
     }
 
     if (use_valgrind && strlen(VALGRIND_BIN) == 0) {
         crm_warn("Cannot enable valgrind for %s:"
                  " The location of the valgrind binary is unknown", child->name);
         use_valgrind = FALSE;
     }
 
     if (child->uid) {
         if (crm_user_lookup(child->uid, &uid, &gid) < 0) {
             crm_err("Invalid user (%s) for %s: not found", child->uid, child->name);
             return FALSE;
         }
         crm_info("Using uid=%u and group=%u for process %s", uid, gid, child->name);
     }
 
     child->pid = fork();
     CRM_ASSERT(child->pid != -1);
 
     if (child->pid > 0) {
         /* parent */
         mainloop_child_add(child->pid, 0, child->name, child, pcmk_child_exit);
 
         crm_info("Forked child %d for process %s%s", child->pid, child->name,
                  use_valgrind ? " (valgrind enabled: " VALGRIND_BIN ")" : "");
         update_node_processes(local_nodeid, NULL, get_process_list());
         return TRUE;
 
     } else {
         /* Start a new session */
         (void)setsid();
 
         /* Setup the two alternate arg arrarys */
         opts_vgrind[0] = strdup(VALGRIND_BIN);
         if (use_callgrind) {
             opts_vgrind[1] = strdup("--tool=callgrind");
             opts_vgrind[2] = strdup("--callgrind-out-file=" CRM_STATE_DIR "/callgrind.out.%p");
             opts_vgrind[3] = strdup(child->command);
             opts_vgrind[4] = NULL;
         } else {
             opts_vgrind[1] = strdup(child->command);
             opts_vgrind[2] = NULL;
             opts_vgrind[3] = NULL;
             opts_vgrind[4] = NULL;
         }
         opts_default[0] = strdup(child->command);;
 
         if(gid) {
             if(stack == pcmk_cluster_corosync) {
                 /* Drop root privileges completely
                  *
                  * We can do this because we set uidgid.gid.${gid}=1
                  * via CMAP which allows these processes to connect to
                  * corosync
                  */
                 if (setgid(gid) < 0) {
                     crm_perror(LOG_ERR, "Could not set group to %d", gid);
                 }
 
                 /* Keep the root group (so we can access corosync), but add the haclient group (so we can access ipc) */
             } else if (initgroups(child->uid, gid) < 0) {
                 crm_err("Cannot initalize groups for %s: %s (%d)", child->uid, pcmk_strerror(errno), errno);
             }
         }
 
         if (uid && setuid(uid) < 0) {
             crm_perror(LOG_ERR, "Could not set user to %d (%s)", uid, child->uid);
         }
 
         /* Close all open file descriptors */
         getrlimit(RLIMIT_NOFILE, &oflimits);
         for (lpc = 0; lpc < oflimits.rlim_cur; lpc++) {
             close(lpc);
         }
 
         (void)open(devnull, O_RDONLY);  /* Stdin:  fd 0 */
         (void)open(devnull, O_WRONLY);  /* Stdout: fd 1 */
         (void)open(devnull, O_WRONLY);  /* Stderr: fd 2 */
 
         if (use_valgrind) {
             (void)execvp(VALGRIND_BIN, opts_vgrind);
         } else {
             (void)execvp(child->command, opts_default);
         }
         crm_perror(LOG_ERR, "FATAL: Cannot exec %s", child->command);
         crm_exit(DAEMON_RESPAWN_STOP);
     }
     return TRUE;                /* never reached */
 }
 
 static gboolean
 escalate_shutdown(gpointer data)
 {
 
     pcmk_child_t *child = data;
 
     if (child->pid) {
         /* Use SIGSEGV instead of SIGKILL to create a core so we can see what it was up to */
         crm_err("Child %s not terminating in a timely manner, forcing", child->name);
         stop_child(child, SIGSEGV);
     }
     return FALSE;
 }
 
 static gboolean
 pcmk_shutdown_worker(gpointer user_data)
 {
     static int phase = 0;
     static time_t next_log = 0;
     static int max = SIZEOF(pcmk_children);
 
     int lpc = 0;
 
     if (phase == 0) {
         crm_notice("Shuting down Pacemaker");
         phase = max;
 
         /* Add a second, more frequent, check to speed up shutdown */
         g_timeout_add_seconds(5, check_active_before_startup_processes, NULL);
     }
 
     for (; phase > 0; phase--) {
         /* dont stop anything with start_seq < 1 */
 
         for (lpc = max - 1; lpc >= 0; lpc--) {
             pcmk_child_t *child = &(pcmk_children[lpc]);
 
             if (phase != child->start_seq) {
                 continue;
             }
 
             if (child->pid) {
                 time_t now = time(NULL);
 
                 if (child->respawn) {
                     next_log = now + 30;
                     child->respawn = FALSE;
                     stop_child(child, SIGTERM);
                     if (phase < pcmk_children[pcmk_child_crmd].start_seq) {
                         g_timeout_add(180000 /* 3m */ , escalate_shutdown, child);
                     }
 
                 } else if (now >= next_log) {
                     next_log = now + 30;
                     crm_notice("Still waiting for %s (pid=%d, seq=%d) to terminate...",
                                child->name, child->pid, child->start_seq);
                 }
                 return TRUE;
             }
 
             /* cleanup */
             crm_debug("%s confirmed stopped", child->name);
             child->pid = 0;
         }
     }
 
     /* send_cluster_id(); */
     crm_notice("Shutdown complete");
     g_main_loop_quit(mainloop);
 
     if (fatal_error) {
         crm_notice("Attempting to inhibit respawning after fatal error");
         crm_exit(DAEMON_RESPAWN_STOP);
     }
 
     return TRUE;
 }
 
 static void
 pcmk_ignore(int nsig)
 {
     crm_info("Ignoring signal %s (%d)", strsignal(nsig), nsig);
 }
 
 static void
 pcmk_sigquit(int nsig)
 {
     pcmk_panic(__FUNCTION__);
 }
 
 void
 pcmk_shutdown(int nsig)
 {
     if (shutdown_trigger == NULL) {
         shutdown_trigger = mainloop_add_trigger(G_PRIORITY_HIGH, pcmk_shutdown_worker, NULL);
     }
     mainloop_set_trigger(shutdown_trigger);
 }
 
 static int32_t
 pcmk_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 {
     crm_trace("Connection %p", c);
     if (crm_client_new(c, uid, gid) == NULL) {
         return -EIO;
     }
     return 0;
 }
 
 static void
 pcmk_ipc_created(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p", c);
 }
 
 /* Exit code means? */
 static int32_t
 pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size)
 {
     uint32_t id = 0;
     uint32_t flags = 0;
     const char *task = NULL;
     crm_client_t *c = crm_client_get(qbc);
     xmlNode *msg = crm_ipcs_recv(c, data, size, &id, &flags);
 
     crm_ipcs_send_ack(c, id, flags, "ack", __FUNCTION__, __LINE__);
     if (msg == NULL) {
         return 0;
     }
 
     task = crm_element_value(msg, F_CRM_TASK);
     if (crm_str_eq(task, CRM_OP_QUIT, TRUE)) {
         /* Time to quit */
         crm_notice("Shutting down in responce to ticket %s (%s)",
                    crm_element_value(msg, F_CRM_REFERENCE), crm_element_value(msg, F_CRM_ORIGIN));
         pcmk_shutdown(15);
 
     } else if (crm_str_eq(task, CRM_OP_RM_NODE_CACHE, TRUE)) {
         /* Send to everyone */
         struct iovec *iov;
         int id = 0;
         const char *name = NULL;
 
         crm_element_value_int(msg, XML_ATTR_ID, &id);
         name = crm_element_value(msg, XML_ATTR_UNAME);
         crm_notice("Instructing peers to remove references to node %s/%u", name, id);
 
         iov = calloc(1, sizeof(struct iovec));
         iov->iov_base = dump_xml_unformatted(msg);
         iov->iov_len = 1 + strlen(iov->iov_base);
         send_cpg_iov(iov);
 
     } else {
         update_process_clients(c);
     }
 
     free_xml(msg);
     return 0;
 }
 
 /* Error code means? */
 static int32_t
 pcmk_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
 pcmk_ipc_destroy(qb_ipcs_connection_t * c)
 {
     crm_trace("Connection %p", c);
     pcmk_ipc_closed(c);
 }
 
 struct qb_ipcs_service_handlers mcp_ipc_callbacks = {
     .connection_accept = pcmk_ipc_accept,
     .connection_created = pcmk_ipc_created,
     .msg_process = pcmk_ipc_dispatch,
     .connection_closed = pcmk_ipc_closed,
     .connection_destroyed = pcmk_ipc_destroy
 };
 
 void
 update_process_clients(crm_client_t *client)
 {
     GHashTableIter iter;
     crm_node_t *node = NULL;
     xmlNode *update = create_xml_node(NULL, "nodes");
 
     crm_trace("Sending process list to %d children", crm_hash_table_size(client_connections));
 
     g_hash_table_iter_init(&iter, crm_peer_cache);
     while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & node)) {
         xmlNode *xml = create_xml_node(update, "node");
 
         crm_xml_add_int(xml, "id", node->id);
         crm_xml_add(xml, "uname", node->uname);
         crm_xml_add(xml, "state", node->state);
         crm_xml_add_int(xml, "processes", node->processes);
     }
 
     if(client) {
         crm_ipcs_send(client, 0, update, crm_ipc_server_event);
 
     } else {
         g_hash_table_iter_init(&iter, client_connections);
         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) & client)) {
             crm_ipcs_send(client, 0, update, crm_ipc_server_event);
         }
     }
 
     free_xml(update);
 }
 
 void
 update_process_peers(void)
 {
     /* Do nothing for corosync-2 based clusters */
 
     char buffer[1024];
     struct iovec *iov;
     int rc = 0;
 
     memset(buffer, 0, SIZEOF(buffer));
 
     if (local_name) {
         rc = snprintf(buffer, SIZEOF(buffer) - 1, "<node uname=\"%s\" proclist=\"%u\"/>",
                       local_name, get_process_list());
     } else {
         rc = snprintf(buffer, SIZEOF(buffer) - 1, "<node proclist=\"%u\"/>", get_process_list());
     }
 
     crm_trace("Sending %s", buffer);
     iov = calloc(1, sizeof(struct iovec));
     iov->iov_base = strdup(buffer);
     iov->iov_len = rc + 1;
     send_cpg_iov(iov);
 }
 
 gboolean
 update_node_processes(uint32_t id, const char *uname, uint32_t procs)
 {
     gboolean changed = FALSE;
     crm_node_t *node = crm_get_peer(id, uname);
 
     if (procs != 0) {
         if (procs != node->processes) {
             crm_debug("Node %s now has process list: %.32x (was %.32x)",
                       node->uname, procs, node->processes);
             node->processes = procs;
             changed = TRUE;
 
         } else {
             crm_trace("Node %s still has process list: %.32x", node->uname, procs);
         }
     }
 
     if (changed && id == local_nodeid) {
         update_process_clients(NULL);
         update_process_peers();
     }
     return changed;
 }
 
 
 /* *INDENT-OFF* */
 static struct crm_option long_options[] = {
     /* Top-level Options */
     {"help",           0, 0, '?', "\tThis text"},
     {"version",        0, 0, '$', "\tVersion information"  },
     {"verbose",        0, 0, 'V', "\tIncrease debug output"},
     {"shutdown",       0, 0, 'S', "\tInstruct Pacemaker to shutdown on this machine"},
     {"features",       0, 0, 'F', "\tDisplay the full version and list of features Pacemaker was built with"},
 
     {"-spacer-",       1, 0, '-', "\nAdditional Options:"},
     {"foreground",     0, 0, 'f', "\t(Ignored) Pacemaker always runs in the foreground"},
     {"pid-file",       1, 0, 'p', "\t(Ignored) Daemon pid file location"},
 
     {NULL, 0, 0, 0}
 };
 /* *INDENT-ON* */
 
 static void
 mcp_chown(const char *path, uid_t uid, gid_t gid)
 {
     int rc = chown(path, uid, gid);
 
     if (rc < 0) {
         crm_warn("Cannot change the ownership of %s to user %s and gid %d: %s",
                  path, CRM_DAEMON_USER, gid, pcmk_strerror(errno));
     }
 }
 
 static gboolean
 check_active_before_startup_processes(gpointer user_data)
 {
     int start_seq = 1, lpc = 0;
     static int max = SIZEOF(pcmk_children);
     gboolean keep_tracking = FALSE;
 
     for (start_seq = 1; start_seq < max; start_seq++) {
         for (lpc = 0; lpc < max; lpc++) {
             if (pcmk_children[lpc].active_before_startup == FALSE) {
                 /* we are already tracking it as a child process. */
                 continue;
             } else if (start_seq != pcmk_children[lpc].start_seq) {
                 continue;
             } else if (crm_pid_active(pcmk_children[lpc].pid) != 1) {
                 crm_notice("Process %s terminated (pid=%d)",
                            pcmk_children[lpc].name, pcmk_children[lpc].pid);
                 pcmk_process_exit(&(pcmk_children[lpc]));
                 continue;
             }
             /* at least one of the processes found at startup
              * is still going, so keep this recurring timer around */
             keep_tracking = TRUE;
         }
     }
 
     return keep_tracking;
 }
 
 static bool
 find_and_track_existing_processes(void)
 {
     DIR *dp;
     struct dirent *entry;
     struct stat statbuf;
     int start_tracker = 0;
 
     dp = opendir("/proc");
     if (!dp) {
         /* no proc directory to search through */
         crm_notice("Can not read /proc directory to track existing components");
         return FALSE;
     }
 
     while ((entry = readdir(dp)) != NULL) {
         char procpath[128];
         char value[64];
         char key[16];
         FILE *file;
         int pid;
         int max = SIZEOF(pcmk_children);
         int i;
 
         strcpy(procpath, "/proc/");
         /* strlen("/proc/") + strlen("/status") + 1 = 14
          * 128 - 14 = 114 */
         strncat(procpath, entry->d_name, 114);
 
         if (lstat(procpath, &statbuf)) {
             continue;
         }
         if (!S_ISDIR(statbuf.st_mode) || !isdigit(entry->d_name[0])) {
             continue;
         }
 
         strcat(procpath, "/status");
 
         file = fopen(procpath, "r");
         if (!file) {
             continue;
         }
         if (fscanf(file, "%15s%63s", key, value) != 2) {
             fclose(file);
             continue;
         }
         fclose(file);
 
         pid = atoi(entry->d_name);
         if (pid <= 0) {
             continue;
         }
 
         for (i = 0; i < max; i++) {
             const char *name = pcmk_children[i].name;
 
             if (pcmk_children[i].start_seq == 0) {
                 continue;
             }
             if (pcmk_children[i].flag == crm_proc_stonith_ng) {
                 name = "stonithd";
             }
             if (safe_str_eq(name, value)) {
                 if (crm_pid_active(pid) != 1) {
                     continue;
                 }
                 crm_notice("Tracking existing %s process (pid=%d)", value, pid);
                 pcmk_children[i].pid = pid;
                 pcmk_children[i].active_before_startup = TRUE;
                 start_tracker = 1;
             }
         }
     }
 
     if (start_tracker) {
         g_timeout_add_seconds(PCMK_PROCESS_CHECK_INTERVAL, check_active_before_startup_processes,
                               NULL);
     }
     closedir(dp);
 
     return start_tracker;
 }
 
 static void
 init_children_processes(void)
 {
     int start_seq = 1, lpc = 0;
     static int max = SIZEOF(pcmk_children);
 
     /* start any children that have not been detected */
     for (start_seq = 1; start_seq < max; start_seq++) {
         /* dont start anything with start_seq < 1 */
         for (lpc = 0; lpc < max; lpc++) {
             if (pcmk_children[lpc].pid) {
                 /* we are already tracking it */
                 continue;
             }
 
             if (start_seq == pcmk_children[lpc].start_seq) {
                 start_child(&(pcmk_children[lpc]));
             }
         }
     }
 
     /* From this point on, any daemons being started will be due to
      * respawning rather than node start.
      *
      * This may be useful for the daemons to know
      */
     setenv("PCMK_respawned", "true", 1);
 }
 
 static void
 mcp_cpg_destroy(gpointer user_data)
 {
     crm_err("Connection destroyed");
     crm_exit(ENOTCONN);
 }
 
 static void
 mcp_cpg_deliver(cpg_handle_t handle,
                  const struct cpg_name *groupName,
                  uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
 {
     xmlNode *xml = string2xml(msg);
     const char *task = crm_element_value(xml, F_CRM_TASK);
 
     crm_trace("Received %s %.200s", task, msg);
     if (task == NULL && nodeid != local_nodeid) {
         uint32_t procs = 0;
         const char *uname = crm_element_value(xml, "uname");
 
         crm_element_value_int(xml, "proclist", (int *)&procs);
         /* crm_debug("Got proclist %.32x from %s", procs, uname); */
         if (update_node_processes(nodeid, uname, procs)) {
             update_process_clients(NULL);
         }
 
     } else if (crm_str_eq(task, CRM_OP_RM_NODE_CACHE, TRUE)) {
         int id = 0;
         const char *name = NULL;
 
         crm_element_value_int(xml, XML_ATTR_ID, &id);
         name = crm_element_value(xml, XML_ATTR_UNAME);
         reap_crm_member(id, name);
     }
 }
 
 static void
 mcp_cpg_membership(cpg_handle_t handle,
                     const struct cpg_name *groupName,
                     const struct cpg_address *member_list, size_t member_list_entries,
                     const struct cpg_address *left_list, size_t left_list_entries,
                     const struct cpg_address *joined_list, size_t joined_list_entries)
 {
     /* Don't care about CPG membership, but we do want to broadcast our own presence */
     update_process_peers();
 }
 
 static gboolean
 mcp_quorum_callback(unsigned long long seq, gboolean quorate)
 {
     /* Nothing to do */
     return TRUE;
 }
 
 static void
 mcp_quorum_destroy(gpointer user_data)
 {
     crm_info("connection closed");
 }
 
 int
 main(int argc, char **argv)
 {
     int rc;
     int flag;
     int argerr = 0;
 
     int option_index = 0;
     gboolean shutdown = FALSE;
 
     uid_t pcmk_uid = 0;
     gid_t pcmk_gid = 0;
     struct rlimit cores;
     crm_ipc_t *old_instance = NULL;
     qb_ipcs_service_t *ipcs = NULL;
     const char *facility = daemon_option("logfacility");
     static crm_cluster_t cluster;
 
     crm_log_preinit(NULL, argc, argv);
     crm_set_options(NULL, "mode [options]", long_options, "Start/Stop Pacemaker\n");
     mainloop_add_signal(SIGHUP, pcmk_ignore);
     mainloop_add_signal(SIGQUIT, pcmk_sigquit);
 
     while (1) {
         flag = crm_get_option(argc, argv, &option_index);
         if (flag == -1)
             break;
 
         switch (flag) {
             case 'V':
                 crm_bump_log_level(argc, argv);
                 break;
             case 'f':
                 /* Legacy */
                 break;
             case 'p':
                 pid_file = optarg;
                 break;
             case '$':
             case '?':
                 crm_help(flag, EX_OK);
                 break;
             case 'S':
                 shutdown = TRUE;
                 break;
             case 'F':
                 printf("Pacemaker %s (Build: %s)\n Supporting v%s: %s\n", VERSION, BUILD_VERSION,
                        CRM_FEATURE_SET, CRM_FEATURES);
                 crm_exit(pcmk_ok);
             default:
                 printf("Argument code 0%o (%c) is not (?yet?) supported\n", flag, flag);
                 ++argerr;
                 break;
         }
     }
 
     if (optind < argc) {
         printf("non-option ARGV-elements: ");
         while (optind < argc)
             printf("%s ", argv[optind++]);
         printf("\n");
     }
     if (argerr) {
         crm_help('?', EX_USAGE);
     }
 
 
     setenv("LC_ALL", "C", 1);
     setenv("HA_LOGD", "no", 1);
 
     set_daemon_option("mcp", "true");
     set_daemon_option("use_logd", "off");
 
     crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
 
     /* Restore the original facility so that mcp_read_config() does the right thing */
     set_daemon_option("logfacility", facility);
 
     crm_debug("Checking for old instances of %s", CRM_SYSTEM_MCP);
     old_instance = crm_ipc_new(CRM_SYSTEM_MCP, 0);
     crm_ipc_connect(old_instance);
 
     if (shutdown) {
         crm_debug("Terminating previous instance");
         while (crm_ipc_connected(old_instance)) {
             xmlNode *cmd =
                 create_request(CRM_OP_QUIT, NULL, NULL, CRM_SYSTEM_MCP, CRM_SYSTEM_MCP, NULL);
 
             crm_debug(".");
             crm_ipc_send(old_instance, cmd, 0, 0, NULL);
             free_xml(cmd);
 
             sleep(2);
         }
         crm_ipc_close(old_instance);
         crm_ipc_destroy(old_instance);
         crm_exit(pcmk_ok);
 
     } else if (crm_ipc_connected(old_instance)) {
         crm_ipc_close(old_instance);
         crm_ipc_destroy(old_instance);
         crm_err("Pacemaker is already active, aborting startup");
         crm_exit(DAEMON_RESPAWN_STOP);
     }
 
     crm_ipc_close(old_instance);
     crm_ipc_destroy(old_instance);
 
     if (mcp_read_config() == FALSE) {
         crm_notice("Could not obtain corosync config data, exiting");
         crm_exit(ENODATA);
     }
 
     crm_notice("Starting Pacemaker %s (Build: %s): %s", VERSION, BUILD_VERSION, CRM_FEATURES);
     mainloop = g_main_new(FALSE);
     sysrq_init();
 
     rc = getrlimit(RLIMIT_CORE, &cores);
     if (rc < 0) {
         crm_perror(LOG_ERR, "Cannot determine current maximum core size.");
     } else {
         if (cores.rlim_max == 0 && geteuid() == 0) {
             cores.rlim_max = RLIM_INFINITY;
         } else {
             crm_info("Maximum core file size is: %lu", (unsigned long)cores.rlim_max);
         }
         cores.rlim_cur = cores.rlim_max;
 
         rc = setrlimit(RLIMIT_CORE, &cores);
         if (rc < 0) {
             crm_perror(LOG_ERR,
                        "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) {
             crm_perror(LOG_ERR, "Could not enable /proc/sys/kernel/core_uses_pid");
         }
 #endif
     }
     rc = pcmk_ok;
 
     if (crm_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) < 0) {
         crm_err("Cluster user %s does not exist, aborting Pacemaker startup", CRM_DAEMON_USER);
         crm_exit(ENOKEY);
     }
 
     mkdir(CRM_STATE_DIR, 0750);
     mcp_chown(CRM_STATE_DIR, pcmk_uid, pcmk_gid);
 
     /* Used to store core files in */
     crm_build_path(CRM_CORE_DIR, 0775);
     mcp_chown(CRM_CORE_DIR, pcmk_uid, pcmk_gid);
 
     /* Used to store blackbox dumps in */
     crm_build_path(CRM_BLACKBOX_DIR, 0755);
     mcp_chown(CRM_BLACKBOX_DIR, pcmk_uid, pcmk_gid);
 
     /* Used to store policy engine inputs in */
     crm_build_path(PE_STATE_DIR, 0755);
     mcp_chown(PE_STATE_DIR, pcmk_uid, pcmk_gid);
 
     /* Used to store the cluster configuration */
     crm_build_path(CRM_CONFIG_DIR, 0755);
     mcp_chown(CRM_CONFIG_DIR, pcmk_uid, pcmk_gid);
 
     /* Resource agent paths are constructed by the lrmd */
 
     ipcs = mainloop_add_ipc_server(CRM_SYSTEM_MCP, QB_IPC_NATIVE, &mcp_ipc_callbacks);
     if (ipcs == NULL) {
         crm_err("Couldn't start IPC server");
         crm_exit(EIO);
     }
 
     /* Allows us to block shutdown */
     if (cluster_connect_cfg(&local_nodeid) == FALSE) {
         crm_err("Couldn't connect to Corosync's CFG service");
         crm_exit(ENOPROTOOPT);
     }
 
+    if(pcmk_locate_sbd() > 0) {
+        setenv("PCMK_watchdog", "true", 1);
+    }
+
     find_and_track_existing_processes();
 
     cluster.destroy = mcp_cpg_destroy;
     cluster.cpg.cpg_deliver_fn = mcp_cpg_deliver;
     cluster.cpg.cpg_confchg_fn = mcp_cpg_membership;
 
     if(cluster_connect_cpg(&cluster) == FALSE) {
         crm_err("Couldn't connect to Corosync's CPG service");
         rc = -ENOPROTOOPT;
     }
 
     if (rc == pcmk_ok && is_corosync_cluster()) {
         /* Keep the membership list up-to-date for crm_node to query */
         if(cluster_connect_quorum(mcp_quorum_callback, mcp_quorum_destroy) == FALSE) {
             rc = -ENOTCONN;
         }
     }
 
     if(rc == pcmk_ok) {
         local_name = get_local_node_name();
         update_node_processes(local_nodeid, local_name, get_process_list());
 
         mainloop_add_signal(SIGTERM, pcmk_shutdown);
         mainloop_add_signal(SIGINT, pcmk_shutdown);
 
         init_children_processes();
 
         crm_info("Starting mainloop");
 
         g_main_run(mainloop);
     }
 
     if (ipcs) {
         crm_trace("Closing IPC server");
         mainloop_del_ipc_server(ipcs);
         ipcs = NULL;
     }
 
     g_main_destroy(mainloop);
 
     cluster_disconnect_cpg(&cluster);
     cluster_disconnect_cfg();
 
     crm_info("Exiting %s", crm_system_name);
 
     return crm_exit(rc);
 }