diff --git a/crmd/control.c b/crmd/control.c
index 1c5a9d3891..646da00d2a 100644
--- a/crmd/control.c
+++ b/crmd/control.c
@@ -1,951 +1,950 @@
 /* 
  * 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/cib/internal.h>
 #include <crm/msg_xml.h>
 
 #include <crm/pengine/rules.h>
 #include <crm/cluster/internal.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 <sys/types.h>
 #include <sys/stat.h>
 #include <grp.h>
 
 qb_ipcs_service_t *ipcs = NULL;
 
 extern gboolean crm_connect_corosync(void);
 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;
 GHashTable *ipc_clients = NULL;
 crm_trigger_t *fsa_source = NULL;
 crm_trigger_t *config_read = NULL;
 
 /*	 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;
 
     if (action & A_HA_DISCONNECT) {
         if (is_openais_cluster()) {
             crm_peer_destroy();
 #if SUPPORT_COROSYNC
             terminate_ais_connection();
 #endif
             crm_info("Disconnected from OpenAIS");
 
 #if SUPPORT_HEARTBEAT
         } else if (fsa_cluster_conn != NULL) {
             set_bit(fsa_input_register, R_HA_DISCONNECTED);
             fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn, FALSE);
             crm_info("Disconnected from Heartbeat");
 #endif
         }
     }
 
     if (action & A_HA_CONNECT) {
         crm_set_status_callback(&peer_update_callback);
 
         if (is_openais_cluster()) {
 #if SUPPORT_COROSYNC
             registered = crm_connect_corosync();
 #endif
         } else if (is_heartbeat_cluster()) {
 #if SUPPORT_HEARTBEAT
             registered =
                 crm_cluster_connect(&fsa_our_uname, &fsa_our_uuid, crmd_ha_msg_callback,
                                     crmd_ha_connection_destroy, &fsa_cluster_conn);
 #endif
         }
 #if SUPPORT_HEARTBEAT
         if (is_heartbeat_cluster()) {
             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
 
         if (registered == FALSE) {
             set_bit(fsa_input_register, R_HA_DISCONNECTED);
             register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
             return;
         }
 
         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(NULL);
             }
         }
         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;
 
 void log_connected_client(gpointer key, gpointer value, gpointer user_data);
 
 void
 log_connected_client(gpointer key, gpointer value, gpointer user_data)
 {
     crmd_client_t *client = value;
 
     crm_err("%s is still connected at exit", client->table_key);
 }
 
 static void
 free_mem(fsa_data_t * msg_data)
 {
     GListPtr gIter = NULL;
 
     crm_ipc_close(attrd_ipc);
     crm_ipc_destroy(attrd_ipc);
     g_main_loop_quit(crmd_mainloop);
     g_main_loop_unref(crmd_mainloop);
 
 #if SUPPORT_HEARTBEAT
     if (fsa_cluster_conn) {
         fsa_cluster_conn->llc_ops->delete(fsa_cluster_conn);
         fsa_cluster_conn = NULL;
     }
 #endif
 
     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);
     }
     g_list_free(fsa_message_queue);
     delete_fsa_input(msg_data);
 
     if (ipc_clients) {
         crm_debug("Number of connected clients: %d", g_hash_table_size(ipc_clients));
 /* 		g_hash_table_foreach(ipc_clients, log_connected_client, NULL); */
         g_hash_table_destroy(ipc_clients);
     }
 
     empty_uuid_cache();
     crm_peer_destroy();
     clear_bit(fsa_input_register, R_MEMBERSHIP);
 
     if (te_subsystem->client && te_subsystem->client->ipc) {
         crm_debug("Full destroy: TE");
         qb_ipcs_disconnect(te_subsystem->client->ipc);
     }
     free(te_subsystem);
 
     if (pe_subsystem->client && pe_subsystem->client->ipc) {
         crm_debug("Full destroy: PE");
         qb_ipcs_disconnect(pe_subsystem->client->ipc);
     }
     free(pe_subsystem);
 
     free(cib_subsystem);
 
     if (integrated_nodes) {
         g_hash_table_destroy(integrated_nodes);
     }
     if (finalized_nodes) {
         g_hash_table_destroy(finalized_nodes);
     }
     if (confirmed_nodes) {
         g_hash_table_destroy(confirmed_nodes);
     }
     if (reload_hash) {
         g_hash_table_destroy(reload_hash);
     }
     if (resource_history) {
         g_hash_table_destroy(resource_history);
     }
     if (voted) {
         g_hash_table_destroy(voted);
     }
 
     cib_delete(fsa_cib_conn);
     fsa_cib_conn = NULL;
 
     if (fsa_lrm_conn) {
         lrmd_api_delete(fsa_lrm_conn);
         fsa_lrm_conn = NULL;
     }
 
     free(transition_timer);
     free(integration_timer);
     free(finalization_timer);
     free(election_trigger);
     free(election_timeout);
     free(shutdown_escalation_timer);
     free(wait_timer);
     free(recheck_timer);
 
     free(fsa_our_dc_version);
     free(fsa_our_uname);
     free(fsa_our_uuid);
     free(fsa_our_dc);
 
     free(max_generation_from);
     free_xml(max_generation_xml);
 
     crm_xml_cleanup();
 }
 
 /*	 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 = 0;
     int log_level = LOG_INFO;
     const char *exit_type = "gracefully";
 
     if (action & A_EXIT_1) {
         exit_code = 1;
         log_level = LOG_ERR;
         exit_type = "forcefully";
     }
 
     verify_stopped(cur_state, LOG_ERR);
     do_crm_log(log_level, "Performing %s - %s exiting the CRMd",
                fsa_action2string(action), exit_type);
 
     if (is_set(fsa_input_register, R_IN_RECOVERY)) {
         crm_err("Could not recover from internal error");
         exit_code = 2;
     }
     if (is_set(fsa_input_register, R_STAYDOWN)) {
         crm_warn("Inhibiting respawn by Heartbeat");
         exit_code = 100;
     }
 
     crm_info("[%s] stopped (%d)", crm_system_name, exit_code);
     free_mem(msg_data);
     exit(exit_code);
 }
 
 /*	 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;
     int interval = 1;           /* seconds between DC heartbeats */
 
     crm_debug("Registering Signal Handlers");
     mainloop_add_signal(SIGTERM, crm_shutdown);
 
     fsa_source = mainloop_add_trigger(G_PRIORITY_HIGH, crm_fsa_trigger, NULL);
     config_read = mainloop_add_trigger(G_PRIORITY_HIGH, crm_read_options, NULL);
 
     ipc_clients = g_hash_table_new(crm_str_hash, g_str_equal);
 
     crm_debug("Creating CIB and LRM objects");
     fsa_cib_conn = cib_new();
     fsa_lrm_conn = lrmd_api_new();
 
     /* 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));
     election_timeout = 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));
 
     interval = interval * 1000;
 
     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 (election_timeout != NULL) {
         election_timeout->source_id = 0;
         election_timeout->period_ms = -1;
         election_timeout->fsa_input = I_ELECTION_DC;
         election_timeout->callback = crm_timer_popped;
         election_timeout->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);
     }
 
     welcomed_nodes = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                            g_hash_destroy_str, g_hash_destroy_str);
     integrated_nodes = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                              g_hash_destroy_str, g_hash_destroy_str);
     finalized_nodes = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                             g_hash_destroy_str, g_hash_destroy_str);
     confirmed_nodes = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                             g_hash_destroy_str, g_hash_destroy_str);
 }
 
 static int32_t
 crmd_ipc_accept(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
 {
     crmd_client_t *blank_client = NULL;
 #if ENABLE_ACL
     struct group *crm_grp = NULL;
 #endif
 
     crm_trace("Connecting %p for uid=%d gid=%d", c, uid, gid);
 
     blank_client = calloc(1, sizeof(crmd_client_t));
     CRM_ASSERT(blank_client != NULL);
 
     crm_trace("Created client: %p", blank_client);
 
     blank_client->ipc = c;
     blank_client->sub_sys = NULL;
     blank_client->uuid = NULL;
     blank_client->table_key = NULL;
 
 #if ENABLE_ACL
     crm_grp = getgrnam(CRM_DAEMON_GROUP);
     if (crm_grp) {
         qb_ipcs_connection_auth_set(c, -1, crm_grp->gr_gid, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
     }
 
     blank_client->user = uid2username(uid);
 #endif
 
     qb_ipcs_context_set(c, blank_client);
 
     return 0;
 }
 
 static void
 crmd_ipc_created(qb_ipcs_connection_t *c)
 {
     crm_trace("Client %p connected", c);
 }
 
 static int32_t
 crmd_ipc_dispatch(qb_ipcs_connection_t *c, void *data, size_t size)
 {
     crmd_client_t *client = qb_ipcs_context_get(c);
 
     xmlNode *msg = crm_ipcs_recv(c, data, size);
     xmlNode *ack = create_xml_node(NULL, "ack");
 
     crm_trace("Invoked: %s", client->table_key);
 
     crm_ipcs_send(c, ack, FALSE); /* TODO: Do not unconditionally send this */
     free_xml(ack);
     
     if (msg == NULL) {
         return 0;
     }
 
 #if ENABLE_ACL
     determine_request_user(client->user, msg, F_CRM_USER);
 #endif
 
     crm_trace("Processing msg from %s", client->table_key);
     crm_log_xml_trace(msg, "CRMd[inbound]");
 
     if (crmd_authorize_message(msg, client)) {
         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) 
 {
     return 0;
 }
 
 static void
 crmd_ipc_destroy(qb_ipcs_connection_t *c) 
 {
     crmd_client_t *client = qb_ipcs_context_get(c);
 
     if (client == NULL) {
         crm_trace("No client to delete");
         return;
     }
 
     process_client_disconnect(client);
     
     crm_trace("Disconnecting client %s (%p)", client->table_key, client);
     free(client->table_key);
     free(client->sub_sys);
     free(client->uuid);
     free(client->user);
     free(client);
 
     trigger_fsa(fsa_source);    
 }
 
 /*	 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)
 {
     if (is_heartbeat_cluster()) {
         stop_subsystem(pe_subsystem, FALSE);   
     }
 
     mainloop_del_ipc_server(ipcs);
     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(NULL);
         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(NULL);
         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(NULL);
         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(NULL);
         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(NULL);
         return;
     }
 
     crm_debug("Init server comms");
     ipcs = mainloop_add_ipc_server(CRM_SYSTEM_CRMD, QB_IPC_NATIVE, &crmd_callbacks);
     if (ipcs == NULL) {
         crm_err("Couldn't start IPC server");
         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_err("Action %s (%.16llx) not supported", fsa_action2string(action), action);
 
     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." },
 	{ 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." },
 	{ 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." },
 };
 /* *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;
     ha_time_t *now = new_ha_date(TRUE);
 
     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_dtd_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, XML_CONFIG_ATTR_FORCE_QUIT);
     shutdown_escalation_timer->period_ms = crm_get_msec(value);
     crm_debug("Shutdown escalation occurs after: %dms", shutdown_escalation_timer->period_ms);
 
     value = crmd_pref(config_hash, XML_CONFIG_ATTR_ELECTION_FAIL);
     election_timeout->period_ms = 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_ais_text(crm_class_quorum, value, TRUE, NULL, crm_msg_ais);
     }
 #endif
 
     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:
     free_ha_date(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);
 
     add_cib_op_callback(fsa_cib_conn, 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)
 {
     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");
         exit(EX_OK);
 
     }
 }
 
 void
 default_cib_update_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
 {
     if (rc != pcmk_ok) {
         fsa_data_t *msg_data = NULL;
 
         crm_err("CIB Update failed: %s", pcmk_strerror(rc));
         crm_log_xml_warn(output, "update:failed");
 
         register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
     }
 }
 
 static void
 create_cib_node_definition(gpointer key, gpointer value, gpointer user_data)
 {
     crm_node_t *node = value;
     xmlNode *cib_nodes = user_data;
     xmlNode *cib_new_node = NULL;
 
     crm_trace("Creating node entry for %s/%s", node->uname, node->uuid);
     cib_new_node = create_xml_node(cib_nodes, XML_CIB_TAG_NODE);
     crm_xml_add(cib_new_node, XML_ATTR_ID, node->uuid);
     crm_xml_add(cib_new_node, XML_ATTR_UNAME, node->uname);
-    crm_xml_add(cib_new_node, XML_ATTR_TYPE, NORMALNODE);
 }
 
 void
 populate_cib_nodes(gboolean with_client_status)
 {
     int call_id = 0;
     xmlNode *cib_node_list = NULL;
 
 #if SUPPORT_HEARTBEAT
     if (is_heartbeat_cluster()) {
         populate_cib_nodes_ha(with_client_status);
         return;
     }
 #endif
 
     cib_node_list = create_xml_node(NULL, XML_CIB_TAG_NODES);
     g_hash_table_foreach(crm_peer_cache, create_cib_node_definition, cib_node_list);
 
     fsa_cib_update(XML_CIB_TAG_NODES, cib_node_list, cib_scope_local | cib_quorum_override, call_id,
                    NULL);
     add_cib_op_callback(fsa_cib_conn, call_id, FALSE, NULL, default_cib_update_callback);
 
     free_xml(cib_node_list);
     crm_trace("Complete");
 }
diff --git a/crmd/crmd_utils.h b/crmd/crmd_utils.h
index ced10497ce..f2593bd9d7 100644
--- a/crmd/crmd_utils.h
+++ b/crmd/crmd_utils.h
@@ -1,95 +1,93 @@
 /* 
  * 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
  */
 #ifndef CRMD_UTILS__H
 #  define CRMD_UTILS__H
 
 #  include <crm/crm.h>
 #  include <crm/common/xml.h>
 
 #  define CLIENT_EXIT_WAIT 30
 #  define FAKE_TE_ID	"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
 
 extern void process_client_disconnect(crmd_client_t * curr_client);
 
 #  define fsa_cib_update(section, data, options, call_id, user_name)	\
 	if(fsa_cib_conn != NULL) {					\
 	    call_id = fsa_cib_conn->cmds->delegated_variant_op(		\
 		fsa_cib_conn, CIB_OP_MODIFY, NULL, section, data,	\
 		NULL, options, user_name);				\
 									\
 	} else {							\
 		crm_err("No CIB connection available");			\
 	}
 
 #  define fsa_cib_anon_update(section, data, options)			\
 	if(fsa_cib_conn != NULL) {					\
 	    fsa_cib_conn->cmds->modify(					\
 		fsa_cib_conn, section, data, options);			\
 									\
 	} else {							\
 		crm_err("No CIB connection available");			\
 	}
 
 extern gboolean fsa_has_quorum;
 extern int last_peer_update;
 
 extern gboolean crm_timer_stop(fsa_timer_t * timer);
 extern gboolean crm_timer_start(fsa_timer_t * timer);
 extern gboolean crm_timer_popped(gpointer data);
 extern gboolean is_timer_started(fsa_timer_t *timer);
 
 extern xmlNode *create_node_state(const char *uname, const char *in_cluster,
                                   const char *is_peer, const char *join_state,
                                   const char *exp_state, gboolean clear_shutdown, const char *src);
 
-extern void create_node_entry(const char *uuid, const char *uname, const char *type);
-
 extern gboolean stop_subsystem(struct crm_subsystem_s *centry, gboolean force_quit);
 extern gboolean start_subsystem(struct crm_subsystem_s *centry);
 
 extern void fsa_dump_actions(long long action, const char *text);
 extern void fsa_dump_inputs(int log_level, const char *text, long long input_register);
 
 extern gboolean update_dc(xmlNode * msg);
 extern void erase_node_from_join(const char *node);
 extern void populate_cib_nodes(gboolean with_client_status);
 extern void crm_update_quorum(gboolean quorum, gboolean force_update);
 extern void erase_status_tag(const char *uname, const char *tag, int options);
 extern void update_attrd(const char *host, const char *name, const char *value,
                          const char *user_name);
 
 extern const char *get_timer_desc(fsa_timer_t * timer);
 gboolean too_many_st_failures(void);
 
 #  define start_transition(state) do {					\
 	switch(state) {							\
 	    case S_TRANSITION_ENGINE:					\
 		register_fsa_action(A_TE_CANCEL);			\
 		break;							\
 	    case S_POLICY_ENGINE:					\
 	    case S_IDLE:						\
 		register_fsa_input(C_FSA_INTERNAL, I_PE_CALC, NULL);	\
 		break;							\
 	    default:							\
 		crm_debug("NOT starting a new transition in state %s",	\
 			  fsa_state2string(fsa_state));			\
 		break;							\
 	}								\
     } while(0)
 
 #endif
diff --git a/crmd/join_dc.c b/crmd/join_dc.c
index 7a9191f1e3..c8e75821e7 100644
--- a/crmd/join_dc.c
+++ b/crmd/join_dc.c
@@ -1,657 +1,665 @@
 /* 
  * 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 <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/cluster.h>
 
 #include <crmd_fsa.h>
 #include <crmd_messages.h>
 
 GHashTable *welcomed_nodes = NULL;
 GHashTable *integrated_nodes = NULL;
 GHashTable *finalized_nodes = NULL;
 GHashTable *confirmed_nodes = NULL;
 char *max_epoch = NULL;
 char *max_generation_from = NULL;
 xmlNode *max_generation_xml = NULL;
 
 void initialize_join(gboolean before);
 gboolean finalize_join_for(gpointer key, gpointer value, gpointer user_data);
 void finalize_sync_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data);
 gboolean check_join_state(enum crmd_fsa_state cur_state, const char *source);
 
 static int current_join_id = 0;
 unsigned long long saved_ccm_membership_id = 0;
 
 void
 initialize_join(gboolean before)
 {
     /* clear out/reset a bunch of stuff */
     crm_debug("join-%d: Initializing join data (flag=%s)",
               current_join_id, before ? "true" : "false");
 
     g_hash_table_destroy(welcomed_nodes);
     g_hash_table_destroy(integrated_nodes);
     g_hash_table_destroy(finalized_nodes);
     g_hash_table_destroy(confirmed_nodes);
 
     if (before) {
         if (max_generation_from != NULL) {
             free(max_generation_from);
             max_generation_from = NULL;
         }
         if (max_generation_xml != NULL) {
             free_xml(max_generation_xml);
             max_generation_xml = NULL;
         }
         clear_bit(fsa_input_register, R_HAVE_CIB);
         clear_bit(fsa_input_register, R_CIB_ASKED);
     }
 
     welcomed_nodes = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                            g_hash_destroy_str, g_hash_destroy_str);
     integrated_nodes = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                              g_hash_destroy_str, g_hash_destroy_str);
     finalized_nodes = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                             g_hash_destroy_str, g_hash_destroy_str);
     confirmed_nodes = g_hash_table_new_full(crm_str_hash, g_str_equal,
                                             g_hash_destroy_str, g_hash_destroy_str);
 }
 
 void
 erase_node_from_join(const char *uname)
 {
     gboolean w = FALSE, i = FALSE, f = FALSE, c = FALSE;
 
     if (uname == NULL) {
         return;
     }
 
     if (welcomed_nodes != NULL) {
         w = g_hash_table_remove(welcomed_nodes, uname);
     }
     if (integrated_nodes != NULL) {
         i = g_hash_table_remove(integrated_nodes, uname);
     }
     if (finalized_nodes != NULL) {
         f = g_hash_table_remove(finalized_nodes, uname);
     }
     if (confirmed_nodes != NULL) {
         c = g_hash_table_remove(confirmed_nodes, uname);
     }
 
     if (w || i || f || c) {
         crm_debug("Removed node %s from join calculations:"
                  " welcomed=%d itegrated=%d finalized=%d confirmed=%d", uname, w, i, f, c);
     }
 }
 
 static void
 join_make_offer(gpointer key, gpointer value, gpointer user_data)
 {
     const char *join_to = NULL;
     const crm_node_t *member = value;
 
     CRM_ASSERT(member != NULL);
     if (crm_is_peer_active(member) == FALSE) {
         crm_trace("Not making an offer to %s: not active", member->uname);
         return;
     }
 
     join_to = member->uname;
     if (join_to == NULL) {
         crm_err("No recipient for welcome message");
         return;
     }
 
     erase_node_from_join(join_to);
 
     if (saved_ccm_membership_id != crm_peer_seq) {
         saved_ccm_membership_id = crm_peer_seq;
         crm_info("Making join offers based on membership %llu", crm_peer_seq);
     }
 
     if (crm_is_peer_active(member)) {
         xmlNode *offer = create_request(CRM_OP_JOIN_OFFER, NULL, join_to,
                                         CRM_SYSTEM_CRMD, CRM_SYSTEM_DC, NULL);
         char *join_offered = crm_itoa(current_join_id);
 
         crm_xml_add_int(offer, F_CRM_JOIN_ID, current_join_id);
         /* send the welcome */
         crm_debug("join-%d: Sending offer to %s", current_join_id, join_to);
 
         send_cluster_message(join_to, crm_msg_crmd, offer, TRUE);
         free_xml(offer);
 
         g_hash_table_insert(welcomed_nodes, strdup(join_to), join_offered);
     } else {
         crm_info("Peer process on %s is not active (yet?): %.8lx %d",
                  join_to, (long)member->processes, g_hash_table_size(crm_peer_cache));
     }
 
 }
 
 /*	 A_DC_JOIN_OFFER_ALL	*/
 void
 do_dc_join_offer_all(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)
 {
     /* reset everyones status back to down or in_ccm in the CIB
      *
      * any nodes that are active in the CIB but not in the CCM list
      *   will be seen as offline by the PE anyway
      */
     current_join_id++;
     initialize_join(TRUE);
 /* 	do_update_cib_nodes(TRUE, __FUNCTION__); */
 
     update_dc(NULL);
     if (cause == C_HA_MESSAGE && current_input == I_NODE_JOIN) {
         crm_info("A new node joined the cluster");
     }
     g_hash_table_foreach(crm_peer_cache, join_make_offer, NULL);
 
     /* dont waste time by invoking the PE yet; */
     crm_info("join-%d: Waiting on %d outstanding join acks",
              current_join_id, g_hash_table_size(welcomed_nodes));
 }
 
 /*	 A_DC_JOIN_OFFER_ONE	*/
 void
 do_dc_join_offer_one(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_node_t *member;
     ha_msg_input_t *welcome = NULL;
 
     const char *op = NULL;
     const char *join_to = NULL;
 
     if (msg_data->data) {
         welcome = fsa_typed_data(fsa_dt_ha_msg);
 
     } else {
         crm_info("A new node joined - wait until it contacts us");
         return;
     }
 
     if (welcome == NULL) {
         crm_err("Attempt to send welcome message without a message to reply to!");
         return;
     }
 
     join_to = crm_element_value(welcome->msg, F_CRM_HOST_FROM);
     if (join_to == NULL) {
         crm_err("Attempt to send welcome message without a host to reply to!");
         return;
     }
 
     member = crm_get_peer(0, join_to);
     if (crm_is_peer_active(member) == FALSE) {
         crm_err("%s is not a fully active member of our partition", join_to);
         return;
     }
 
     op = crm_element_value(welcome->msg, F_CRM_TASK);
     if (join_to != NULL && (cur_state == S_INTEGRATION || cur_state == S_FINALIZE_JOIN)) {
         /* note: it _is_ possible that a node will have been
          *  sick or starting up when the original offer was made.
          *  however, it will either re-announce itself in due course
          *  _or_ we can re-store the original offer on the client.
          */
         crm_trace("(Re-)offering membership to %s...", join_to);
     }
 
     crm_info("join-%d: Processing %s request from %s in state %s",
              current_join_id, op, join_to, fsa_state2string(cur_state));
 
     join_make_offer(NULL, member, NULL);
 
     /* always offer to the DC (ourselves)
      * this ensures the correct value for max_generation_from
      */
     member = crm_get_peer(0, fsa_our_uname);
     join_make_offer(NULL, member, NULL);
 
     /* this was a genuine join request, cancel any existing
      * transition and invoke the PE
      */
     start_transition(fsa_state);
 
     /* dont waste time by invoking the pe yet; */
     crm_debug("Waiting on %d outstanding join acks for join-%d",
               g_hash_table_size(welcomed_nodes), current_join_id);
 }
 
 static int
 compare_int_fields(xmlNode * left, xmlNode * right, const char *field)
 {
     const char *elem_l = crm_element_value(left, field);
     const char *elem_r = crm_element_value(right, field);
 
     int int_elem_l = crm_int_helper(elem_l, NULL);
     int int_elem_r = crm_int_helper(elem_r, NULL);
 
     if (int_elem_l < int_elem_r) {
         return -1;
 
     } else if (int_elem_l > int_elem_r) {
         return 1;
     }
 
     return 0;
 }
 
 /*	 A_DC_JOIN_PROCESS_REQ	*/
 void
 do_dc_join_filter_offer(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 *generation = NULL;
 
     int cmp = 0;
     int join_id = -1;
     gboolean ack_nack_bool = TRUE;
     const char *ack_nack = CRMD_JOINSTATE_MEMBER;
     ha_msg_input_t *join_ack = fsa_typed_data(fsa_dt_ha_msg);
 
     const char *join_from = crm_element_value(join_ack->msg, F_CRM_HOST_FROM);
     const char *ref = crm_element_value(join_ack->msg, XML_ATTR_REFERENCE);
 
     crm_node_t *join_node = crm_get_peer(0, join_from);
 
     crm_debug("Processing req from %s", join_from);
 
     generation = join_ack->xml;
     crm_element_value_int(join_ack->msg, F_CRM_JOIN_ID, &join_id);
 
     if (max_generation_xml != NULL && generation != NULL) {
         int lpc = 0;
 
         const char *attributes[] = {
             XML_ATTR_GENERATION_ADMIN,
             XML_ATTR_GENERATION,
             XML_ATTR_NUMUPDATES,
         };
 
         for (lpc = 0; cmp == 0 && lpc < DIMOF(attributes); lpc++) {
             cmp = compare_int_fields(max_generation_xml, generation, attributes[lpc]);
         }
     }
 
     if (join_id != current_join_id) {
         crm_debug("Invalid response from %s: join-%d vs. join-%d",
                   join_from, join_id, current_join_id);
         check_join_state(cur_state, __FUNCTION__);
         return;
 
     } else if (join_node == NULL || crm_is_peer_active(join_node) == FALSE) {
         crm_err("Node %s is not a member", join_from);
         ack_nack_bool = FALSE;
 
     } else if (generation == NULL) {
         crm_err("Generation was NULL");
         ack_nack_bool = FALSE;
 
     } else if (max_generation_xml == NULL) {
         max_generation_xml = copy_xml(generation);
         max_generation_from = strdup(join_from);
 
     } else if (cmp < 0 || (cmp == 0 && safe_str_eq(join_from, fsa_our_uname))) {
         crm_debug("%s has a better generation number than"
                   " the current max %s", join_from, max_generation_from);
         if (max_generation_xml) {
             crm_log_xml_debug(max_generation_xml, "Max generation");
         }
         crm_log_xml_debug(generation, "Their generation");
 
         free(max_generation_from);
         free_xml(max_generation_xml);
 
         max_generation_from = strdup(join_from);
         max_generation_xml = copy_xml(join_ack->xml);
     }
 
     if (ack_nack_bool == FALSE) {
         /* NACK this client */
         ack_nack = CRMD_JOINSTATE_NACK;
         crm_err("join-%d: NACK'ing node %s (ref %s)", join_id, join_from, ref);
     } else {
         crm_debug("join-%d: Welcoming node %s (ref %s)", join_id, join_from, ref);
     }
 
     /* add them to our list of CRMD_STATE_ACTIVE nodes */
     g_hash_table_insert(integrated_nodes, strdup(join_from), strdup(ack_nack));
 
     crm_debug("%u nodes have been integrated into join-%d",
               g_hash_table_size(integrated_nodes), join_id);
 
     g_hash_table_remove(welcomed_nodes, join_from);
 
     if (check_join_state(cur_state, __FUNCTION__) == FALSE) {
         /* dont waste time by invoking the PE yet; */
         crm_debug("join-%d: Still waiting on %d outstanding offers",
                   join_id, g_hash_table_size(welcomed_nodes));
     }
 }
 
 /*	A_DC_JOIN_FINALIZE	*/
 void
 do_dc_join_finalize(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)
 {
     char *sync_from = NULL;
     int rc = pcmk_ok;
 
     /* This we can do straight away and avoid clients timing us out
      *  while we compute the latest CIB
      */
     crm_debug("Finializing join-%d for %d clients",
               current_join_id, g_hash_table_size(integrated_nodes));
     if (g_hash_table_size(integrated_nodes) == 0) {
         /* If we don't even have ourself, start again */
         register_fsa_error_adv(C_FSA_INTERNAL, I_ELECTION_DC, NULL, NULL, __FUNCTION__);
         return;
     }
 
     clear_bit(fsa_input_register, R_HAVE_CIB);
     if (max_generation_from == NULL || safe_str_eq(max_generation_from, fsa_our_uname)) {
         set_bit(fsa_input_register, R_HAVE_CIB);
     }
 
     if (is_set(fsa_input_register, R_IN_TRANSITION)) {
         crm_warn("join-%d: We are still in a transition."
                  "  Delaying until the TE completes.", current_join_id);
         crmd_fsa_stall(NULL);
         return;
     }
 
     if (is_set(fsa_input_register, R_HAVE_CIB) == FALSE) {
         /* ask for the agreed best CIB */
         sync_from = strdup(max_generation_from);
         crm_log_xml_debug(max_generation_xml, "Requesting version");
         set_bit(fsa_input_register, R_CIB_ASKED);
 
     } else {
         /* Send _our_ CIB out to everyone */
         sync_from = strdup(fsa_our_uname);
     }
 
     crm_info("join-%d: Syncing the CIB from %s to the rest of the cluster",
              current_join_id, sync_from);
 
     rc = fsa_cib_conn->cmds->sync_from(fsa_cib_conn, sync_from, NULL, cib_quorum_override);
 
     fsa_cib_conn->cmds->register_callback(fsa_cib_conn, rc, 60, FALSE, sync_from,
                                           "finalize_sync_callback", finalize_sync_callback);
 }
 
 void
 finalize_sync_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
 {
     CRM_LOG_ASSERT(-EPERM != rc);
     clear_bit(fsa_input_register, R_CIB_ASKED);
     if (rc != pcmk_ok) {
         do_crm_log((rc == -pcmk_err_old_data ? LOG_WARNING : LOG_ERR),
                    "Sync from %s failed: %s",
                    (char *)user_data, pcmk_strerror(rc));
 
         /* restart the whole join process */
         register_fsa_error_adv(C_FSA_INTERNAL, I_ELECTION_DC, NULL, NULL, __FUNCTION__);
 
     } else if (AM_I_DC && fsa_state == S_FINALIZE_JOIN) {
         set_bit(fsa_input_register, R_HAVE_CIB);
         clear_bit(fsa_input_register, R_CIB_ASKED);
 
         /* make sure dc_uuid is re-set to us */
         if (check_join_state(fsa_state, __FUNCTION__) == FALSE) {
             crm_debug("Notifying %d clients of join-%d results",
                       g_hash_table_size(integrated_nodes), current_join_id);
             g_hash_table_foreach_remove(integrated_nodes, finalize_join_for, NULL);
         }
 
     } else {
         crm_debug("No longer the DC in S_FINALIZE_JOIN: %s/%s",
                   AM_I_DC ? "DC" : "CRMd", fsa_state2string(fsa_state));
     }
 
     free(user_data);
 }
 
 static void
 join_update_complete_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
 {
     fsa_data_t *msg_data = NULL;
 
     if (rc == pcmk_ok) {
         crm_debug("Join update %d complete", call_id);
         check_join_state(fsa_state, __FUNCTION__);
 
     } else {
         crm_err("Join update %d failed", call_id);
         crm_log_xml_debug(msg, "failed");
         register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
     }
 }
 
 /*	A_DC_JOIN_PROCESS_ACK	*/
 void
 do_dc_join_ack(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 join_id = -1;
     int call_id = 0;
     ha_msg_input_t *join_ack = fsa_typed_data(fsa_dt_ha_msg);
 
     const char *join_id_s = NULL;
     const char *join_state = NULL;
     const char *op = crm_element_value(join_ack->msg, F_CRM_TASK);
     const char *join_from = crm_element_value(join_ack->msg, F_CRM_HOST_FROM);
 
     if (safe_str_neq(op, CRM_OP_JOIN_CONFIRM)) {
         crm_debug("Ignoring op=%s message from %s", op, join_from);
         return;
     }
 
     crm_element_value_int(join_ack->msg, F_CRM_JOIN_ID, &join_id);
     join_id_s = crm_element_value(join_ack->msg, F_CRM_JOIN_ID);
 
     /* now update them to "member" */
 
     crm_trace("Processing ack from %s", join_from);
 
     join_state = (const char *)
         g_hash_table_lookup(finalized_nodes, join_from);
 
     if (join_state == NULL) {
         crm_err("Join not in progress: ignoring join-%d from %s", join_id, join_from);
         return;
 
     } else if (safe_str_neq(join_state, CRMD_JOINSTATE_MEMBER)) {
         crm_err("Node %s wasnt invited to join the cluster", join_from);
         g_hash_table_remove(finalized_nodes, join_from);
         return;
 
     } else if (join_id != current_join_id) {
         crm_err("Invalid response from %s: join-%d vs. join-%d",
                 join_from, join_id, current_join_id);
         g_hash_table_remove(finalized_nodes, join_from);
         return;
     }
 
     g_hash_table_remove(finalized_nodes, join_from);
 
     if (g_hash_table_lookup(confirmed_nodes, join_from) != NULL) {
         crm_err("join-%d: hash already contains confirmation from %s", join_id, join_from);
     }
 
     g_hash_table_insert(confirmed_nodes, strdup(join_from), strdup(join_id_s));
 
     crm_info("join-%d: Updating node state to %s for %s",
              join_id, CRMD_JOINSTATE_MEMBER, join_from);
 
     /* update CIB with the current LRM status from the node
      * We dont need to notify the TE of these updates, a transition will
      *   be started in due time
      */
     erase_status_tag(join_from, XML_CIB_TAG_LRM, cib_scope_local);
     fsa_cib_update(XML_CIB_TAG_STATUS, join_ack->xml,
                    cib_scope_local | cib_quorum_override | cib_can_create, call_id, NULL);
     add_cib_op_callback(fsa_cib_conn, call_id, FALSE, NULL, join_update_complete_callback);
     crm_debug("join-%d: Registered callback for LRM update %d", join_id, call_id);
 }
 
 gboolean
 finalize_join_for(gpointer key, gpointer value, gpointer user_data)
 {
     const char *join_to = NULL;
     const char *join_state = NULL;
     xmlNode *acknak = NULL;
+    xmlNode *tmp1 = NULL;
     crm_node_t *join_node = NULL;
 
     if (key == NULL || value == NULL) {
         return TRUE;
     }
 
     join_to = (const char *)key;
     join_state = (const char *)value;
 
-    /* make sure the node exists in the config section */
-    create_node_entry(join_to, join_to, NORMALNODE);
+    /* make sure a node entry exists for the new node */
+    crm_trace("Creating node entry for %s", join_to);
+
+    tmp1 = create_xml_node(NULL, XML_CIB_TAG_NODE);
+    set_uuid(tmp1, XML_ATTR_UUID, join_to);
+    crm_xml_add(tmp1, XML_ATTR_UNAME, join_to);
+
+    fsa_cib_anon_update(XML_CIB_TAG_NODES, tmp1, cib_scope_local | cib_quorum_override | cib_can_create);
+    free_xml(tmp1);
 
     join_node = crm_get_peer(0, join_to);
     if (crm_is_peer_active(join_node) == FALSE) {
         /*
          * NACK'ing nodes that the membership layer doesn't know about yet
          * simply creates more churn
          *
          * Better to leave them waiting and let the join restart when
          * the new membership event comes in
          *
          * All other NACKs (due to versions etc) should still be processed
          */
         return TRUE;
     }
 
     /* send the ack/nack to the node */
     acknak = create_request(CRM_OP_JOIN_ACKNAK, NULL, join_to,
                             CRM_SYSTEM_CRMD, CRM_SYSTEM_DC, NULL);
     crm_xml_add_int(acknak, F_CRM_JOIN_ID, current_join_id);
 
     /* set the ack/nack */
     if (safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) {
         crm_debug("join-%d: ACK'ing join request from %s, state %s",
                   current_join_id, join_to, join_state);
         crm_xml_add(acknak, CRM_OP_JOIN_ACKNAK, XML_BOOLEAN_TRUE);
         g_hash_table_insert(finalized_nodes,
                             strdup(join_to), strdup(CRMD_JOINSTATE_MEMBER));
     } else {
         crm_warn("join-%d: NACK'ing join request from %s, state %s",
                  current_join_id, join_to, join_state);
 
         crm_xml_add(acknak, CRM_OP_JOIN_ACKNAK, XML_BOOLEAN_FALSE);
     }
 
     send_cluster_message(join_to, crm_msg_crmd, acknak, TRUE);
     free_xml(acknak);
     return TRUE;
 }
 
 void ghash_print_node(gpointer key, gpointer value, gpointer user_data);
 
 gboolean
 check_join_state(enum crmd_fsa_state cur_state, const char *source)
 {
     crm_debug("Invoked by %s in state: %s", source, fsa_state2string(cur_state));
 
     if (saved_ccm_membership_id != crm_peer_seq) {
         crm_debug("%s: Membership changed since join started: %llu -> %llu",
                  source, saved_ccm_membership_id, crm_peer_seq);
         register_fsa_input_before(C_FSA_INTERNAL, I_NODE_JOIN, NULL);
 
     } else if (cur_state == S_INTEGRATION) {
         if (g_hash_table_size(welcomed_nodes) == 0) {
             crm_debug("join-%d: Integration of %d peers complete: %s",
                       current_join_id, g_hash_table_size(integrated_nodes), source);
             register_fsa_input_before(C_FSA_INTERNAL, I_INTEGRATED, NULL);
             return TRUE;
         }
 
     } else if (cur_state == S_FINALIZE_JOIN) {
         if (is_set(fsa_input_register, R_HAVE_CIB) == FALSE) {
             crm_debug("join-%d: Delaying I_FINALIZED until we have the CIB", current_join_id);
             return TRUE;
 
         } else if (g_hash_table_size(integrated_nodes) == 0
                    && g_hash_table_size(finalized_nodes) == 0) {
             crm_debug("join-%d complete: %s", current_join_id, source);
             register_fsa_input_later(C_FSA_INTERNAL, I_FINALIZED, NULL);
 
         } else if (g_hash_table_size(integrated_nodes) != 0
                    && g_hash_table_size(finalized_nodes) != 0) {
             char *msg = NULL;
 
             crm_err("join-%d: Waiting on %d integrated nodes"
                     " AND %d finalized nodes",
                     current_join_id,
                     g_hash_table_size(integrated_nodes), g_hash_table_size(finalized_nodes));
             msg = strdup("Integrated node");
             g_hash_table_foreach(integrated_nodes, ghash_print_node, msg);
             free(msg);
 
             msg = strdup("Finalized node");
             g_hash_table_foreach(finalized_nodes, ghash_print_node, msg);
             free(msg);
 
         } else if (g_hash_table_size(integrated_nodes) != 0) {
             crm_debug("join-%d: Still waiting on %d integrated nodes",
                       current_join_id, g_hash_table_size(integrated_nodes));
 
         } else if (g_hash_table_size(finalized_nodes) != 0) {
             crm_debug("join-%d: Still waiting on %d finalized nodes",
                       current_join_id, g_hash_table_size(finalized_nodes));
         }
     }
 
     return FALSE;
 }
 
 void
 do_dc_join_final(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_debug("Ensuring DC, quorum and node attributes are up-to-date");
     update_attrd(NULL, NULL, NULL, NULL);
     crm_update_quorum(crm_have_quorum, TRUE);
 }
diff --git a/crmd/utils.c b/crmd/utils.c
index 2b98f2993a..a42ae37a96 100644
--- a/crmd/utils.c
+++ b/crmd/utils.c
@@ -1,1184 +1,1158 @@
 /* 
  * 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 <sys/types.h>
 #include <sys/wait.h>
 #include <signal.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/attrd.h>
 
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 
 #include <crm/cluster.h>
 
 #include <crmd_fsa.h>
 #include <crmd_utils.h>
 #include <crmd_messages.h>
 
 /*	A_DC_TIMER_STOP, A_DC_TIMER_START,
  *	A_FINALIZE_TIMER_STOP, A_FINALIZE_TIMER_START
  *	A_INTEGRATE_TIMER_STOP, A_INTEGRATE_TIMER_START
  */
 void
 do_timer_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 timer_op_ok = TRUE;
 
     if (action & A_DC_TIMER_STOP) {
         timer_op_ok = crm_timer_stop(election_trigger);
 
     } else if (action & A_FINALIZE_TIMER_STOP) {
         timer_op_ok = crm_timer_stop(finalization_timer);
 
     } else if (action & A_INTEGRATE_TIMER_STOP) {
         timer_op_ok = crm_timer_stop(integration_timer);
 
 /* 	} else if(action & A_ELECTION_TIMEOUT_STOP) { */
 /* 		timer_op_ok = crm_timer_stop(election_timeout); */
     }
 
     /* dont start a timer that wasnt already running */
     if (action & A_DC_TIMER_START && timer_op_ok) {
         crm_timer_start(election_trigger);
         if (AM_I_DC) {
             /* there can be only one */
             register_fsa_input(cause, I_ELECTION, NULL);
         }
 
     } else if (action & A_FINALIZE_TIMER_START) {
         crm_timer_start(finalization_timer);
 
     } else if (action & A_INTEGRATE_TIMER_START) {
         crm_timer_start(integration_timer);
 
 /* 	} else if(action & A_ELECTION_TIMEOUT_START) { */
 /* 		crm_timer_start(election_timeout); */
     }
 }
 
 const char *
 get_timer_desc(fsa_timer_t * timer)
 {
     if (timer == election_trigger) {
         return "Election Trigger";
 
     } else if (timer == election_timeout) {
         return "Election Timeout";
 
     } else if (timer == shutdown_escalation_timer) {
         return "Shutdown Escalation";
 
     } else if (timer == integration_timer) {
         return "Integration Timer";
 
     } else if (timer == finalization_timer) {
         return "Finalization Timer";
 
     } else if (timer == transition_timer) {
         return "New Transition Timer";
 
     } else if (timer == wait_timer) {
         return "Wait Timer";
 
     } else if (timer == recheck_timer) {
         return "PEngine Recheck Timer";
 
     }
     return "Unknown Timer";
 }
 
 gboolean
 crm_timer_popped(gpointer data)
 {
     fsa_timer_t *timer = (fsa_timer_t *) data;
 
     if (timer == wait_timer
         || timer == recheck_timer
         || timer == transition_timer || timer == finalization_timer || timer == election_trigger) {
         crm_info("%s (%s) just popped (%dms)",
                  get_timer_desc(timer), fsa_input2string(timer->fsa_input), timer->period_ms);
         timer->counter++;
 
     } else {
         crm_err("%s (%s) just popped in state %s! (%dms)",
                 get_timer_desc(timer), fsa_input2string(timer->fsa_input),
                 fsa_state2string(fsa_state), timer->period_ms);
     }
 
     if(timer == election_trigger && election_trigger->counter > 5) {
         crm_notice("We appear to be in an election loop, something may be wrong");
         election_trigger->counter = 0;
     }
 
     if (timer->repeat == FALSE) {
         crm_timer_stop(timer);  /* make it _not_ go off again */
     }
 
     if (timer->fsa_input == I_INTEGRATED) {
         crm_info("Welcomed: %d, Integrated: %d",
                  g_hash_table_size(welcomed_nodes), g_hash_table_size(integrated_nodes));
         if (g_hash_table_size(welcomed_nodes) == 0) {
             /* If we don't even have ourself, start again */
             register_fsa_error_adv(C_FSA_INTERNAL, I_ELECTION, NULL, NULL, __FUNCTION__);
 
         } else {
             register_fsa_input_before(C_TIMER_POPPED, timer->fsa_input, NULL);
         }
 
     } else if (timer == recheck_timer && fsa_state != S_IDLE) {
         crm_debug("Discarding %s event in state: %s",
                   fsa_input2string(timer->fsa_input), fsa_state2string(fsa_state));
 
     } else if (timer == finalization_timer && fsa_state != S_FINALIZE_JOIN) {
         crm_debug("Discarding %s event in state: %s",
                   fsa_input2string(timer->fsa_input), fsa_state2string(fsa_state));
 
     } else if (timer->fsa_input != I_NULL) {
         register_fsa_input(C_TIMER_POPPED, timer->fsa_input, NULL);
     }
 
     crm_trace("Triggering FSA: %s", __FUNCTION__);
     mainloop_set_trigger(fsa_source);
 
     return TRUE;
 }
 
 gboolean 
 is_timer_started(fsa_timer_t *timer)
 {
     if (timer->period_ms > 0) {
         if(transition_timer->source_id == 0) {
             return FALSE;
         } else {
             return TRUE;
         }
     }
     return FALSE;
 }
 
 gboolean
 crm_timer_start(fsa_timer_t * timer)
 {
     const char *timer_desc = get_timer_desc(timer);
 
     if (timer->source_id == 0 && timer->period_ms > 0) {
         timer->source_id = g_timeout_add(timer->period_ms, timer->callback, (void *)timer);
         CRM_ASSERT(timer->source_id != 0);
         crm_debug("Started %s (%s:%dms), src=%d",
                   timer_desc, fsa_input2string(timer->fsa_input),
                   timer->period_ms, timer->source_id);
 
     } else if (timer->period_ms < 0) {
         crm_err("Tried to start %s (%s:%dms) with a -ve period",
                 timer_desc, fsa_input2string(timer->fsa_input), timer->period_ms);
 
     } else {
         crm_debug("%s (%s:%dms) already running: src=%d",
                   timer_desc, fsa_input2string(timer->fsa_input),
                   timer->period_ms, timer->source_id);
         return FALSE;
     }
     return TRUE;
 }
 
 gboolean
 crm_timer_stop(fsa_timer_t * timer)
 {
     const char *timer_desc = get_timer_desc(timer);
 
     if (timer == NULL) {
         crm_err("Attempted to stop NULL timer");
         return FALSE;
 
     } else if (timer->source_id != 0) {
         crm_trace("Stopping %s (%s:%dms), src=%d",
                     timer_desc, fsa_input2string(timer->fsa_input),
                     timer->period_ms, timer->source_id);
         g_source_remove(timer->source_id);
         timer->source_id = 0;
 
     } else {
         crm_trace("%s (%s:%dms) already stopped",
                     timer_desc, fsa_input2string(timer->fsa_input), timer->period_ms);
         return FALSE;
     }
     return TRUE;
 }
 
 const char *
 fsa_input2string(enum crmd_fsa_input input)
 {
     const char *inputAsText = NULL;
 
     switch (input) {
         case I_NULL:
             inputAsText = "I_NULL";
             break;
         case I_CIB_OP:
             inputAsText = "I_CIB_OP (unused)";
             break;
         case I_CIB_UPDATE:
             inputAsText = "I_CIB_UPDATE";
             break;
         case I_DC_TIMEOUT:
             inputAsText = "I_DC_TIMEOUT";
             break;
         case I_ELECTION:
             inputAsText = "I_ELECTION";
             break;
         case I_PE_CALC:
             inputAsText = "I_PE_CALC";
             break;
         case I_RELEASE_DC:
             inputAsText = "I_RELEASE_DC";
             break;
         case I_ELECTION_DC:
             inputAsText = "I_ELECTION_DC";
             break;
         case I_ERROR:
             inputAsText = "I_ERROR";
             break;
         case I_FAIL:
             inputAsText = "I_FAIL";
             break;
         case I_INTEGRATED:
             inputAsText = "I_INTEGRATED";
             break;
         case I_FINALIZED:
             inputAsText = "I_FINALIZED";
             break;
         case I_NODE_JOIN:
             inputAsText = "I_NODE_JOIN";
             break;
         case I_JOIN_OFFER:
             inputAsText = "I_JOIN_OFFER";
             break;
         case I_JOIN_REQUEST:
             inputAsText = "I_JOIN_REQUEST";
             break;
         case I_JOIN_RESULT:
             inputAsText = "I_JOIN_RESULT";
             break;
         case I_NOT_DC:
             inputAsText = "I_NOT_DC";
             break;
         case I_RECOVERED:
             inputAsText = "I_RECOVERED";
             break;
         case I_RELEASE_FAIL:
             inputAsText = "I_RELEASE_FAIL";
             break;
         case I_RELEASE_SUCCESS:
             inputAsText = "I_RELEASE_SUCCESS";
             break;
         case I_RESTART:
             inputAsText = "I_RESTART";
             break;
         case I_PE_SUCCESS:
             inputAsText = "I_PE_SUCCESS";
             break;
         case I_ROUTER:
             inputAsText = "I_ROUTER";
             break;
         case I_SHUTDOWN:
             inputAsText = "I_SHUTDOWN";
             break;
         case I_STARTUP:
             inputAsText = "I_STARTUP";
             break;
         case I_TE_SUCCESS:
             inputAsText = "I_TE_SUCCESS";
             break;
         case I_STOP:
             inputAsText = "I_STOP";
             break;
         case I_DC_HEARTBEAT:
             inputAsText = "I_DC_HEARTBEAT";
             break;
         case I_WAIT_FOR_EVENT:
             inputAsText = "I_WAIT_FOR_EVENT";
             break;
         case I_LRM_EVENT:
             inputAsText = "I_LRM_EVENT";
             break;
         case I_PENDING:
             inputAsText = "I_PENDING";
             break;
         case I_HALT:
             inputAsText = "I_HALT";
             break;
         case I_TERMINATE:
             inputAsText = "I_TERMINATE";
             break;
         case I_ILLEGAL:
             inputAsText = "I_ILLEGAL";
             break;
     }
 
     if (inputAsText == NULL) {
         crm_err("Input %d is unknown", input);
         inputAsText = "<UNKNOWN_INPUT>";
     }
 
     return inputAsText;
 }
 
 const char *
 fsa_state2string(enum crmd_fsa_state state)
 {
     const char *stateAsText = NULL;
 
     switch (state) {
         case S_IDLE:
             stateAsText = "S_IDLE";
             break;
         case S_ELECTION:
             stateAsText = "S_ELECTION";
             break;
         case S_INTEGRATION:
             stateAsText = "S_INTEGRATION";
             break;
         case S_FINALIZE_JOIN:
             stateAsText = "S_FINALIZE_JOIN";
             break;
         case S_NOT_DC:
             stateAsText = "S_NOT_DC";
             break;
         case S_POLICY_ENGINE:
             stateAsText = "S_POLICY_ENGINE";
             break;
         case S_RECOVERY:
             stateAsText = "S_RECOVERY";
             break;
         case S_RELEASE_DC:
             stateAsText = "S_RELEASE_DC";
             break;
         case S_PENDING:
             stateAsText = "S_PENDING";
             break;
         case S_STOPPING:
             stateAsText = "S_STOPPING";
             break;
         case S_TERMINATE:
             stateAsText = "S_TERMINATE";
             break;
         case S_TRANSITION_ENGINE:
             stateAsText = "S_TRANSITION_ENGINE";
             break;
         case S_STARTING:
             stateAsText = "S_STARTING";
             break;
         case S_HALT:
             stateAsText = "S_HALT";
             break;
         case S_ILLEGAL:
             stateAsText = "S_ILLEGAL";
             break;
     }
 
     if (stateAsText == NULL) {
         crm_err("State %d is unknown", state);
         stateAsText = "<UNKNOWN_STATE>";
     }
 
     return stateAsText;
 }
 
 const char *
 fsa_cause2string(enum crmd_fsa_cause cause)
 {
     const char *causeAsText = NULL;
 
     switch (cause) {
         case C_UNKNOWN:
             causeAsText = "C_UNKNOWN";
             break;
         case C_STARTUP:
             causeAsText = "C_STARTUP";
             break;
         case C_IPC_MESSAGE:
             causeAsText = "C_IPC_MESSAGE";
             break;
         case C_HA_MESSAGE:
             causeAsText = "C_HA_MESSAGE";
             break;
         case C_CCM_CALLBACK:
             causeAsText = "C_CCM_CALLBACK";
             break;
         case C_TIMER_POPPED:
             causeAsText = "C_TIMER_POPPED";
             break;
         case C_SHUTDOWN:
             causeAsText = "C_SHUTDOWN";
             break;
         case C_HEARTBEAT_FAILED:
             causeAsText = "C_HEARTBEAT_FAILED";
             break;
         case C_SUBSYSTEM_CONNECT:
             causeAsText = "C_SUBSYSTEM_CONNECT";
             break;
         case C_LRM_OP_CALLBACK:
             causeAsText = "C_LRM_OP_CALLBACK";
             break;
         case C_LRM_MONITOR_CALLBACK:
             causeAsText = "C_LRM_MONITOR_CALLBACK";
             break;
         case C_CRMD_STATUS_CALLBACK:
             causeAsText = "C_CRMD_STATUS_CALLBACK";
             break;
         case C_HA_DISCONNECT:
             causeAsText = "C_HA_DISCONNECT";
             break;
         case C_FSA_INTERNAL:
             causeAsText = "C_FSA_INTERNAL";
             break;
         case C_ILLEGAL:
             causeAsText = "C_ILLEGAL";
             break;
     }
 
     if (causeAsText == NULL) {
         crm_err("Cause %d is unknown", cause);
         causeAsText = "<UNKNOWN_CAUSE>";
     }
 
     return causeAsText;
 }
 
 const char *
 fsa_action2string(long long action)
 {
     const char *actionAsText = NULL;
 
     switch (action) {
 
         case A_NOTHING:
             actionAsText = "A_NOTHING";
             break;
         case A_ELECTION_START:
             actionAsText = "A_ELECTION_START";
             break;
         case A_DC_JOIN_FINAL:
             actionAsText = "A_DC_JOIN_FINAL";
             break;
         case A_READCONFIG:
             actionAsText = "A_READCONFIG";
             break;
         case O_RELEASE:
             actionAsText = "O_RELEASE";
             break;
         case A_STARTUP:
             actionAsText = "A_STARTUP";
             break;
         case A_STARTED:
             actionAsText = "A_STARTED";
             break;
         case A_HA_CONNECT:
             actionAsText = "A_HA_CONNECT";
             break;
         case A_HA_DISCONNECT:
             actionAsText = "A_HA_DISCONNECT";
             break;
         case A_LRM_CONNECT:
             actionAsText = "A_LRM_CONNECT";
             break;
         case A_LRM_EVENT:
             actionAsText = "A_LRM_EVENT";
             break;
         case A_LRM_INVOKE:
             actionAsText = "A_LRM_INVOKE";
             break;
         case A_LRM_DISCONNECT:
             actionAsText = "A_LRM_DISCONNECT";
             break;
         case O_LRM_RECONNECT:
             actionAsText = "O_LRM_RECONNECT";
             break;
         case A_CL_JOIN_QUERY:
             actionAsText = "A_CL_JOIN_QUERY";
             break;
         case A_DC_TIMER_STOP:
             actionAsText = "A_DC_TIMER_STOP";
             break;
         case A_DC_TIMER_START:
             actionAsText = "A_DC_TIMER_START";
             break;
         case A_INTEGRATE_TIMER_START:
             actionAsText = "A_INTEGRATE_TIMER_START";
             break;
         case A_INTEGRATE_TIMER_STOP:
             actionAsText = "A_INTEGRATE_TIMER_STOP";
             break;
         case A_FINALIZE_TIMER_START:
             actionAsText = "A_FINALIZE_TIMER_START";
             break;
         case A_FINALIZE_TIMER_STOP:
             actionAsText = "A_FINALIZE_TIMER_STOP";
             break;
         case A_ELECTION_COUNT:
             actionAsText = "A_ELECTION_COUNT";
             break;
         case A_ELECTION_VOTE:
             actionAsText = "A_ELECTION_VOTE";
             break;
         case A_ELECTION_CHECK:
             actionAsText = "A_ELECTION_CHECK";
             break;
         case A_CL_JOIN_ANNOUNCE:
             actionAsText = "A_CL_JOIN_ANNOUNCE";
             break;
         case A_CL_JOIN_REQUEST:
             actionAsText = "A_CL_JOIN_REQUEST";
             break;
         case A_CL_JOIN_RESULT:
             actionAsText = "A_CL_JOIN_RESULT";
             break;
         case A_DC_JOIN_OFFER_ALL:
             actionAsText = "A_DC_JOIN_OFFER_ALL";
             break;
         case A_DC_JOIN_OFFER_ONE:
             actionAsText = "A_DC_JOIN_OFFER_ONE";
             break;
         case A_DC_JOIN_PROCESS_REQ:
             actionAsText = "A_DC_JOIN_PROCESS_REQ";
             break;
         case A_DC_JOIN_PROCESS_ACK:
             actionAsText = "A_DC_JOIN_PROCESS_ACK";
             break;
         case A_DC_JOIN_FINALIZE:
             actionAsText = "A_DC_JOIN_FINALIZE";
             break;
         case A_MSG_PROCESS:
             actionAsText = "A_MSG_PROCESS";
             break;
         case A_MSG_ROUTE:
             actionAsText = "A_MSG_ROUTE";
             break;
         case A_RECOVER:
             actionAsText = "A_RECOVER";
             break;
         case A_DC_RELEASE:
             actionAsText = "A_DC_RELEASE";
             break;
         case A_DC_RELEASED:
             actionAsText = "A_DC_RELEASED";
             break;
         case A_DC_TAKEOVER:
             actionAsText = "A_DC_TAKEOVER";
             break;
         case A_SHUTDOWN:
             actionAsText = "A_SHUTDOWN";
             break;
         case A_SHUTDOWN_REQ:
             actionAsText = "A_SHUTDOWN_REQ";
             break;
         case A_STOP:
             actionAsText = "A_STOP  ";
             break;
         case A_EXIT_0:
             actionAsText = "A_EXIT_0";
             break;
         case A_EXIT_1:
             actionAsText = "A_EXIT_1";
             break;
         case A_CCM_CONNECT:
             actionAsText = "A_CCM_CONNECT";
             break;
         case A_CCM_DISCONNECT:
             actionAsText = "A_CCM_DISCONNECT";
             break;
         case O_CIB_RESTART:
             actionAsText = "O_CIB_RESTART";
             break;
         case A_CIB_START:
             actionAsText = "A_CIB_START";
             break;
         case A_CIB_STOP:
             actionAsText = "A_CIB_STOP";
             break;
         case A_TE_INVOKE:
             actionAsText = "A_TE_INVOKE";
             break;
         case O_TE_RESTART:
             actionAsText = "O_TE_RESTART";
             break;
         case A_TE_START:
             actionAsText = "A_TE_START";
             break;
         case A_TE_STOP:
             actionAsText = "A_TE_STOP";
             break;
         case A_TE_HALT:
             actionAsText = "A_TE_HALT";
             break;
         case A_TE_CANCEL:
             actionAsText = "A_TE_CANCEL";
             break;
         case A_PE_INVOKE:
             actionAsText = "A_PE_INVOKE";
             break;
         case O_PE_RESTART:
             actionAsText = "O_PE_RESTART";
             break;
         case A_PE_START:
             actionAsText = "A_PE_START";
             break;
         case A_PE_STOP:
             actionAsText = "A_PE_STOP";
             break;
         case A_NODE_BLOCK:
             actionAsText = "A_NODE_BLOCK";
             break;
         case A_UPDATE_NODESTATUS:
             actionAsText = "A_UPDATE_NODESTATUS";
             break;
         case A_LOG:
             actionAsText = "A_LOG   ";
             break;
         case A_ERROR:
             actionAsText = "A_ERROR ";
             break;
         case A_WARN:
             actionAsText = "A_WARN  ";
             break;
             /* Composite actions */
         case A_DC_TIMER_START | A_CL_JOIN_QUERY:
             actionAsText = "A_DC_TIMER_START|A_CL_JOIN_QUERY";
             break;
     }
 
     if (actionAsText == NULL) {
         crm_err("Action %.16llx is unknown", action);
         actionAsText = "<UNKNOWN_ACTION>";
     }
 
     return actionAsText;
 }
 
 void
 fsa_dump_inputs(int log_level, const char *text, long long input_register)
 {
     if (input_register == A_NOTHING) {
         return;
     }
     if (text == NULL) {
         text = "Input register contents:";
     }
 
     if (is_set(input_register, R_THE_DC)) {
         crm_trace( "%s %.16llx (R_THE_DC)", text, R_THE_DC);
     }
     if (is_set(input_register, R_STARTING)) {
         crm_trace( "%s %.16llx (R_STARTING)", text, R_STARTING);
     }
     if (is_set(input_register, R_SHUTDOWN)) {
         crm_trace( "%s %.16llx (R_SHUTDOWN)", text, R_SHUTDOWN);
     }
     if (is_set(input_register, R_STAYDOWN)) {
         crm_trace( "%s %.16llx (R_STAYDOWN)", text, R_STAYDOWN);
     }
     if (is_set(input_register, R_JOIN_OK)) {
         crm_trace( "%s %.16llx (R_JOIN_OK)", text, R_JOIN_OK);
     }
     if (is_set(input_register, R_READ_CONFIG)) {
         crm_trace( "%s %.16llx (R_READ_CONFIG)", text, R_READ_CONFIG);
     }
     if (is_set(input_register, R_INVOKE_PE)) {
         crm_trace( "%s %.16llx (R_INVOKE_PE)", text, R_INVOKE_PE);
     }
     if (is_set(input_register, R_CIB_CONNECTED)) {
         crm_trace( "%s %.16llx (R_CIB_CONNECTED)", text, R_CIB_CONNECTED);
     }
     if (is_set(input_register, R_PE_CONNECTED)) {
         crm_trace( "%s %.16llx (R_PE_CONNECTED)", text, R_PE_CONNECTED);
     }
     if (is_set(input_register, R_TE_CONNECTED)) {
         crm_trace( "%s %.16llx (R_TE_CONNECTED)", text, R_TE_CONNECTED);
     }
     if (is_set(input_register, R_LRM_CONNECTED)) {
         crm_trace( "%s %.16llx (R_LRM_CONNECTED)", text, R_LRM_CONNECTED);
     }
     if (is_set(input_register, R_CIB_REQUIRED)) {
         crm_trace( "%s %.16llx (R_CIB_REQUIRED)", text, R_CIB_REQUIRED);
     }
     if (is_set(input_register, R_PE_REQUIRED)) {
         crm_trace( "%s %.16llx (R_PE_REQUIRED)", text, R_PE_REQUIRED);
     }
     if (is_set(input_register, R_TE_REQUIRED)) {
         crm_trace( "%s %.16llx (R_TE_REQUIRED)", text, R_TE_REQUIRED);
     }
     if (is_set(input_register, R_REQ_PEND)) {
         crm_trace( "%s %.16llx (R_REQ_PEND)", text, R_REQ_PEND);
     }
     if (is_set(input_register, R_PE_PEND)) {
         crm_trace( "%s %.16llx (R_PE_PEND)", text, R_PE_PEND);
     }
     if (is_set(input_register, R_TE_PEND)) {
         crm_trace( "%s %.16llx (R_TE_PEND)", text, R_TE_PEND);
     }
     if (is_set(input_register, R_RESP_PEND)) {
         crm_trace( "%s %.16llx (R_RESP_PEND)", text, R_RESP_PEND);
     }
     if (is_set(input_register, R_CIB_DONE)) {
         crm_trace( "%s %.16llx (R_CIB_DONE)", text, R_CIB_DONE);
     }
     if (is_set(input_register, R_HAVE_CIB)) {
         crm_trace( "%s %.16llx (R_HAVE_CIB)", text, R_HAVE_CIB);
     }
     if (is_set(input_register, R_CIB_ASKED)) {
         crm_trace( "%s %.16llx (R_CIB_ASKED)", text, R_CIB_ASKED);
     }
     if (is_set(input_register, R_MEMBERSHIP)) {
         crm_trace( "%s %.16llx (R_MEMBERSHIP)", text, R_MEMBERSHIP);
     }
     if (is_set(input_register, R_PEER_DATA)) {
         crm_trace( "%s %.16llx (R_PEER_DATA)", text, R_PEER_DATA);
     }
     if (is_set(input_register, R_IN_RECOVERY)) {
         crm_trace( "%s %.16llx (R_IN_RECOVERY)", text, R_IN_RECOVERY);
     }
 }
 
 void
 fsa_dump_actions(long long action, const char *text)
 {
     if (is_set(action, A_READCONFIG)) {
         crm_trace( "Action %.16llx (A_READCONFIG) %s", A_READCONFIG, text);
     }
     if (is_set(action, A_STARTUP)) {
         crm_trace( "Action %.16llx (A_STARTUP) %s", A_STARTUP, text);
     }
     if (is_set(action, A_STARTED)) {
         crm_trace( "Action %.16llx (A_STARTED) %s", A_STARTED, text);
     }
     if (is_set(action, A_HA_CONNECT)) {
         crm_trace( "Action %.16llx (A_CONNECT) %s", A_HA_CONNECT, text);
     }
     if (is_set(action, A_HA_DISCONNECT)) {
         crm_trace( "Action %.16llx (A_DISCONNECT) %s", A_HA_DISCONNECT, text);
     }
     if (is_set(action, A_LRM_CONNECT)) {
         crm_trace( "Action %.16llx (A_LRM_CONNECT) %s", A_LRM_CONNECT, text);
     }
     if (is_set(action, A_LRM_EVENT)) {
         crm_trace( "Action %.16llx (A_LRM_EVENT) %s", A_LRM_EVENT, text);
     }
     if (is_set(action, A_LRM_INVOKE)) {
         crm_trace( "Action %.16llx (A_LRM_INVOKE) %s", A_LRM_INVOKE, text);
     }
     if (is_set(action, A_LRM_DISCONNECT)) {
         crm_trace(
                             "Action %.16llx (A_LRM_DISCONNECT) %s", A_LRM_DISCONNECT, text);
     }
     if (is_set(action, A_DC_TIMER_STOP)) {
         crm_trace(
                             "Action %.16llx (A_DC_TIMER_STOP) %s", A_DC_TIMER_STOP, text);
     }
     if (is_set(action, A_DC_TIMER_START)) {
         crm_trace(
                             "Action %.16llx (A_DC_TIMER_START) %s", A_DC_TIMER_START, text);
     }
     if (is_set(action, A_INTEGRATE_TIMER_START)) {
         crm_trace(
                             "Action %.16llx (A_INTEGRATE_TIMER_START) %s",
                             A_INTEGRATE_TIMER_START, text);
     }
     if (is_set(action, A_INTEGRATE_TIMER_STOP)) {
         crm_trace(
                             "Action %.16llx (A_INTEGRATE_TIMER_STOP) %s",
                             A_INTEGRATE_TIMER_STOP, text);
     }
     if (is_set(action, A_FINALIZE_TIMER_START)) {
         crm_trace(
                             "Action %.16llx (A_FINALIZE_TIMER_START) %s",
                             A_FINALIZE_TIMER_START, text);
     }
     if (is_set(action, A_FINALIZE_TIMER_STOP)) {
         crm_trace(
                             "Action %.16llx (A_FINALIZE_TIMER_STOP) %s",
                             A_FINALIZE_TIMER_STOP, text);
     }
     if (is_set(action, A_ELECTION_COUNT)) {
         crm_trace(
                             "Action %.16llx (A_ELECTION_COUNT) %s", A_ELECTION_COUNT, text);
     }
     if (is_set(action, A_ELECTION_VOTE)) {
         crm_trace(
                             "Action %.16llx (A_ELECTION_VOTE) %s", A_ELECTION_VOTE, text);
     }
     if (is_set(action, A_ELECTION_CHECK)) {
         crm_trace(
                             "Action %.16llx (A_ELECTION_CHECK) %s", A_ELECTION_CHECK, text);
     }
     if (is_set(action, A_CL_JOIN_ANNOUNCE)) {
         crm_trace(
                             "Action %.16llx (A_CL_JOIN_ANNOUNCE) %s", A_CL_JOIN_ANNOUNCE, text);
     }
     if (is_set(action, A_CL_JOIN_REQUEST)) {
         crm_trace(
                             "Action %.16llx (A_CL_JOIN_REQUEST) %s", A_CL_JOIN_REQUEST, text);
     }
     if (is_set(action, A_CL_JOIN_RESULT)) {
         crm_trace(
                             "Action %.16llx (A_CL_JOIN_RESULT) %s", A_CL_JOIN_RESULT, text);
     }
     if (is_set(action, A_DC_JOIN_OFFER_ALL)) {
         crm_trace(
                             "Action %.16llx (A_DC_JOIN_OFFER_ALL) %s", A_DC_JOIN_OFFER_ALL, text);
     }
     if (is_set(action, A_DC_JOIN_OFFER_ONE)) {
         crm_trace(
                             "Action %.16llx (A_DC_JOIN_OFFER_ONE) %s", A_DC_JOIN_OFFER_ONE, text);
     }
     if (is_set(action, A_DC_JOIN_PROCESS_REQ)) {
         crm_trace(
                             "Action %.16llx (A_DC_JOIN_PROCESS_REQ) %s",
                             A_DC_JOIN_PROCESS_REQ, text);
     }
     if (is_set(action, A_DC_JOIN_PROCESS_ACK)) {
         crm_trace(
                             "Action %.16llx (A_DC_JOIN_PROCESS_ACK) %s",
                             A_DC_JOIN_PROCESS_ACK, text);
     }
     if (is_set(action, A_DC_JOIN_FINALIZE)) {
         crm_trace(
                             "Action %.16llx (A_DC_JOIN_FINALIZE) %s", A_DC_JOIN_FINALIZE, text);
     }
     if (is_set(action, A_MSG_PROCESS)) {
         crm_trace( "Action %.16llx (A_MSG_PROCESS) %s", A_MSG_PROCESS, text);
     }
     if (is_set(action, A_MSG_ROUTE)) {
         crm_trace( "Action %.16llx (A_MSG_ROUTE) %s", A_MSG_ROUTE, text);
     }
     if (is_set(action, A_RECOVER)) {
         crm_trace( "Action %.16llx (A_RECOVER) %s", A_RECOVER, text);
     }
     if (is_set(action, A_DC_RELEASE)) {
         crm_trace( "Action %.16llx (A_DC_RELEASE) %s", A_DC_RELEASE, text);
     }
     if (is_set(action, A_DC_RELEASED)) {
         crm_trace( "Action %.16llx (A_DC_RELEASED) %s", A_DC_RELEASED, text);
     }
     if (is_set(action, A_DC_TAKEOVER)) {
         crm_trace( "Action %.16llx (A_DC_TAKEOVER) %s", A_DC_TAKEOVER, text);
     }
     if (is_set(action, A_SHUTDOWN)) {
         crm_trace( "Action %.16llx (A_SHUTDOWN) %s", A_SHUTDOWN, text);
     }
     if (is_set(action, A_SHUTDOWN_REQ)) {
         crm_trace( "Action %.16llx (A_SHUTDOWN_REQ) %s", A_SHUTDOWN_REQ, text);
     }
     if (is_set(action, A_STOP)) {
         crm_trace( "Action %.16llx (A_STOP  ) %s", A_STOP, text);
     }
     if (is_set(action, A_EXIT_0)) {
         crm_trace( "Action %.16llx (A_EXIT_0) %s", A_EXIT_0, text);
     }
     if (is_set(action, A_EXIT_1)) {
         crm_trace( "Action %.16llx (A_EXIT_1) %s", A_EXIT_1, text);
     }
     if (is_set(action, A_CCM_CONNECT)) {
         crm_trace( "Action %.16llx (A_CCM_CONNECT) %s", A_CCM_CONNECT, text);
     }
     if (is_set(action, A_CCM_DISCONNECT)) {
         crm_trace(
                             "Action %.16llx (A_CCM_DISCONNECT) %s", A_CCM_DISCONNECT, text);
     }
     if (is_set(action, A_CIB_START)) {
         crm_trace( "Action %.16llx (A_CIB_START) %s", A_CIB_START, text);
     }
     if (is_set(action, A_CIB_STOP)) {
         crm_trace( "Action %.16llx (A_CIB_STOP) %s", A_CIB_STOP, text);
     }
     if (is_set(action, A_TE_INVOKE)) {
         crm_trace( "Action %.16llx (A_TE_INVOKE) %s", A_TE_INVOKE, text);
     }
     if (is_set(action, A_TE_START)) {
         crm_trace( "Action %.16llx (A_TE_START) %s", A_TE_START, text);
     }
     if (is_set(action, A_TE_STOP)) {
         crm_trace( "Action %.16llx (A_TE_STOP) %s", A_TE_STOP, text);
     }
     if (is_set(action, A_TE_CANCEL)) {
         crm_trace( "Action %.16llx (A_TE_CANCEL) %s", A_TE_CANCEL, text);
     }
     if (is_set(action, A_PE_INVOKE)) {
         crm_trace( "Action %.16llx (A_PE_INVOKE) %s", A_PE_INVOKE, text);
     }
     if (is_set(action, A_PE_START)) {
         crm_trace( "Action %.16llx (A_PE_START) %s", A_PE_START, text);
     }
     if (is_set(action, A_PE_STOP)) {
         crm_trace( "Action %.16llx (A_PE_STOP) %s", A_PE_STOP, text);
     }
     if (is_set(action, A_NODE_BLOCK)) {
         crm_trace( "Action %.16llx (A_NODE_BLOCK) %s", A_NODE_BLOCK, text);
     }
     if (is_set(action, A_UPDATE_NODESTATUS)) {
         crm_trace(
                             "Action %.16llx (A_UPDATE_NODESTATUS) %s", A_UPDATE_NODESTATUS, text);
     }
     if (is_set(action, A_LOG)) {
         crm_trace( "Action %.16llx (A_LOG   ) %s", A_LOG, text);
     }
     if (is_set(action, A_ERROR)) {
         crm_trace( "Action %.16llx (A_ERROR ) %s", A_ERROR, text);
     }
     if (is_set(action, A_WARN)) {
         crm_trace( "Action %.16llx (A_WARN  ) %s", A_WARN, text);
     }
 }
 
-void
-create_node_entry(const char *uuid, const char *uname, const char *type)
-{
-
-    /* make sure a node entry exists for the new node
-     *
-     * this will add anyone except the first ever node in the cluster
-     *   since it will also be the DC which doesnt go through the
-     *   join process (with itself).  We can include a special case
-     *   later if desired.
-     */
-    xmlNode *tmp1 = create_xml_node(NULL, XML_CIB_TAG_NODE);
-
-    crm_trace("Creating node entry for %s", uname);
-    set_uuid(tmp1, XML_ATTR_UUID, uname);
-
-    crm_xml_add(tmp1, XML_ATTR_UNAME, uname);
-    crm_xml_add(tmp1, XML_ATTR_TYPE, type);
-
-    fsa_cib_anon_update(XML_CIB_TAG_NODES, tmp1,
-                        cib_scope_local | cib_quorum_override | cib_can_create);
-
-    free_xml(tmp1);
-
-}
-
 xmlNode *
 create_node_state(const char *uname, const char *in_cluster,
                   const char *is_peer, const char *join_state, const char *exp_state,
                   gboolean clear_shutdown, const char *src)
 {
     xmlNode *node_state = create_xml_node(NULL, XML_CIB_TAG_STATE);
 
     crm_trace("%s Creating node state entry for %s", src, uname);
     set_uuid(node_state, XML_ATTR_UUID, uname);
 
     if (crm_element_value(node_state, XML_ATTR_UUID) == NULL) {
         crm_debug("Node %s is not a cluster member", uname);
         free_xml(node_state);
         return NULL;
     }
 
     crm_xml_add(node_state, XML_ATTR_UNAME, uname);
     crm_xml_add(node_state, XML_NODE_IN_CLUSTER, in_cluster);
     crm_xml_add(node_state, XML_NODE_IS_PEER, is_peer);
     crm_xml_add(node_state, XML_NODE_JOIN_STATE, join_state);
     crm_xml_add(node_state, XML_NODE_EXPECTED, exp_state);
     crm_xml_add(node_state, XML_ATTR_ORIGIN, src);
 
     if (clear_shutdown) {
         crm_xml_add(node_state, XML_CIB_ATTR_SHUTDOWN, "0");
     }
 
     crm_log_xml_trace(node_state, "created");
 
     return node_state;
 }
 
 extern GHashTable *ipc_clients;
 
 void
 process_client_disconnect(crmd_client_t * curr_client)
 {
     struct crm_subsystem_s *the_subsystem = NULL;
 
     CRM_CHECK(curr_client != NULL, return);
     crm_trace("received HUP from %s", curr_client->table_key);
 
     if (curr_client->sub_sys == NULL) {
         crm_trace("Client hadn't registered with us yet");
 
     } else if (strcasecmp(CRM_SYSTEM_PENGINE, curr_client->sub_sys) == 0) {
         the_subsystem = pe_subsystem;
 
     } else if (strcasecmp(CRM_SYSTEM_TENGINE, curr_client->sub_sys) == 0) {
         the_subsystem = te_subsystem;
 
     } else if (strcasecmp(CRM_SYSTEM_CIB, curr_client->sub_sys) == 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");
     }
 
     if (curr_client->table_key != NULL) {
         /*
          * Key is destroyed below as:
          *      curr_client->table_key
          * Value is cleaned up by:
          *      crmd_ipc_connection_destroy
          *   which will also call:
          *      G_main_del_IPC_Channel
          */
         g_hash_table_remove(ipc_clients, curr_client->table_key);
     }
 }
 
 gboolean
 update_dc(xmlNode * msg)
 {
     char *last_dc = fsa_our_dc;
     const char *dc_version = NULL;
     const char *welcome_from = NULL;
 
     if (msg != NULL) {
         gboolean invalid = FALSE;
 
         dc_version = crm_element_value(msg, F_CRM_VERSION);
         welcome_from = crm_element_value(msg, F_CRM_HOST_FROM);
 
         CRM_CHECK(dc_version != NULL, return FALSE);
         CRM_CHECK(welcome_from != NULL, return FALSE);
 
         if (AM_I_DC && safe_str_neq(welcome_from, fsa_our_uname)) {
             invalid = TRUE;
 
         } else if (fsa_our_dc && safe_str_neq(welcome_from, fsa_our_dc)) {
             invalid = TRUE;
         }
 
         if (invalid) {
             CRM_CHECK(fsa_our_dc != NULL, crm_err("We have no DC"));
             if (AM_I_DC) {
                 crm_err("Not updating DC to %s (%s): we are also a DC", welcome_from, dc_version);
             } else {
                 crm_warn("New DC %s is not %s", welcome_from, fsa_our_dc);
             }
 
             register_fsa_action(A_CL_JOIN_QUERY | A_DC_TIMER_START);
             return FALSE;
         }
     }
 
     free(fsa_our_dc_version);
     fsa_our_dc_version = NULL;
 
     fsa_our_dc = NULL;          /* Free'd as last_dc */
 
     if (welcome_from != NULL) {
         fsa_our_dc = strdup(welcome_from);
     }
     if (dc_version != NULL) {
         fsa_our_dc_version = strdup(dc_version);
     }
 
     if (safe_str_eq(fsa_our_dc, last_dc)) {
         /* do nothing */
 
     } else if (fsa_our_dc != NULL) {
         crm_info("Set DC to %s (%s)", crm_str(fsa_our_dc), crm_str(fsa_our_dc_version));
 
     } else if (last_dc != NULL) {
         crm_debug("Unset DC. Was %s", crm_str(last_dc));
     }
 
     free(last_dc);
     return TRUE;
 }
 
 #define STATUS_PATH_MAX 512
 static void
 erase_xpath_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
 {
     char *xpath = user_data;
 
     do_crm_log_unlikely(rc == 0 ? LOG_DEBUG : LOG_NOTICE,
                "Deletion of \"%s\": %s (rc=%d)", xpath, pcmk_strerror(rc), rc);
     free(xpath);
 }
 
 void
 erase_status_tag(const char *uname, const char *tag, int options)
 {
     int rc = pcmk_ok;
     char xpath[STATUS_PATH_MAX];
     int cib_opts = cib_quorum_override | cib_xpath | options;
 
     if (fsa_cib_conn && uname) {
         snprintf(xpath, STATUS_PATH_MAX, "//node_state[@uname='%s']/%s", uname, tag);
         crm_info("Deleting xpath: %s", xpath);
         rc = fsa_cib_conn->cmds->delete(fsa_cib_conn, xpath, NULL, cib_opts);
         add_cib_op_callback(fsa_cib_conn, rc, FALSE, strdup(xpath), erase_xpath_callback);
     }
 }
 
 crm_ipc_t *attrd_ipc = NULL;
 
 void
 update_attrd(const char *host, const char *name, const char *value, const char *user_name)
 {
     gboolean rc;
     int max = 5;
 
     if(attrd_ipc == NULL) {
         attrd_ipc = crm_ipc_new(T_ATTRD, 0);
     }
 
     do {
         if (crm_ipc_connected(attrd_ipc) == FALSE) {
             crm_info("Connecting to cluster... %d retries remaining", max);
             crm_ipc_connect(attrd_ipc);
         }
 
         rc = attrd_update_delegate(attrd_ipc, 'U', host, name, value, XML_CIB_TAG_STATUS, NULL, NULL, user_name);
         if (rc > 0) {
             break;
         }
 
         crm_ipc_close(attrd_ipc);
         sleep(5-max);
 
     } while(max--);
     
     if (rc == FALSE) {
         crm_err("Could not send %s %s %s (%d)", T_ATTRD, name ? "update" : "refresh",
                 name?name:"", is_set(fsa_input_register, R_SHUTDOWN));
 
         if(is_set(fsa_input_register, R_SHUTDOWN)) {
             register_fsa_input(C_FSA_INTERNAL, I_FAIL, NULL);
         }
     }
 }
diff --git a/tools/crm_inject.c b/tools/crm_inject.c
index 8562f64073..61f668741f 100644
--- a/tools/crm_inject.c
+++ b/tools/crm_inject.c
@@ -1,1487 +1,1486 @@
 /* 
  * 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 <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <dirent.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/common/util.h>
 #include <crm/transition.h>
 #include <crm/common/iso8601.h>
 #include <crm/pengine/status.h>
 #include <allocate.h>
 
 cib_t *global_cib = NULL;
 GListPtr op_fail = NULL;
 gboolean quiet = FALSE;
 
 #define new_node_template "//"XML_CIB_TAG_NODE"[@uname='%s']"
 #define node_template "//"XML_CIB_TAG_STATE"[@uname='%s']"
 #define rsc_template "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']"
 #define op_template  "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']/"XML_LRM_TAG_RSC_OP"[@id='%s']"
 /* #define op_template  "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']/"XML_LRM_TAG_RSC_OP"[@id='%s' and @"XML_LRM_ATTR_CALLID"='%d']" */
 
 #define FAKE_TE_ID	"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
 
 #define quiet_log(fmt, args...) do {		\
 	if(quiet == FALSE) {			\
 	    printf(fmt , ##args);		\
 	}					\
     } while(0)
 
 extern void cleanup_alloc_calculations(pe_working_set_t * data_set);
 
 extern xmlNode *do_calculations(pe_working_set_t * data_set, xmlNode * xml_input, ha_time_t * now);
 
 char *use_date = NULL;
 static ha_time_t *
 get_date(void)
 {
     if (use_date) {
         char *date_m = use_date;
 
         return parse_date(&date_m);
     }
     return NULL;
 }
 
 static xmlNode *
 find_resource(xmlNode * cib_node, const char *resource)
 {
     char *xpath = NULL;
     xmlNode *match = NULL;
     const char *node = crm_element_value(cib_node, XML_ATTR_UNAME);
     int max = strlen(rsc_template) + strlen(resource) + strlen(node) + 1;
 
     xpath = calloc(1, max);
 
     snprintf(xpath, max, rsc_template, node, resource);
     match = get_xpath_object(xpath, cib_node, LOG_DEBUG_2);
 
     free(xpath);
     return match;
 }
 
 static void
 create_node_entry(cib_t * cib_conn, char *node)
 {
     int rc = pcmk_ok;
     int max = strlen(new_node_template) + strlen(node) + 1;
     char *xpath = NULL;
 
     xpath = calloc(1, max);
 
     snprintf(xpath, max, new_node_template, node);
     rc = cib_conn->cmds->query(cib_conn, xpath, NULL, cib_xpath | cib_sync_call | cib_scope_local);
 
     if (rc == -ENXIO) {
         xmlNode *cib_object = create_xml_node(NULL, XML_CIB_TAG_NODE);
 
         /* Using node uname as uuid ala corosync/openais */
         crm_xml_add(cib_object, XML_ATTR_ID, node);
         crm_xml_add(cib_object, XML_ATTR_UNAME, node);
-        crm_xml_add(cib_object, XML_ATTR_TYPE, NORMALNODE);
         cib_conn->cmds->create(cib_conn, XML_CIB_TAG_NODES, cib_object,
                                cib_sync_call | cib_scope_local);
         /* Not bothering with subsequent query to see if it exists,
            we'll bomb out later in the call to determine_host... */
 
         free_xml(cib_object);
     }
 
     free(xpath);
 }
 
 static xmlNode *
 inject_node_state(cib_t * cib_conn, char *node)
 {
     int rc = pcmk_ok;
     int max = strlen(rsc_template) + strlen(node) + 1;
     char *xpath = NULL;
     xmlNode *cib_object = NULL;
 
     xpath = calloc(1, max);
 
     create_node_entry(cib_conn, node);
 
     snprintf(xpath, max, node_template, node);
     rc = cib_conn->cmds->query(cib_conn, xpath, &cib_object,
                                cib_xpath | cib_sync_call | cib_scope_local);
 
     if(cib_object && ID(cib_object) == NULL) {
         crm_err("Detected multiple node_state entries for xpath=%s, bailing", xpath);
         crm_log_xml_warn(cib_object, "Duplicates");
         exit(1);
     }
 
     if (rc == -ENXIO) {
         char *uuid = NULL;
 
         cib_object = create_xml_node(NULL, XML_CIB_TAG_STATE);
         determine_host(cib_conn, &node, &uuid);
         crm_xml_add(cib_object, XML_ATTR_UUID, uuid);
         crm_xml_add(cib_object, XML_ATTR_UNAME, node);
         cib_conn->cmds->create(cib_conn, XML_CIB_TAG_STATUS, cib_object,
                                cib_sync_call | cib_scope_local);
         free_xml(cib_object);
         free(uuid);
 
         rc = cib_conn->cmds->query(cib_conn, xpath, &cib_object,
                                    cib_xpath | cib_sync_call | cib_scope_local);
     }
 
     free(xpath);
     CRM_ASSERT(rc == pcmk_ok);
     return cib_object;
 }
 
 static xmlNode *
 modify_node(cib_t * cib_conn, char *node, gboolean up)
 {
     xmlNode *cib_node = inject_node_state(cib_conn, node);
 
     if (up) {
         crm_xml_add(cib_node, XML_NODE_IN_CLUSTER, XML_BOOLEAN_YES);
         crm_xml_add(cib_node, XML_NODE_IS_PEER, ONLINESTATUS);
         crm_xml_add(cib_node, XML_NODE_JOIN_STATE, CRMD_JOINSTATE_MEMBER);
         crm_xml_add(cib_node, XML_NODE_EXPECTED, CRMD_JOINSTATE_MEMBER);
 
     } else {
         crm_xml_add(cib_node, XML_NODE_IN_CLUSTER, XML_BOOLEAN_NO);
         crm_xml_add(cib_node, XML_NODE_IS_PEER, OFFLINESTATUS);
         crm_xml_add(cib_node, XML_NODE_JOIN_STATE, CRMD_JOINSTATE_DOWN);
         crm_xml_add(cib_node, XML_NODE_EXPECTED, CRMD_JOINSTATE_DOWN);
     }
 
     crm_xml_add(cib_node, XML_ATTR_ORIGIN, crm_system_name);
     return cib_node;
 }
 
 static void
 inject_transient_attr(xmlNode * cib_node, const char *name, const char *value)
 {
     xmlNode *attrs = NULL;
     xmlNode *container = NULL;
     xmlNode *nvp = NULL;
     const char *node_uuid = ID(cib_node);
     char *nvp_id = crm_concat(name, node_uuid, '-');
 
     crm_info("Injecting attribute %s=%s into %s '%s'", name, value, xmlGetNodePath(cib_node),
              ID(cib_node));
 
     attrs = first_named_child(cib_node, XML_TAG_TRANSIENT_NODEATTRS);
     if (attrs == NULL) {
         attrs = create_xml_node(cib_node, XML_TAG_TRANSIENT_NODEATTRS);
         crm_xml_add(attrs, XML_ATTR_ID, node_uuid);
     }
 
     container = first_named_child(attrs, XML_TAG_ATTR_SETS);
     if (container == NULL) {
         container = create_xml_node(attrs, XML_TAG_ATTR_SETS);
         crm_xml_add(container, XML_ATTR_ID, node_uuid);
     }
 
     nvp = create_xml_node(container, XML_CIB_TAG_NVPAIR);
     crm_xml_add(nvp, XML_ATTR_ID, nvp_id);
     crm_xml_add(nvp, XML_NVPAIR_ATTR_NAME, name);
     crm_xml_add(nvp, XML_NVPAIR_ATTR_VALUE, value);
 
     free(nvp_id);
 }
 
 static xmlNode *
 inject_resource(xmlNode * cib_node, const char *resource, const char *rclass, const char *rtype,
                 const char *rprovider)
 {
     xmlNode *lrm = NULL;
     xmlNode *container = NULL;
     xmlNode *cib_resource = NULL;
     char *xpath = NULL;
 
     cib_resource = find_resource(cib_node, resource);
     if (cib_resource != NULL) {
         return cib_resource;
     }
 
     /* One day, add query for class, provider, type */
 
     if (rclass == NULL || rtype == NULL) {
         fprintf(stderr, "Resource %s not found in the status section of %s."
                 "  Please supply the class and type to continue\n", resource, ID(cib_node));
         return NULL;
 
     } else if (safe_str_neq(rclass, "ocf")
                && safe_str_neq(rclass, "stonith")
                && safe_str_neq(rclass, "heartbeat")
                && safe_str_neq(rclass, "lsb")) {
         fprintf(stderr, "Invalid class for %s: %s\n", resource, rclass);
         return NULL;
 
     } else if (safe_str_eq(rclass, "ocf") && rprovider == NULL) {
         fprintf(stderr, "Please specify the provider for resource %s\n", resource);
         return NULL;
     }
 
     xpath = (char *)xmlGetNodePath(cib_node);
     crm_info("Injecting new resource %s into %s '%s'", resource, xpath, ID(cib_node));
     free(xpath);
 
     lrm = first_named_child(cib_node, XML_CIB_TAG_LRM);
     if (lrm == NULL) {
         const char *node_uuid = ID(cib_node);
 
         lrm = create_xml_node(cib_node, XML_CIB_TAG_LRM);
         crm_xml_add(lrm, XML_ATTR_ID, node_uuid);
     }
 
     container = first_named_child(lrm, XML_LRM_TAG_RESOURCES);
     if (container == NULL) {
         container = create_xml_node(lrm, XML_LRM_TAG_RESOURCES);
     }
 
     cib_resource = create_xml_node(container, XML_LRM_TAG_RESOURCE);
     crm_xml_add(cib_resource, XML_ATTR_ID, resource);
 
     crm_xml_add(cib_resource, XML_AGENT_ATTR_CLASS, rclass);
     crm_xml_add(cib_resource, XML_AGENT_ATTR_PROVIDER, rprovider);
     crm_xml_add(cib_resource, XML_ATTR_TYPE, rtype);
 
     return cib_resource;
 }
 
 static lrmd_event_data_t *
 create_op(xmlNode * cib_resource, const char *task, int interval, int outcome)
 {
     lrmd_event_data_t *op = NULL;
     xmlNode *xop = NULL;
 
     op = calloc(1, sizeof(lrmd_event_data_t));
 
     op->rsc_id = strdup(ID(cib_resource));
     op->interval = interval;
     op->op_type = strdup(task);
 
     op->rc = outcome;
     op->op_status = 0;
     op->params = NULL;          /* TODO: Fill me in */
 
     op->call_id = 0;
     for (xop = __xml_first_child(cib_resource); xop != NULL; xop = __xml_next(xop)) {
         int tmp = 0;
 
         crm_element_value_int(xop, XML_LRM_ATTR_CALLID, &tmp);
         if (tmp > op->call_id) {
             op->call_id = tmp;
         }
     }
     op->call_id++;
 
     return op;
 }
 
 static xmlNode *
 inject_op(xmlNode * cib_resource, lrmd_event_data_t * op, int target_rc)
 {
     return create_operation_update(cib_resource, op, CRM_FEATURE_SET, target_rc, crm_system_name,
                                    LOG_DEBUG_2);
 }
 
 static void
 update_failcounts(xmlNode * cib_node, const char *resource, int interval, int rc)
 {
     if (rc == 0) {
         return;
 
     } else if (rc == 7 && interval == 0) {
         return;
 
     } else {
         char *name = NULL;
         char *now = crm_itoa(time(NULL));
 
         name = crm_concat("fail-count", resource, '-');
         inject_transient_attr(cib_node, name, "value++");
 
         name = crm_concat("last-failure", resource, '-');
         inject_transient_attr(cib_node, name, now);
 
         free(name);
         free(now);
     }
 }
 
 static gboolean
 exec_pseudo_action(crm_graph_t * graph, crm_action_t * action)
 {
     const char *node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
     const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
     action->confirmed = TRUE;
 
     quiet_log(" * Pseudo action:   %s%s%s\n", task, node?" on ":"", node?node:"");
     update_graph(graph, action);
     return TRUE;
 }
 
 static gboolean
 exec_rsc_action(crm_graph_t * graph, crm_action_t * action)
 {
     int rc = 0;
     GListPtr gIter = NULL;
     lrmd_event_data_t *op = NULL;
     int target_outcome = 0;
 
     const char *rtype = NULL;
     const char *rclass = NULL;
     const char *resource = NULL;
     const char *rprovider = NULL;
     const char *target_rc_s = crm_meta_value(action->params, XML_ATTR_TE_TARGET_RC);
 
     xmlNode *cib_node = NULL;
     xmlNode *cib_resource = NULL;
     xmlNode *action_rsc = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
 
     char *node = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET);
 
     if (safe_str_eq(crm_element_value(action->xml, "operation"), "probe_complete")) {
         crm_info("Skipping %s op for %s\n", crm_element_value(action->xml, "operation"), node);
         goto done;
     }
 
     if (action_rsc == NULL) {
         crm_log_xml_err(action->xml, "Bad");
         free(node);
         return FALSE;
     }
 
     resource = ID(action_rsc);
     rclass = crm_element_value(action_rsc, XML_AGENT_ATTR_CLASS);
     rtype = crm_element_value(action_rsc, XML_ATTR_TYPE);
     rprovider = crm_element_value(action_rsc, XML_AGENT_ATTR_PROVIDER);
 
     if (target_rc_s != NULL) {
         target_outcome = crm_parse_int(target_rc_s, "0");
     }
 
     CRM_ASSERT(global_cib->cmds->query(global_cib, NULL, NULL, cib_sync_call | cib_scope_local) ==
                pcmk_ok);
 
     cib_node = inject_node_state(global_cib, node);
     CRM_ASSERT(cib_node != NULL);
 
     cib_resource = inject_resource(cib_node, resource, rclass, rtype, rprovider);
     CRM_ASSERT(cib_resource != NULL);
 
     op = convert_graph_action(cib_resource, action, 0, target_outcome);
     if(op->interval) {
         quiet_log(" * Resource action: %-15s %s=%d on %s\n", resource, op->op_type, op->interval, node);
     } else {
         quiet_log(" * Resource action: %-15s %s on %s\n", resource, op->op_type, node);
     }
 
     for (gIter = op_fail; gIter != NULL; gIter = gIter->next) {
         char *spec = (char *)gIter->data;
         char *key = NULL;
 
         key = calloc(1, 1 + strlen(spec));
         snprintf(key, strlen(spec), "%s_%s_%d@%s=", resource, op->op_type, op->interval, node);
 
         if (strncasecmp(key, spec, strlen(key)) == 0) {
             rc = sscanf(spec, "%*[^=]=%d", (int *) &op->rc);
 
             action->failed = TRUE;
             graph->abort_priority = INFINITY;
             printf("\tPretending action %d failed with rc=%d\n", action->id, op->rc);
             update_failcounts(cib_node, resource, op->interval, op->rc);
             free(key);
             break;
         }
         free(key);
     }
 
     inject_op(cib_resource, op, target_outcome);
     lrmd_free_event(op);
 
     rc = global_cib->cmds->modify(global_cib, XML_CIB_TAG_STATUS, cib_node,
                                   cib_sync_call | cib_scope_local);
     CRM_ASSERT(rc == pcmk_ok);
 
   done:
     free(node);
     free_xml(cib_node);
     action->confirmed = TRUE;
     update_graph(graph, action);
     return TRUE;
 }
 
 static gboolean
 exec_crmd_action(crm_graph_t * graph, crm_action_t * action)
 {
     const char *node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
     const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
     action->confirmed = TRUE;
 
     quiet_log(" * Cluster action:  %s on %s\n", task, node);
     update_graph(graph, action);
     return TRUE;
 }
 
 #define STATUS_PATH_MAX 512
 static gboolean
 exec_stonith_action(crm_graph_t * graph, crm_action_t * action)
 {
     int rc = 0;
     char xpath[STATUS_PATH_MAX];
     char *target = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET);
     xmlNode *cib_node = modify_node(global_cib, target, FALSE);
 
     crm_xml_add(cib_node, XML_ATTR_ORIGIN, __FUNCTION__);
     CRM_ASSERT(cib_node != NULL);
 
     quiet_log(" * Fencing %s\n", target);
     rc = global_cib->cmds->replace(global_cib, XML_CIB_TAG_STATUS, cib_node,
                                    cib_sync_call | cib_scope_local);
     CRM_ASSERT(rc == pcmk_ok);
 
     snprintf(xpath, STATUS_PATH_MAX, "//node_state[@uname='%s']/%s", target, XML_CIB_TAG_LRM);
     rc = global_cib->cmds->delete(global_cib, xpath, NULL,
                                   cib_xpath | cib_sync_call | cib_scope_local);
 
     snprintf(xpath, STATUS_PATH_MAX, "//node_state[@uname='%s']/%s", target,
              XML_TAG_TRANSIENT_NODEATTRS);
     rc = global_cib->cmds->delete(global_cib, xpath, NULL,
                                   cib_xpath | cib_sync_call | cib_scope_local);
 
     action->confirmed = TRUE;
     update_graph(graph, action);
     free_xml(cib_node);
     free(target);
     return TRUE;
 }
 
 static char *
 add_list_element(char *list, const char *value)
 {
     int len = 0;
     int last = 0;
 
     if (value == NULL) {
         return list;
     }
     if (list) {
         last = strlen(list);
     }
     len = last + 2;             /* +1 space, +1 EOS */
     len += strlen(value);
     list = realloc(list, len);
     sprintf(list + last, " %s", value);
     return list;
 }
 
 static void
 print_cluster_status(pe_working_set_t * data_set)
 {
     char *online_nodes = NULL;
     char *offline_nodes = NULL;
 
     GListPtr gIter = NULL;
 
     for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
         node_t *node = (node_t *) gIter->data;
         const char *node_mode = NULL;
 
         if (node->details->unclean) {
             if (node->details->online && node->details->unclean) {
                 node_mode = "UNCLEAN (online)";
 
             } else if (node->details->pending) {
                 node_mode = "UNCLEAN (pending)";
 
             } else {
                 node_mode = "UNCLEAN (offline)";
             }
 
         } else if (node->details->pending) {
             node_mode = "pending";
 
         } else if (node->details->standby_onfail && node->details->online) {
             node_mode = "standby (on-fail)";
 
         } else if (node->details->standby) {
             if (node->details->online) {
                 node_mode = "standby";
             } else {
                 node_mode = "OFFLINE (standby)";
             }
 
         } else if (node->details->online) {
             node_mode = "online";
             online_nodes = add_list_element(online_nodes, node->details->uname);
             continue;
 
         } else {
             node_mode = "OFFLINE";
             offline_nodes = add_list_element(offline_nodes, node->details->uname);
             continue;
         }
 
         if (safe_str_eq(node->details->uname, node->details->id)) {
             printf("Node %s: %s\n", node->details->uname, node_mode);
         } else {
             printf("Node %s (%s): %s\n", node->details->uname, node->details->id, node_mode);
         }
     }
 
     if (online_nodes) {
         printf("Online: [%s ]\n", online_nodes);
         free(online_nodes);
     }
     if (offline_nodes) {
         printf("OFFLINE: [%s ]\n", offline_nodes);
         free(offline_nodes);
     }
 
     fprintf(stdout, "\n");
     for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
         resource_t *rsc = (resource_t *) gIter->data;
 
         if (is_set(rsc->flags, pe_rsc_orphan)
             && rsc->role == RSC_ROLE_STOPPED) {
             continue;
         }
         rsc->fns->print(rsc, NULL, pe_print_printf, stdout);
     }
     fprintf(stdout, "\n");
 }
 
 static int
 run_simulation(pe_working_set_t * data_set)
 {
     crm_graph_t *transition = NULL;
     enum transition_status graph_rc = -1;
 
     crm_graph_functions_t exec_fns = {
         exec_pseudo_action,
         exec_rsc_action,
         exec_crmd_action,
         exec_stonith_action,
     };
 
     set_graph_functions(&exec_fns);
 
     quiet_log("\nExecuting cluster transition:\n");
     transition = unpack_graph(data_set->graph, crm_system_name);
     print_graph(LOG_DEBUG, transition);
 
     do {
         graph_rc = run_graph(transition);
 
     } while (graph_rc == transition_active);
 
     if (graph_rc != transition_complete) {
         fprintf(stdout, "Transition failed: %s\n", transition_status(graph_rc));
         print_graph(LOG_ERR, transition);
     }
     destroy_graph(transition);
     if (graph_rc != transition_complete) {
         fprintf(stdout, "An invalid transition was produced\n");
     }
 
     if (quiet == FALSE) {
         xmlNode *cib_object = NULL;
         int rc =
             global_cib->cmds->query(global_cib, NULL, &cib_object, cib_sync_call | cib_scope_local);
 
         CRM_ASSERT(rc == pcmk_ok);
         quiet_log("\nRevised cluster status:\n");
         cleanup_alloc_calculations(data_set);
         data_set->input = cib_object;
         data_set->now = get_date();
 
         cluster_status(data_set);
         print_cluster_status(data_set);
     }
 
     if (graph_rc != transition_complete) {
         return graph_rc;
     }
     return 0;
 }
 
 static char *
 create_action_name(action_t * action)
 {
     char *action_name = NULL;
     const char *action_host = NULL;
 
     if (action->node) {
         action_host = action->node->details->uname;
         action_name = crm_concat(action->uuid, action_host, ' ');
 
     } else if (is_set(action->flags, pe_action_pseudo)) {
         action_name = strdup(action->uuid);
 
     } else {
         action_host = "<none>";
         action_name = crm_concat(action->uuid, action_host, ' ');
     }
     if (safe_str_eq(action->task, RSC_CANCEL)) {
         char *tmp_action_name = action_name;
 
         action_name = crm_concat("Cancel", tmp_action_name, ' ');
         free(tmp_action_name);
     }
 
     return action_name;
 }
 
 static void
 create_dotfile(pe_working_set_t * data_set, const char *dot_file, gboolean all_actions)
 {
     GListPtr gIter = NULL;
     FILE *dot_strm = fopen(dot_file, "w");
 
     if (dot_strm == NULL) {
         crm_perror(LOG_ERR, "Could not open %s for writing", dot_file);
         return;
     }
 
     fprintf(dot_strm, " digraph \"g\" {\n");
     for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
         action_t *action = (action_t *) gIter->data;
         const char *style = "dashed";
         const char *font = "black";
         const char *color = "black";
         char *action_name = create_action_name(action);
 
         crm_trace("Action %d: %p", action->id, action);
 
         if (is_set(action->flags, pe_action_pseudo)) {
             font = "orange";
         }
 
         if (is_set(action->flags, pe_action_dumped)) {
             style = "bold";
             color = "green";
 
         } else if (action->rsc != NULL && is_not_set(action->rsc->flags, pe_rsc_managed)) {
             color = "red";
             font = "purple";
             if (all_actions == FALSE) {
                 goto dont_write;
             }
 
         } else if (is_set(action->flags, pe_action_optional)) {
             color = "blue";
             if (all_actions == FALSE) {
                 goto dont_write;
             }
 
         } else {
             color = "red";
             CRM_CHECK(is_set(action->flags, pe_action_runnable) == FALSE,;
                 );
         }
 
         set_bit(action->flags, pe_action_dumped);
         fprintf(dot_strm, "\"%s\" [ style=%s color=\"%s\" fontcolor=\"%s\"]\n",
                 action_name, style, color, font);
   dont_write:
         free(action_name);
     }
 
     for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
         action_t *action = (action_t *) gIter->data;
 
         GListPtr gIter2 = NULL;
 
         for (gIter2 = action->actions_before; gIter2 != NULL; gIter2 = gIter2->next) {
             action_wrapper_t *before = (action_wrapper_t *) gIter2->data;
 
             char *before_name = NULL;
             char *after_name = NULL;
             const char *style = "dashed";
             gboolean optional = TRUE;
 
             if (before->state == pe_link_dumped) {
                 optional = FALSE;
                 style = "bold";
             } else if (is_set(action->flags, pe_action_pseudo)
                        && (before->type & pe_order_stonith_stop)) {
                 continue;
             } else if (before->state == pe_link_dup) {
                 continue;
             } else if (before->type == pe_order_none) {
                 continue;
             } else if (is_set(before->action->flags, pe_action_dumped)
                        && is_set(action->flags, pe_action_dumped)
                        && before->type != pe_order_load) {
                 optional = FALSE;
             }
 
             if (all_actions || optional == FALSE) {
                 before_name = create_action_name(before->action);
                 after_name = create_action_name(action);
                 fprintf(dot_strm, "\"%s\" -> \"%s\" [ style = %s]\n",
                         before_name, after_name, style);
                 free(before_name);
                 free(after_name);
             }
         }
     }
 
     fprintf(dot_strm, "}\n");
     if (dot_strm != NULL) {
         fflush(dot_strm);
         fclose(dot_strm);
     }
 }
 
 static int
 find_ticket_state(cib_t * the_cib, const char * ticket_id, xmlNode ** ticket_state_xml)
 {
     int offset = 0;
     static int xpath_max = 1024;
     int rc = pcmk_ok;
     xmlNode *xml_search = NULL;
 
     char *xpath_string = NULL;
 
     CRM_ASSERT(ticket_state_xml != NULL);
     *ticket_state_xml = NULL;
 
     xpath_string = calloc(1, xpath_max);
     offset +=
         snprintf(xpath_string + offset, xpath_max - offset, "%s", "/cib/status/tickets");
 
     if (ticket_id) {
         offset += snprintf(xpath_string + offset, xpath_max - offset, "/%s[@id=\"%s\"]",
                        XML_CIB_TAG_TICKET_STATE, ticket_id);
     }
 
     rc = the_cib->cmds->query(the_cib, xpath_string, &xml_search,
                               cib_sync_call | cib_scope_local | cib_xpath);
 
     if (rc != pcmk_ok) {
         goto bail;
     }
 
     crm_log_xml_debug(xml_search, "Match");
     if (xml_has_children(xml_search)) {
         if (ticket_id) {
             fprintf(stdout, "Multiple ticket_states match ticket_id=%s\n", ticket_id);
         }
         *ticket_state_xml = xml_search;
     } else {
         *ticket_state_xml = xml_search;
     }
 
   bail:
     free(xpath_string);
     return rc;
 }
 
 static int
 set_ticket_state_attr(const char *ticket_id, const char *attr_name,
                       const char *attr_value, cib_t * cib, int cib_options)
 {
     int rc = pcmk_ok;
     xmlNode *xml_top = NULL;
     xmlNode *ticket_state_xml = NULL;
 
     rc = find_ticket_state(cib, ticket_id, &ticket_state_xml);
     if (rc == pcmk_ok) {
         crm_debug("Found a match state for ticket: id=%s", ticket_id);
         xml_top = ticket_state_xml;
 
     } else if (rc != -ENXIO) {
         return rc;
 
     } else {
         xmlNode *xml_obj = NULL;
 
         xml_top = create_xml_node(NULL, XML_CIB_TAG_STATUS);
         xml_obj = create_xml_node(xml_top, XML_CIB_TAG_TICKETS);
         ticket_state_xml = create_xml_node(xml_obj, XML_CIB_TAG_TICKET_STATE);
         crm_xml_add(ticket_state_xml, XML_ATTR_ID, ticket_id);
     }
 
     crm_xml_add(ticket_state_xml, attr_name, attr_value);
 
     crm_log_xml_debug(xml_top, "Update");
 
     rc = cib->cmds->modify(cib, XML_CIB_TAG_STATUS, xml_top, cib_options);
 
     free_xml(xml_top);
 
     return rc;
 }
 
 static void
 modify_configuration(pe_working_set_t * data_set,
                      const char *quorum, GListPtr node_up, GListPtr node_down, GListPtr node_fail,
                      GListPtr op_inject, GListPtr ticket_grant, GListPtr ticket_revoke,
                      GListPtr ticket_standby, GListPtr ticket_activate)
 {
     int rc = pcmk_ok;
     GListPtr gIter = NULL;
 
     xmlNode *cib_op = NULL;
     xmlNode *cib_node = NULL;
     xmlNode *cib_resource = NULL;
 
     lrmd_event_data_t *op = NULL;
 
     if (quorum) {
         xmlNode *top = create_xml_node(NULL, XML_TAG_CIB);
 
         quiet_log(" + Setting quorum: %s\n", quorum);
         /* crm_xml_add(top, XML_ATTR_DC_UUID, dc_uuid);      */
         crm_xml_add(top, XML_ATTR_HAVE_QUORUM, quorum);
 
         rc = global_cib->cmds->modify(global_cib, NULL, top, cib_sync_call | cib_scope_local);
         CRM_ASSERT(rc == pcmk_ok);
     }
 
     for (gIter = node_up; gIter != NULL; gIter = gIter->next) {
         char *node = (char *)gIter->data;
 
         quiet_log(" + Bringing node %s online\n", node);
         cib_node = modify_node(global_cib, node, TRUE);
         CRM_ASSERT(cib_node != NULL);
 
         rc = global_cib->cmds->modify(global_cib, XML_CIB_TAG_STATUS, cib_node,
                                       cib_sync_call | cib_scope_local);
         CRM_ASSERT(rc == pcmk_ok);
     }
 
     for (gIter = node_down; gIter != NULL; gIter = gIter->next) {
         char *node = (char *)gIter->data;
 
         quiet_log(" + Taking node %s offline\n", node);
         cib_node = modify_node(global_cib, node, FALSE);
         CRM_ASSERT(cib_node != NULL);
 
         rc = global_cib->cmds->modify(global_cib, XML_CIB_TAG_STATUS, cib_node,
                                       cib_sync_call | cib_scope_local);
         CRM_ASSERT(rc == pcmk_ok);
     }
 
     for (gIter = node_fail; gIter != NULL; gIter = gIter->next) {
         char *node = (char *)gIter->data;
 
         quiet_log(" + Failing node %s\n", node);
         cib_node = modify_node(global_cib, node, TRUE);
         crm_xml_add(cib_node, XML_NODE_IN_CLUSTER, XML_BOOLEAN_NO);
         CRM_ASSERT(cib_node != NULL);
 
         rc = global_cib->cmds->modify(global_cib, XML_CIB_TAG_STATUS, cib_node,
                                       cib_sync_call | cib_scope_local);
         CRM_ASSERT(rc == pcmk_ok);
     }
 
     for (gIter = ticket_grant; gIter != NULL; gIter = gIter->next) {
         char *ticket_id = (char *)gIter->data;
 
         quiet_log(" + Granting ticket %s\n", ticket_id);
         rc = set_ticket_state_attr(ticket_id, "granted", "true",
                                   global_cib, cib_sync_call | cib_scope_local);
 
         CRM_ASSERT(rc == pcmk_ok);
     }
 
     for (gIter = ticket_revoke; gIter != NULL; gIter = gIter->next) {
         char *ticket_id = (char *)gIter->data;
 
         quiet_log(" + Revoking ticket %s\n", ticket_id);
         rc = set_ticket_state_attr(ticket_id, "granted", "false",
                                   global_cib, cib_sync_call | cib_scope_local);
 
         CRM_ASSERT(rc == pcmk_ok);
     }
 
     for (gIter = ticket_standby; gIter != NULL; gIter = gIter->next) {
         char *ticket_id = (char *)gIter->data;
 
         quiet_log(" + Making ticket %s standby\n", ticket_id);
         rc = set_ticket_state_attr(ticket_id, "standby", "true",
                                   global_cib, cib_sync_call | cib_scope_local);
 
         CRM_ASSERT(rc == pcmk_ok);
     }
 
     for (gIter = ticket_activate; gIter != NULL; gIter = gIter->next) {
         char *ticket_id = (char *)gIter->data;
 
         quiet_log(" + Activating ticket %s\n", ticket_id);
         rc = set_ticket_state_attr(ticket_id, "standby", "false",
                                   global_cib, cib_sync_call | cib_scope_local);
 
         CRM_ASSERT(rc == pcmk_ok);
     }
 
     for (gIter = op_inject; gIter != NULL; gIter = gIter->next) {
         char *spec = (char *)gIter->data;
 
         int rc = 0;
         int outcome = 0;
         int interval = 0;
 
         char *key = NULL;
         char *node = NULL;
         char *task = NULL;
         char *resource = NULL;
 
         const char *rtype = NULL;
         const char *rclass = NULL;
         const char *rprovider = NULL;
 
         resource_t *rsc = NULL;
 
         quiet_log(" + Injecting %s into the configuration\n", spec);
 
         key = calloc(1, strlen(spec) + 1);
         node = calloc(1, strlen(spec) + 1);
         rc = sscanf(spec, "%[^@]@%[^=]=%d", key, node, &outcome);
         CRM_CHECK(rc == 3,
                   fprintf(stderr, "Invalid operation spec: %s.  Only found %d fields\n", spec, rc);
                   continue);
 
         parse_op_key(key, &resource, &task, &interval);
 
         rsc = pe_find_resource(data_set->resources, resource);
         if (rsc == NULL) {
             fprintf(stderr, " - Invalid resource name: %s\n", resource);
         } else {
             rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
             rtype = crm_element_value(rsc->xml, XML_ATTR_TYPE);
             rprovider = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
 
             cib_node = inject_node_state(global_cib, node);
             CRM_ASSERT(cib_node != NULL);
 
             update_failcounts(cib_node, resource, interval, outcome);
 
             cib_resource = inject_resource(cib_node, resource, rclass, rtype, rprovider);
             CRM_ASSERT(cib_resource != NULL);
 
             op = create_op(cib_resource, task, interval, outcome);
             CRM_ASSERT(op != NULL);
 
             cib_op = inject_op(cib_resource, op, 0);
             CRM_ASSERT(cib_op != NULL);
             lrmd_free_event(op);
 
             rc = global_cib->cmds->modify(global_cib, XML_CIB_TAG_STATUS, cib_node,
                                           cib_sync_call | cib_scope_local);
             CRM_ASSERT(rc == pcmk_ok);
         }
         free(task);
         free(node);
         free(key);
     }
 }
 
 static void
 setup_input(const char *input, const char *output)
 {
     int rc = pcmk_ok;
     cib_t *cib_conn = NULL;
     xmlNode *cib_object = NULL;
     char *local_output = NULL;
 
     if (input == NULL) {
         /* Use live CIB */
         cib_conn = cib_new();
         rc = cib_conn->cmds->signon(cib_conn, crm_system_name, cib_command);
 
         if (rc == pcmk_ok) {
             cib_object = get_cib_copy(cib_conn);
         }
 
         cib_conn->cmds->signoff(cib_conn);
         cib_delete(cib_conn);
         cib_conn = NULL;
 
         if (cib_object == NULL) {
             fprintf(stderr, "Live CIB query failed: empty result\n");
             exit(3);
         }
 
     } else if (safe_str_eq(input, "-")) {
         cib_object = filename2xml(NULL);
 
     } else {
         cib_object = filename2xml(input);
     }
 
     if (get_object_root(XML_CIB_TAG_STATUS, cib_object) == NULL) {
         create_xml_node(cib_object, XML_CIB_TAG_STATUS);
     }
 
     if (cli_config_update(&cib_object, NULL, FALSE) == FALSE) {
         free_xml(cib_object);
         exit(-ENOKEY);
     }
 
     if (validate_xml(cib_object, NULL, FALSE) != TRUE) {
         free_xml(cib_object);
         exit(-pcmk_err_dtd_validation);
     }
 
     if (output == NULL) {
         char *pid = crm_itoa(getpid());
 
         local_output = get_shadow_file(pid);
         output = local_output;
         free(pid);
     }
 
     rc = write_xml_file(cib_object, output, FALSE);
     free_xml(cib_object);
     cib_object = NULL;
 
     if (rc < 0) {
         fprintf(stderr, "Could not create '%s': %s\n", output, strerror(errno));
         exit(rc);
     }
     setenv("CIB_file", output, 1);
     free(local_output);
 }
 
 
 /* *INDENT-OFF* */
 static struct crm_option long_options[] = {
     /* Top-level Options */
     {"help",    0, 0, '?', "\tThis text"},
     {"version", 0, 0, '$', "\tVersion information"  },
     {"quiet",   0, 0, 'Q', "\tDisplay only essentialoutput"},
     {"verbose", 0, 0, 'V', "\tIncrease debug output"},
 
     {"-spacer-",      0, 0, '-', "\nOperations:"},
     {"run",           0, 0, 'R', "\tDetermine the cluster's response to the given configuration and status"},
     {"simulate",      0, 0, 'S', "Simulate the transition's execution and display the resulting cluster status"},
     {"in-place",      0, 0, 'X', "Simulate the transition's execution and store the result back to the input file"},
     {"show-scores",   0, 0, 's', "Show allocation scores"},
     {"show-utilization",   0, 0, 'U', "Show utilization information"},
     {"profile",       1, 0, 'P', "Run all tests in the named directory to create profiling data"},
 
     {"-spacer-",     0, 0, '-', "\nSynthetic Cluster Events:"},
     {"node-up",      1, 0, 'u', "\tBring a node online"},
     {"node-down",    1, 0, 'd', "\tTake a node offline"},
     {"node-fail",    1, 0, 'f', "\tMark a node as failed"},
     {"op-inject",    1, 0, 'i', "\t$rsc_$task_$interval@$node=$rc - Inject the specified task before running the simulation"},
     {"op-fail",      1, 0, 'F', "\t$rsc_$task_$interval@$node=$rc - Fail the specified task while running the simulation"},
     {"set-datetime", 1, 0, 't', "Set date/time"},
     {"quorum",       1, 0, 'q', "\tSpecify a value for quorum"},
     {"ticket-grant",     1, 0, 'g', "Grant a ticket"},
     {"ticket-revoke",    1, 0, 'r', "Revoke a ticket"},
     {"ticket-standby",   1, 0, 'b', "Make a ticket standby"},
     {"ticket-activate",  1, 0, 'e', "Activate a ticket"},
 
     {"-spacer-",     0, 0, '-', "\nOutput Options:"},
     
     {"save-input",   1, 0, 'I', "\tSave the input configuration to the named file"},
     {"save-output",  1, 0, 'O', "Save the output configuration to the named file"},
     {"save-graph",   1, 0, 'G', "\tSave the transition graph (XML format) to the named file"},
     {"save-dotfile", 1, 0, 'D', "Save the transition graph (DOT format) to the named file"},
     {"all-actions",  0, 0, 'a', "\tDisplay all possible actions in the DOT graph - even ones not part of the transition"},
     
     {"-spacer-",    0, 0, '-', "\nData Source:"},
     {"live-check",  0, 0, 'L', "\tConnect to the CIB and use the current contents as input"},
     {"xml-file",    1, 0, 'x', "\tRetrieve XML from the named file"},
     {"xml-pipe",    0, 0, 'p', "\tRetrieve XML from stdin"},
     
     {0, 0, 0, 0}
 };
 /* *INDENT-ON* */
 
 static void
 profile_one(const char *xml_file)
 {
     xmlNode *cib_object = NULL;
     pe_working_set_t data_set;
 
     printf("* Testing %s\n", xml_file);
     cib_object = filename2xml(xml_file);
     if (get_object_root(XML_CIB_TAG_STATUS, cib_object) == NULL) {
         create_xml_node(cib_object, XML_CIB_TAG_STATUS);
     }
 
     if (cli_config_update(&cib_object, NULL, FALSE) == FALSE) {
         free_xml(cib_object);
         return;
     }
 
     if (validate_xml(cib_object, NULL, FALSE) != TRUE) {
         free_xml(cib_object);
         return;
     }
 
     set_working_set_defaults(&data_set);
 
     data_set.input = cib_object;
     data_set.now = get_date();
     do_calculations(&data_set, cib_object, NULL);
 
     cleanup_alloc_calculations(&data_set);
 }
 
 #ifndef FILENAME_MAX
 #  define FILENAME_MAX 512
 #endif
 
 static int
 profile_all(const char *dir)
 {
     struct dirent **namelist;
 
     int lpc = 0;
     int file_num = scandir(dir, &namelist, 0, alphasort);
 
     if (file_num > 0) {
 	struct stat prop;
 	char buffer[FILENAME_MAX + 1];
 
 	while (file_num--) {
 	    if ('.' == namelist[file_num]->d_name[0]) {
 		free(namelist[file_num]);
 		continue;
 
 	    } else if (strstr(namelist[file_num]->d_name, ".xml") == NULL) {
 		free(namelist[file_num]);
 		continue;
 	    }
 
 	    lpc++;
 	    snprintf(buffer, FILENAME_MAX, "%s/%s", dir, namelist[file_num]->d_name);
 	    if (stat(buffer, &prop) == 0 && S_ISREG(prop.st_mode)) {
 		profile_one(buffer);
 	    }
 	    free(namelist[file_num]);
 	}
 	free(namelist);
     }
 
     return lpc;
 }
 
 int
 main(int argc, char **argv)
 {
     int rc = 0;
     guint modified = 0;
 
     gboolean store = FALSE;
     gboolean process = FALSE;
     gboolean verbose = FALSE;
     gboolean simulate = FALSE;
     gboolean all_actions = FALSE;
     gboolean have_stdout = FALSE;
 
     pe_working_set_t data_set;
 
     const char *xml_file = "-";
     const char *quorum = NULL;
     const char *test_dir = NULL;
     const char *dot_file = NULL;
     const char *graph_file = NULL;
     const char *input_file = NULL;
     const char *output_file = NULL;
 
     int flag = 0;
     int index = 0;
     int argerr = 0;
 
     GListPtr node_up = NULL;
     GListPtr node_down = NULL;
     GListPtr node_fail = NULL;
     GListPtr op_inject = NULL;
     GListPtr ticket_grant = NULL;
     GListPtr ticket_revoke = NULL;
     GListPtr ticket_standby = NULL;
     GListPtr ticket_activate = NULL;
 
     xmlNode *input = NULL;
 
     crm_log_cli_init("crm_simulate");
     crm_set_options(NULL, "datasource operation [additional options]",
                     long_options, "Tool for simulating the cluster's response to events");
 
     if (argc < 2) {
         crm_help('?', EX_USAGE);
     }
 
     while (1) {
         flag = crm_get_option(argc, argv, &index);
         if (flag == -1)
             break;
 
         switch (flag) {
             case 'V':
                 verbose = TRUE;
 
                 if(have_stdout == FALSE) {
                     /* Redirect stderr to stdout so we can grep the output */
                     have_stdout = TRUE;
                     close(STDERR_FILENO);
                     dup2(STDOUT_FILENO, STDERR_FILENO);
                 }
                 
                 crm_bump_log_level();
                 break;
             case '?':
             case '$':
                 crm_help(flag, EX_OK);
                 break;
             case 'p':
                 xml_file = "-";
                 break;
             case 'Q':
                 quiet = TRUE;
                 break;
             case 'L':
                 xml_file = NULL;
                 break;
             case 'x':
                 xml_file = optarg;
                 break;
             case 'u':
                 modified++;
                 node_up = g_list_append(node_up, optarg);
                 break;
             case 'd':
                 modified++;
                 node_down = g_list_append(node_down, optarg);
                 break;
             case 'f':
                 modified++;
                 node_fail = g_list_append(node_fail, optarg);
                 break;
             case 't':
                 use_date = strdup(optarg);
                 break;
             case 'i':
                 modified++;
                 op_inject = g_list_append(op_inject, optarg);
                 break;
             case 'F':
                 process = TRUE;
                 simulate = TRUE;
                 op_fail = g_list_append(op_fail, optarg);
                 break;
             case 'q':
                 modified++;
                 quorum = optarg;
                 break;
             case 'g':
                 modified++;
                 ticket_grant = g_list_append(ticket_grant, optarg);
                 break;
             case 'r':
                 modified++;
                 ticket_revoke = g_list_append(ticket_revoke, optarg);
                 break;
             case 'b':
                 modified++;
                 ticket_standby = g_list_append(ticket_standby, optarg);
                 break;
             case 'e':
                 modified++;
                 ticket_activate = g_list_append(ticket_activate, optarg);
                 break;
             case 'a':
                 all_actions = TRUE;
                 break;
             case 's':
                 process = TRUE;
                 show_scores = TRUE;
                 break;
             case 'U':
                 process = TRUE;
                 show_utilization = TRUE;
                 break;
             case 'S':
                 process = TRUE;
                 simulate = TRUE;
                 break;
             case 'X':
                 store = TRUE;
                 process = TRUE;
                 simulate = TRUE;
                 break;
             case 'R':
                 process = TRUE;
                 break;
             case 'D':
                 process = TRUE;
                 dot_file = optarg;
                 break;
             case 'G':
                 process = TRUE;
                 graph_file = optarg;
                 break;
             case 'I':
                 input_file = optarg;
                 break;
             case 'O':
                 output_file = optarg;
                 break;
             case 'P':
                 test_dir = optarg;
                 break;
             default:
                 ++argerr;
                 break;
         }
     }
 
     if (optind > argc) {
         ++argerr;
     }
 
     if (argerr) {
         crm_help('?', EX_USAGE);
     }
 
     if(test_dir != NULL) {
 	return profile_all(test_dir);
     }
 
     setup_input(xml_file, store ? xml_file : output_file);
 
     global_cib = cib_new();
     global_cib->cmds->signon(global_cib, crm_system_name, cib_command);
 
     set_working_set_defaults(&data_set);
 
     if (data_set.now != NULL) {
         quiet_log(" + Setting effective cluster time: %s", use_date);
         log_date(LOG_WARNING, "Set fake 'now' to", data_set.now, ha_log_date | ha_log_time);
     }
 
     rc = global_cib->cmds->query(global_cib, NULL, &input, cib_sync_call | cib_scope_local);
     CRM_ASSERT(rc == pcmk_ok);
 
     data_set.input = input;
     data_set.now = get_date();
     cluster_status(&data_set);
 
     if (quiet == FALSE) {
         quiet_log("\nCurrent cluster status:\n");
         print_cluster_status(&data_set);
     }
 
     if (modified) {
         quiet_log("Performing requested modifications\n");
         modify_configuration(&data_set, quorum, node_up, node_down, node_fail, op_inject,
                              ticket_grant, ticket_revoke, ticket_standby, ticket_activate);
 
         rc = global_cib->cmds->query(global_cib, NULL, &input, cib_sync_call);
         if (rc != pcmk_ok) {
             fprintf(stderr, "Could not connect to the CIB for input: %s\n", pcmk_strerror(rc));
             goto done;
         }
 
         cleanup_alloc_calculations(&data_set);
         data_set.now = get_date();
         data_set.input = input;
     }
 
     if (input_file != NULL) {
         rc = write_xml_file(input, input_file, FALSE);
         if (rc < 0) {
             fprintf(stderr, "Could not create '%s': %s\n", input_file, strerror(errno));
             goto done;
         }
     }
 
     rc = 0;
     if (process || simulate) {
         ha_time_t *local_date = NULL;
 
         if (show_scores && show_utilization) {
             printf("Allocation scores and utilization information:\n");
         } else if (show_scores) {
             fprintf(stdout, "Allocation scores:\n");
         } else if (show_utilization) {
             printf("Utilization information:\n");
         }
 
         do_calculations(&data_set, input, local_date);
         input = NULL;           /* Don't try and free it twice */
 
         if (graph_file != NULL) {
             char *msg_buffer = dump_xml_formatted(data_set.graph);
             FILE *graph_strm = fopen(graph_file, "w");
 
             if (graph_strm == NULL) {
                 crm_perror(LOG_ERR, "Could not open %s for writing", graph_file);
 
             } else {
                 if (fprintf(graph_strm, "%s\n\n", msg_buffer) < 0) {
                     crm_perror(LOG_ERR, "Write to %s failed", graph_file);
                 }
                 fflush(graph_strm);
                 fclose(graph_strm);
             }
             free(msg_buffer);
         }
 
         if (dot_file != NULL) {
             create_dotfile(&data_set, dot_file, all_actions);
         }
 
         if (quiet == FALSE) {
             GListPtr gIter = NULL;
 
             quiet_log("%sTransition Summary:\n", show_scores || show_utilization
                       || modified ? "\n" : "");
             fflush(stdout);
 
             for (gIter = data_set.resources; gIter != NULL; gIter = gIter->next) {
                 resource_t *rsc = (resource_t *) gIter->data;
 
                 LogActions(rsc, &data_set, TRUE);
             }
         }
     }
 
     if (simulate) {
         rc = run_simulation(&data_set);
     }
 
   done:
     cleanup_alloc_calculations(&data_set);
 
     global_cib->cmds->signoff(global_cib);
     cib_delete(global_cib);
     free(use_date);
     crm_xml_cleanup();
     fflush(stderr);
     qb_log_fini();
     return rc;
 }