diff --git a/crm/crmd/callbacks.c b/crm/crmd/callbacks.c index 1eb82fb222..3adbae95bf 100644 --- a/crm/crmd/callbacks.c +++ b/crm/crmd/callbacks.c @@ -1,401 +1,402 @@ /* * Copyright (C) 2004 Andrew Beekhof * * 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.1 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include FILE *msg_in_strm = NULL; FILE *msg_ipc_strm = NULL; xmlNodePtr find_xml_in_hamessage(const struct ha_msg* msg); gboolean crmd_ha_input_dispatch(int fd, gpointer user_data); void crmd_ha_input_destroy(gpointer user_data); void crmd_ha_input_callback(const struct ha_msg* msg, void* private_data) { const char *from = ha_msg_value(msg, F_ORIG); const char *to = NULL; xmlNodePtr root_xml_node; #ifdef MSG_LOG if(msg_in_strm == NULL) { msg_in_strm = fopen(DEVEL_DIR"/inbound.log", "w"); } #endif if(safe_str_eq(from, fsa_our_uname)) { #ifdef MSG_LOG fprintf(msg_in_strm, "Discarded message [F_SEQ=%s] from ourselves.\n", ha_msg_value(msg, F_SEQ)); fflush(msg_in_strm); #endif return; } else if(from == NULL) { crm_err("Value of %s was NULL", F_ORIG); } #ifdef MSG_LOG fprintf(msg_in_strm, "[%s (%s:%s)]\t%s\n", crm_str(from), ha_msg_value(msg, F_SEQ), ha_msg_value(msg, F_TYPE), ha_msg_value(msg, "xml") ); fflush(msg_in_strm); #endif root_xml_node = find_xml_in_hamessage(msg); to = xmlGetProp(root_xml_node, XML_ATTR_HOSTTO); if(to != NULL && strlen(to) > 0 && strcmp(to, fsa_our_uname) != 0) { #ifdef MSG_LOG fprintf(msg_in_strm, "Discarding message [F_SEQ=%s] for someone else.", ha_msg_value(msg, F_SEQ)); #endif return; } set_xml_property_copy(root_xml_node, XML_ATTR_HOSTFROM, from); s_crmd_fsa(C_HA_MESSAGE, I_ROUTER, root_xml_node); free_xml(root_xml_node); return; } /* * Apparently returning TRUE means "stay connected, keep doing stuff". * Returning FALSE means "we're all done, close the connection" */ gboolean crmd_ipc_input_callback(IPC_Channel *client, gpointer user_data) { int lpc = 0; char *buffer = NULL; IPC_Message *msg = NULL; gboolean hack_return_good = TRUE; xmlNodePtr root_xml_node; crmd_client_t *curr_client = (crmd_client_t*)user_data; crm_verbose("Processing IPC message from %s", curr_client->table_key); #ifdef MSG_LOG if(msg_ipc_strm == NULL) { msg_ipc_strm = fopen(DEVEL_DIR"/inbound.ipc.log", "w"); } #endif while(client->ops->is_message_pending(client)) { if (client->ch_status == IPC_DISCONNECT) { /* The message which was pending for us is that * the IPC status is now IPC_DISCONNECT */ break; } if (client->ops->recv(client, &msg) != IPC_OK) { perror("Receive failure:"); #ifdef MSG_LOG fprintf(msg_ipc_strm, "[%s] [receive failure]\n", curr_client->table_key); fflush(msg_in_strm); #endif return !hack_return_good; } if (msg == NULL) { #ifdef MSG_LOG fprintf(msg_ipc_strm, "[%s] [__nothing__]\n", curr_client->table_key); fflush(msg_in_strm); #endif crm_err("No message this time"); continue; } lpc++; buffer = (char*)msg->msg_body; crm_verbose("Processing xml from %s [text=%s]\n", curr_client->table_key, buffer); #ifdef MSG_LOG fprintf(msg_ipc_strm, "[%s] [text=%s]\n", curr_client->table_key, buffer); fflush(msg_in_strm); #endif root_xml_node = find_xml_in_ipcmessage(msg, FALSE); if (root_xml_node != NULL) { if (crmd_authorize_message( root_xml_node, msg, curr_client)) { s_crmd_fsa( C_IPC_MESSAGE,I_ROUTER,root_xml_node); } } else { crm_info("IPC Message was not valid... discarding."); } free_xml(root_xml_node); msg->msg_done(msg); msg = NULL; buffer = NULL; root_xml_node = NULL; } crm_verbose("Processed %d messages", lpc); if (client->ch_status == IPC_DISCONNECT) { crm_info("received HUP from %s", curr_client->table_key); if (curr_client != NULL) { struct crm_subsystem_s *the_subsystem = NULL; if (curr_client->sub_sys == NULL) { crm_warn("Client hadn't registered with us yet"); } else if (strcmp(CRM_SYSTEM_PENGINE, curr_client->sub_sys) == 0) { the_subsystem = pe_subsystem; } else if (strcmp(CRM_SYSTEM_TENGINE, curr_client->sub_sys) == 0) { the_subsystem = te_subsystem; } else if (strcmp(CRM_SYSTEM_CIB, curr_client->sub_sys) == 0){ the_subsystem = cib_subsystem; } if(the_subsystem != NULL) { cleanup_subsystem(the_subsystem); } /* else that was a transient client */ if (curr_client->table_key != NULL) { /* * Key is destroyed below: * curr_client->table_key * Value is cleaned up by: * G_main_del_IPC_Channel */ g_hash_table_remove( ipc_clients, curr_client->table_key); } if(curr_client->client_source != NULL) { gboolean det = G_main_del_IPC_Channel( curr_client->client_source); crm_verbose("crm_client was %s detached", det?"successfully":"not"); } crm_free(curr_client->table_key); crm_free(curr_client->sub_sys); crm_free(curr_client->uuid); crm_free(curr_client); } return !hack_return_good; } return hack_return_good; } void lrm_op_callback (lrm_op_t* op) { s_crmd_fsa(C_LRM_OP_CALLBACK, I_LRM_EVENT, op); } void crmd_client_status_callback(const char * node, const char * client, const char * status, void * private) { const char *join = NULL; const char *extra = NULL; xmlNodePtr update = NULL; xmlNodePtr fragment = NULL; xmlNodePtr msg_options = NULL; xmlNodePtr request = NULL; if(safe_str_eq(status, JOINSTATUS)){ status = ONLINESTATUS; extra = XML_CIB_ATTR_CLEAR_SHUTDOWN; } else if(safe_str_eq(status, LEAVESTATUS)){ status = OFFLINESTATUS; join = CRMD_JOINSTATE_DOWN; extra = XML_CIB_ATTR_CLEAR_SHUTDOWN; } crm_notice("Status update: Client %s/%s now has status [%s]\n", node, client, status); if(AM_I_DC) { update = create_node_state(node, node, NULL, status, join); if(extra != NULL) { set_xml_property_copy(update, extra, XML_BOOLEAN_TRUE); } fragment = create_cib_fragment(update, NULL); /* store_request(NULL, fragment, */ /* CRM_OP_UPDATE, CRM_SYSTEM_DCIB); */ msg_options = set_xml_attr( NULL, XML_TAG_OPTIONS, XML_ATTR_OP, CRM_OP_UPDATE, TRUE); /* crm_verbose("Storing op=%s message for later processing", operation); */ request = create_request( - msg_options, fragment, NULL, CRM_SYSTEM_DCIB, CRM_SYSTEM_DC, NULL, NULL); + msg_options, fragment, NULL, + CRM_SYSTEM_DCIB, CRM_SYSTEM_DC, NULL, NULL); free_xml(fragment); free_xml(update); /* s_crmd_fsa(C_CRMD_STATUS_CALLBACK, I_NULL, NULL); */ s_crmd_fsa(C_CRMD_STATUS_CALLBACK, I_CIB_OP, request); } else { crm_err("Got client status callback in non-DC mode"); } } xmlNodePtr find_xml_in_hamessage(const struct ha_msg* msg) { const char *xml; xmlDocPtr doc; xmlNodePtr root; if (msg == NULL) { crm_info("**** ha_crm_msg_callback called on a NULL message"); return NULL; } #if 0 crm_debug("[F_TYPE=%s]", ha_msg_value(msg, F_TYPE)); crm_debug("[F_ORIG=%s]", ha_msg_value(msg, F_ORIG)); crm_debug("[F_TO=%s]", ha_msg_value(msg, F_TO)); crm_debug("[F_COMMENT=%s]", ha_msg_value(msg, F_COMMENT)); crm_debug("[F_XML=%s]", ha_msg_value(msg, "xml")); /* crm_debug("[F_=%s]", ha_msg_value(ha_msg, F_)); */ #endif if (strcmp("CRM", ha_msg_value(msg, F_TYPE)) != 0) { crm_info("Received a (%s) message by mistake.", ha_msg_value(msg, F_TYPE)); return NULL; } xml = ha_msg_value(msg, "xml"); if (xml == NULL) { crm_info("No XML attached to this message."); return NULL; } doc = xmlParseMemory(xml, strlen(xml)); if (doc == NULL) { crm_info("XML Buffer was not valid."); return NULL; } root = xmlDocGetRootElement(doc); if (root == NULL) { crm_info("Root node was NULL."); return NULL; } return root; } gboolean lrm_dispatch(int fd, gpointer user_data) { ll_lrm_t *lrm = (ll_lrm_t*)user_data; lrm->lrm_ops->rcvmsg(lrm, FALSE); return TRUE; } #define MAX_EMPTY_CALLBACKS 20 int empty_callbacks = 0; gboolean crmd_ha_input_dispatch(int fd, gpointer user_data) { int lpc = 0; ll_cluster_t *hb_cluster = (ll_cluster_t*)user_data; while(hb_cluster->llc_ops->msgready(hb_cluster)) { lpc++; empty_callbacks = 0; /* invoke the callbacks but dont block */ hb_cluster->llc_ops->rcvmsg(hb_cluster, 0); } if(lpc == 0) { /* hey what happened?? */ crm_warn("We were called but no message was ready." " Likely the connection to Heartbeat failed," " check the logs."); if(empty_callbacks++ > MAX_EMPTY_CALLBACKS) { crm_err("%d empty callbacks received..." " considering heartbeat dead", MAX_EMPTY_CALLBACKS); /* s_crmd_fsa(C_HA_DISCONNECT, I_ERROR, NULL); */ return FALSE; } } return TRUE; } void crmd_ha_input_destroy(gpointer user_data) { crm_crit("Heartbeat has left us"); /* this is always an error */ /* feed this back into the FSA */ s_crmd_fsa(C_HA_DISCONNECT, I_ERROR, NULL); } diff --git a/crm/crmd/control.c b/crm/crmd/control.c index 6a5775bc14..86bd17f9d3 100644 --- a/crm/crmd/control.c +++ b/crm/crmd/control.c @@ -1,579 +1,578 @@ /* * Copyright (C) 2004 Andrew Beekhof * * 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.1 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include extern gboolean crmd_ha_input_dispatch(int fd, gpointer user_data); extern void crmd_ha_input_destroy(gpointer user_data); void crm_shutdown(int nsig); IPC_WaitConnection *wait_channel_init(char daemonsocket[]); int init_server_ipc_comms( const char *child, gboolean (*channel_client_connect)(IPC_Channel *newclient, gpointer user_data), void (*channel_input_destroy)(gpointer user_data)); gboolean register_with_ha(ll_cluster_t *hb_cluster, const char *client_name, gboolean (*dispatch_method)(int fd, gpointer user_data), void (*message_callback)(const struct ha_msg* msg, void* private_data), GDestroyNotify cleanup_method); GHashTable *ipc_clients = NULL; /* A_HA_CONNECT */ enum crmd_fsa_input do_ha_control(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { gboolean registered = FALSE; if(action & A_HA_DISCONNECT) { if(fsa_cluster_conn != NULL) { fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn); } } if(action & A_HA_CONNECT) { if(fsa_cluster_conn == NULL) fsa_cluster_conn = ll_cluster_new("heartbeat"); /* make sure we are disconnected first */ fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn); registered = register_with_ha(fsa_cluster_conn, crm_system_name, crmd_ha_input_dispatch, crmd_ha_input_callback, crmd_ha_input_destroy); if(registered == FALSE) { return I_FAIL; } } if(action & ~(A_HA_CONNECT|A_HA_DISCONNECT)) { crm_err("Unexpected action %s in %s", fsa_action2string(action), __FUNCTION__); } return I_NULL; } /* A_SHUTDOWN */ enum crmd_fsa_input do_shutdown(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { enum crmd_fsa_input next_input = I_NULL; enum crmd_fsa_input tmp = I_NULL; /* last attempt to shut these down */ if(is_set(fsa_input_register, R_PE_CONNECTED)) { crm_warn("Last attempt to shutdown the PolicyEngine"); tmp = do_pe_control(A_PE_STOP, cause, cur_state, current_input, data); if(tmp != I_NULL) { next_input = I_ERROR; crm_err("Failed to shutdown the PolicyEngine"); } } if(is_set(fsa_input_register, R_TE_CONNECTED)) { crm_warn("Last attempt to shutdown the Transitioner"); tmp = do_pe_control(A_TE_STOP, cause, cur_state, current_input, data); if(tmp != I_NULL) { next_input = I_ERROR; crm_err("Failed to shutdown the Transitioner"); } } /* TODO: shutdown all remaining resources? */ return next_input; } /* A_SHUTDOWN_REQ */ enum crmd_fsa_input do_shutdown_req(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { enum crmd_fsa_input next_input = I_NULL; if(send_request(NULL, NULL, CRM_OP_SHUTDOWN_REQ, NULL, CRM_SYSTEM_DC, NULL) == FALSE){ next_input = I_ERROR; } return next_input; } /* A_EXIT_0, A_EXIT_1 */ enum crmd_fsa_input do_exit(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { crm_err("Action %s (%.16llx) not supported\n", fsa_action2string(action), action); if(action & A_EXIT_0) { g_main_quit(crmd_mainloop); } else { exit(1); } return I_NULL; } /* A_STARTUP */ enum crmd_fsa_input do_startup(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { int facility; int was_error = 0; int interval = 1; /* seconds between DC heartbeats */ fsa_input_register = 0; /* zero out the regester */ crm_info("Register PID"); register_pid(PID_FILE, FALSE, crm_shutdown); ipc_clients = g_hash_table_new(&g_str_hash, &g_str_equal); /* change the logging facility to the one used by heartbeat daemon */ fsa_cluster_conn = ll_cluster_new("heartbeat"); crm_info("Switching to Heartbeat logger"); if ((facility = fsa_cluster_conn->llc_ops->get_logfacility( fsa_cluster_conn)) > 0) { cl_log_set_facility(facility); } crm_verbose("Facility: %d", facility); if(was_error == 0) { crm_info("Init server comms"); was_error = init_server_ipc_comms( CRM_SYSTEM_CRMD, crmd_client_connect, default_ipc_input_destroy); } /* set up the timers */ crm_malloc(dc_heartbeat, sizeof(fsa_timer_t)); crm_malloc(integration_timer, sizeof(fsa_timer_t)); crm_malloc(election_trigger, sizeof(fsa_timer_t)); crm_malloc(election_timeout, sizeof(fsa_timer_t)); crm_malloc(shutdown_escalation_timmer, sizeof(fsa_timer_t)); interval = interval * 1000; if(election_trigger != NULL) { election_trigger->source_id = -1; election_trigger->period_ms = -1; election_trigger->fsa_input = I_DC_TIMEOUT; election_trigger->callback = timer_popped; } else { was_error = TRUE; } if(dc_heartbeat != NULL) { dc_heartbeat->source_id = -1; dc_heartbeat->period_ms = -1; dc_heartbeat->fsa_input = I_NULL; dc_heartbeat->callback = do_dc_heartbeat; } else { was_error = TRUE; } if(election_timeout != NULL) { election_timeout->source_id = -1; election_timeout->period_ms = -1; election_timeout->fsa_input = I_ELECTION_DC; election_timeout->callback = timer_popped; } else { was_error = TRUE; } if(integration_timer != NULL) { integration_timer->source_id = -1; integration_timer->period_ms = -1; integration_timer->fsa_input = I_INTEGRATION_TIMEOUT; integration_timer->callback = timer_popped; } else { was_error = TRUE; } if(shutdown_escalation_timmer != NULL) { shutdown_escalation_timmer->source_id = -1; shutdown_escalation_timmer->period_ms = -1; shutdown_escalation_timmer->fsa_input = I_TERMINATE; shutdown_escalation_timmer->callback = timer_popped; } else { was_error = TRUE; } /* set up the sub systems */ crm_malloc(cib_subsystem, sizeof(struct crm_subsystem_s)); crm_malloc(te_subsystem, sizeof(struct crm_subsystem_s)); crm_malloc(pe_subsystem, sizeof(struct crm_subsystem_s)); if(cib_subsystem != NULL) { cib_subsystem->pid = 0; cib_subsystem->respawn = 1; cib_subsystem->path = crm_strdup(BIN_DIR); cib_subsystem->name = crm_strdup(CRM_SYSTEM_CIB); cib_subsystem->command = BIN_DIR"/cib"; cib_subsystem->flag = R_CIB_CONNECTED; } else { was_error = TRUE; } if(te_subsystem != NULL) { te_subsystem->pid = 0; te_subsystem->respawn = 1; te_subsystem->path = crm_strdup(BIN_DIR); te_subsystem->name = crm_strdup(CRM_SYSTEM_TENGINE); te_subsystem->command = BIN_DIR"/tengine"; te_subsystem->flag = R_TE_CONNECTED; } else { was_error = TRUE; } if(pe_subsystem != NULL) { pe_subsystem->pid = 0; pe_subsystem->respawn = 1; pe_subsystem->path = crm_strdup(BIN_DIR); pe_subsystem->name = crm_strdup(CRM_SYSTEM_PENGINE); pe_subsystem->command = BIN_DIR"/pengine"; pe_subsystem->flag = R_PE_CONNECTED; } else { was_error = TRUE; } if(was_error) return I_FAIL; return I_NULL; } /* A_STOP */ enum crmd_fsa_input do_stop(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { crm_err("Action %s (%.16llx) not supported\n", fsa_action2string(action), action); return I_NULL; } /* A_STARTED */ enum crmd_fsa_input do_started(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { clear_bit_inplace(&fsa_input_register, R_STARTING); return I_NULL; } /* A_RECOVER */ enum crmd_fsa_input do_recover(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { crm_err("Action %s (%.16llx) not supported\n", fsa_action2string(action), action); return I_SHUTDOWN; } /* A_READCONFIG */ enum crmd_fsa_input do_read_config(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { xmlNodePtr cib_copy = get_cib_copy(); xmlNodePtr config = get_object_root(XML_CIB_TAG_CRMCONFIG, cib_copy); xml_child_iter( config, iter, XML_CIB_TAG_NVPAIR, const char *name = xmlGetProp(iter, XML_NVPAIR_ATTR_NAME); const char *value = xmlGetProp(iter, XML_NVPAIR_ATTR_VALUE); if(name == NULL || value == NULL) { - xml_iter_continue(iter); continue; } else if(safe_str_eq(name, "dc_heartbeat")) { dc_heartbeat->period_ms = atoi(value); } else if(safe_str_eq(name, "dc_deadtime")) { election_trigger->period_ms = atoi(value); } else if(safe_str_eq(name, "shutdown_escalation")) { shutdown_escalation_timmer->period_ms = atoi(value); } ); if(dc_heartbeat->period_ms < 1) { /* sensible default */ dc_heartbeat->period_ms = 1000; } if(election_trigger->period_ms < 1) { /* sensible default */ election_trigger->period_ms = dc_heartbeat->period_ms * 4; } if(shutdown_escalation_timmer->period_ms < 1) { /* sensible default */ shutdown_escalation_timmer->period_ms = election_trigger->period_ms * 3 *10;/* 10 for testing */ } election_timeout->period_ms = dc_heartbeat->period_ms * 6; integration_timer->period_ms = dc_heartbeat->period_ms * 6; return I_NULL; } void crm_shutdown(int nsig) { CL_SIGNAL(nsig, crm_shutdown); if (crmd_mainloop != NULL && g_main_is_running(crmd_mainloop)) { if(is_set(fsa_input_register, R_SHUTDOWN)) { crm_err("Escalating the shutdown"); s_crmd_fsa(C_SHUTDOWN, I_ERROR, NULL); } else { set_bit_inplace(&fsa_input_register, R_SHUTDOWN); if(is_set(fsa_input_register, R_SHUTDOWN)) { /* cant rely on this... */ startTimer(shutdown_escalation_timmer); s_crmd_fsa(C_SHUTDOWN, I_SHUTDOWN, NULL); } else { crm_err("Could not set R_SHUTDOWN"); exit(LSB_EXIT_ENOTSUPPORTED); } } } else { crm_info("exit from shutdown"); exit(LSB_EXIT_OK); } return; } IPC_WaitConnection * wait_channel_init(char daemonsocket[]) { IPC_WaitConnection *wait_ch; mode_t mask; char path[] = IPC_PATH_ATTR; GHashTable * attrs; attrs = g_hash_table_new(g_str_hash,g_str_equal); g_hash_table_insert(attrs, path, daemonsocket); mask = umask(0); wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs); if (wait_ch == NULL) { cl_perror("Can't create wait channel of type %s", IPC_ANYTYPE); exit(1); } mask = umask(mask); g_hash_table_destroy(attrs); return wait_ch; } int init_server_ipc_comms( const char *child, gboolean (*channel_client_connect)(IPC_Channel *newclient, gpointer user_data), void (*channel_input_destroy)(gpointer user_data)) { /* the clients wait channel is the other source of events. * This source delivers the clients connection events. * listen to this source at a relatively lower priority. */ char commpath[SOCKET_LEN]; IPC_WaitConnection *wait_ch; sprintf(commpath, WORKING_DIR "/%s", child); wait_ch = wait_channel_init(commpath); if (wait_ch == NULL) return 1; G_main_add_IPC_WaitConnection(G_PRIORITY_LOW, wait_ch, NULL, FALSE, channel_client_connect, wait_ch, /* user data passed to ?? */ channel_input_destroy); crm_debug("Listening on: %s", commpath); return 0; } #define safe_val3(def, t,u,v) (t?t->u?t->u->v:def:def) gboolean register_with_ha(ll_cluster_t *hb_cluster, const char *client_name, gboolean (*dispatch_method)(int fd, gpointer user_data), void (*message_callback)(const struct ha_msg* msg, void* private_data), GDestroyNotify cleanup_method) { if(safe_val3(NULL, hb_cluster, llc_ops, errmsg) == NULL) { crm_crit("cluster errmsg function unavailable"); } crm_info("Signing in with Heartbeat"); if (hb_cluster->llc_ops->signon(hb_cluster, client_name)!= HA_OK) { crm_err("Cannot sign on with heartbeat"); if(safe_val3(NULL, hb_cluster, llc_ops, errmsg) == NULL) { crm_crit("cluster errmsg function unavailable"); } else { crm_err("REASON: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); } return FALSE; } crm_debug("Be informed of CRM messages"); if (hb_cluster->llc_ops->set_msg_callback(hb_cluster, "CRM", message_callback, hb_cluster) !=HA_OK){ crm_err("Cannot set CRM message callback"); if(safe_val3(NULL, hb_cluster, llc_ops, errmsg) == NULL) { crm_crit("cluster errmsg function unavailable"); } else { crm_err("REASON: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); } return FALSE; } G_main_add_fd(G_PRIORITY_HIGH, hb_cluster->llc_ops->inputfd(hb_cluster), FALSE, dispatch_method, hb_cluster, /* usrdata */ cleanup_method); crm_debug("Finding our node name"); if ((fsa_our_uname = hb_cluster->llc_ops->get_mynodeid(hb_cluster)) == NULL) { crm_err("get_mynodeid() failed"); return FALSE; } crm_info("FSA Hostname: %s", fsa_our_uname); return TRUE; } diff --git a/crm/crmd/join.c b/crm/crmd/join.c index 47451a68fe..d0a8203a2c 100644 --- a/crm/crmd/join.c +++ b/crm/crmd/join.c @@ -1,406 +1,406 @@ /* * Copyright (C) 2004 Andrew Beekhof * * 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.1 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include GHashTable *joined_nodes = NULL; /* A_JOIN_WELCOME */ enum crmd_fsa_input do_send_welcome(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { xmlNodePtr update = NULL; xmlNodePtr welcome = NULL; xmlNodePtr tmp1 = NULL; xmlNodePtr tmp2 = NULL; const char *join_to = NULL; if(action & A_JOIN_WELCOME && data == NULL) { crm_err("Attempt to send welcome message " "without a message to reply to!"); return I_NULL; /* return do_send_welcome_all( */ /* A_JOIN_WELCOME_ALL,cause,cur_state,current_input,data); */ } else if(action & A_JOIN_WELCOME) { welcome = (xmlNodePtr)data; join_to = xmlGetProp(welcome, XML_ATTR_HOSTFROM); if(join_to != NULL) { stopTimer(integration_timer); /* update node status */ crm_debug("Updating node state to %s for %s", CRMD_JOINSTATE_PENDING, join_to); update = create_node_state( join_to, join_to, NULL, NULL, CRMD_JOINSTATE_PENDING); tmp1 = create_cib_fragment(update, NULL); invoke_local_cib(NULL, tmp1, CRM_OP_UPDATE); free_xml(tmp1); /* Make sure they have the *whole* CIB */ crm_debug("Sending complete CIB to %s", join_to); tmp1 = get_cib_copy(); tmp2 = create_cib_fragment(tmp1, NULL); send_request(NULL, tmp2, CRM_OP_REPLACE, join_to, CRM_SYSTEM_CRMD, NULL); free_xml(tmp1); free_xml(tmp2); /* send the welcome */ crm_debug("Sending %s to %s", CRM_OP_WELCOME, join_to); send_request(NULL, NULL, CRM_OP_WELCOME, join_to, CRM_SYSTEM_CRMD, NULL); free_xml(update); /* if this client is sick, we shouldnt wait forever */ crm_debug("Restarting the integration timer"); startTimer(integration_timer); } else { crm_err("No recipient for welcome message"); } return I_NULL; } return I_ERROR; } /* A_JOIN_WELCOME_ALL */ enum crmd_fsa_input do_send_welcome_all(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { /* reset everyones status back to down or in_ccm in the CIB */ xmlNodePtr update = NULL; xmlNodePtr cib_copy = get_cib_copy(); xmlNodePtr tmp1 = get_object_root(XML_CIB_TAG_STATUS, cib_copy); xmlNodePtr tmp2 = NULL; /* Give everyone a chance to join before invoking the PolicyEngine */ stopTimer(integration_timer); startTimer(integration_timer); if(joined_nodes != NULL) { g_hash_table_destroy(joined_nodes); joined_nodes = g_hash_table_new(&g_str_hash, &g_str_equal); } /* catch any nodes that are active in the CIB but not in the CCM list*/ xml_child_iter( tmp1, node_entry, XML_CIB_TAG_STATE, const char *node_id = xmlGetProp(node_entry, XML_ATTR_UNAME); gpointer a_node = g_hash_table_lookup( fsa_membership_copy->members, node_id); if(a_node != NULL || (safe_str_eq(fsa_our_uname, node_id))) { /* handled by do_update_cib_node() */ - xml_iter_continue(node_entry); + continue; } tmp2 = create_node_state( node_id, node_id, XML_BOOLEAN_NO, NULL, CRMD_JOINSTATE_DOWN); if(update == NULL) { update = tmp2; } else { update = xmlAddSibling(update, tmp2); } ); /* now process the CCM data */ free_xml(do_update_cib_nodes(update, TRUE)); free_xml(cib_copy); /* Make sure everyone has the *whole* CIB */ tmp1 = get_cib_copy(); tmp2 = create_cib_fragment(tmp1, NULL); send_request(NULL, tmp2, CRM_OP_REPLACE, NULL, CRM_SYSTEM_CRMD, NULL); free_xml(tmp1); free_xml(tmp2); /* Avoid ordered message delays caused when the CRMd proc * isnt running yet (ie. send as a broadcast msg which are never * sent ordered. */ send_request(NULL, NULL, CRM_OP_WELCOME, NULL, CRM_SYSTEM_CRMD, NULL); /* No point hanging around in S_INTEGRATION if we're the only ones here! */ if(joined_nodes == NULL) { if(fsa_membership_copy->members_size == 1) { /* we're the only ones in here */ crm_info("Not expecting any join acks"); return I_SUCCESS; } } else if(g_hash_table_size(joined_nodes) >= (fsa_membership_copy->members_size -1)) { crm_info("That was the last outstanding join ack"); return I_SUCCESS; } /* dont waste time by invoking the pe yet; */ crm_debug("Still waiting on %d outstanding join acks", fsa_membership_copy->members_size - g_hash_table_size(joined_nodes) - 1); return I_NULL; } /* A_JOIN_ACK */ enum crmd_fsa_input do_ack_welcome(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { xmlNodePtr welcome = (xmlNodePtr)data; xmlNodePtr cib_copy; xmlNodePtr tmp1; xmlNodePtr tmp2; #if 0 if(we are sick) { log error ; return I_NULL; } #endif fsa_our_dc = xmlGetProp(welcome, XML_ATTR_HOSTFROM); if(fsa_our_dc == NULL) { crm_err("Failed to determin our DC"); return I_FAIL; } /* send our status section to the DC */ cib_copy = get_cib_copy(); tmp1 = get_object_root(XML_CIB_TAG_STATUS, cib_copy); if(tmp1 != NULL) { tmp2 = create_cib_fragment(tmp1->children, NULL); send_ha_reply(fsa_cluster_conn, welcome, tmp2); free_xml(tmp2); } free_xml(cib_copy); return I_NULL; } /* A_ANNOUNCE */ enum crmd_fsa_input do_announce(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { xmlNodePtr msg = (xmlNodePtr)data; /* Once we hear from the DC, we can stop the timer * * This timer was started either on startup or when a node * left the CCM list */ /* dont announce if we're in one of these states */ switch(cur_state) { case S_RECOVERY: case S_RECOVERY_DC: case S_RELEASE_DC: case S_TERMINATE: crm_warn("Do not announce ourselves in state %s", fsa_state2string(cur_state)); return I_NULL; break; default: break; } if(AM_I_OPERATIONAL) { const char *from = xmlGetProp(msg, XML_ATTR_HOSTFROM); if(from == NULL) { crm_err("Failed to origin of ping message"); return I_FAIL; } send_request(NULL, NULL, CRM_OP_ANNOUNCE, from, CRM_SYSTEM_DC, NULL); } else { /* Delay announce until we have finished local startup */ crm_warn("Delaying announce until local startup is complete"); return I_NULL; } return I_NULL; } /* A_JOIN_PROCESS_ACK */ enum crmd_fsa_input do_process_welcome_ack(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, void *data) { xmlNodePtr tmp1; xmlNodePtr tmp2; xmlNodePtr cib_fragment; xmlNodePtr msg_cib; xmlNodePtr join_ack = (xmlNodePtr)data; gboolean is_a_member = FALSE; const char *join_from = xmlGetProp(join_ack, XML_ATTR_HOSTFROM); const char *ref = xmlGetProp(join_ack, XML_ATTR_REFERENCE); uuid_t uuid_raw; char *uuid_calc = NULL; gpointer join_node = g_hash_table_lookup(fsa_membership_copy->members, join_from); if(join_node != NULL) { is_a_member = TRUE; } cib_fragment = find_xml_node(join_ack, XML_TAG_FRAGMENT); crm_debug("Welcoming node %s after ACK (ref %s)", join_from, ref); if(is_a_member == FALSE) { crm_err("Node %s is not known to us (ref %s)", join_from, ref); /* make sure any information from this node is discarded, * it is invalid */ free_xml(cib_fragment); return I_FAIL; } /* add them to our list of CRMD_STATE_ACTIVE nodes TODO: still used? TODO: check its not already there */ g_hash_table_insert(joined_nodes, strdup(join_from),strdup(join_from)); if(cib_fragment == NULL) { crm_err("No status information was part of the" " Welcome ACK from %s", join_from); return I_NULL; } create_node_entry(join_from, join_from, "member"); crm_malloc(uuid_calc, sizeof(char)*50); if(uuid_calc != NULL) { if(fsa_cluster_conn->llc_ops->get_uuid_by_name( fsa_cluster_conn, join_from, uuid_raw) == HA_FAIL) { crm_err("Could not calculate UUID for %s", join_from); crm_free(uuid_calc); uuid_calc = crm_strdup(join_from); } else { uuid_unparse(uuid_raw, uuid_calc); } } /* Make changes so that exp_state=active for this node when the update * is processed by A_CIB_INVOKE */ msg_cib = find_xml_node(cib_fragment, XML_TAG_CIB); tmp1 = get_object_root(XML_CIB_TAG_STATUS, msg_cib); tmp2 = find_entity(tmp1, XML_CIB_TAG_STATE, uuid_calc, FALSE); if(tmp2 == NULL) { crm_err("Status entry for %s not found in update, adding", join_from); tmp2 = create_xml_node(tmp1, XML_CIB_TAG_STATE); set_xml_property_copy(tmp2, XML_ATTR_UUID, uuid_calc); set_xml_property_copy(tmp2, XML_ATTR_UNAME, join_from); } crm_free(uuid_calc); /* make sure these values are correct in the CIB */ set_xml_property_copy( tmp2, XML_CIB_ATTR_EXPSTATE, CRMD_STATE_ACTIVE); set_xml_property_copy( tmp2, XML_CIB_ATTR_JOINSTATE,CRMD_JOINSTATE_MEMBER); /* No point hanging around in S_INTEGRATION if we're the only ones here! */ if(g_hash_table_size(joined_nodes) >= (fsa_membership_copy->members_size -1)) { crm_info("That was the last outstanding join ack"); return I_SUCCESS; } /* dont waste time by invoking the pe yet; */ crm_debug("Still waiting on %d outstanding join acks", fsa_membership_copy->members_size - g_hash_table_size(joined_nodes) - 1); return I_CIB_OP; } diff --git a/crm/crmd/utils.c b/crm/crmd/utils.c index fcc7eee7e4..8f223e4905 100644 --- a/crm/crmd/utils.c +++ b/crm/crmd/utils.c @@ -1,716 +1,719 @@ /* * Copyright (C) 2004 Andrew Beekhof * * 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.1 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include gboolean timer_popped(gpointer data) { fsa_timer_t *timer = (fsa_timer_t *)data; crm_info("#!!#!!# Timer %s just popped!", fsa_input2string(timer->fsa_input)); stopTimer(timer); /* dont make it go off again */ s_crmd_fsa(C_TIMER_POPPED, timer->fsa_input, NULL); return TRUE; } gboolean startTimer(fsa_timer_t *timer) { if(((int)timer->source_id) < 0 && timer->period_ms > 0) { timer->source_id = Gmain_timeout_add(timer->period_ms, timer->callback, (void*)timer); /* crm_verbose("#!!#!!# Started %s timer (%d)", fsa_input2string(timer->fsa_input), timer->source_id); */ } else if(timer->period_ms < 0) { crm_err("Tried to start timer %s with -ve period", fsa_input2string(timer->fsa_input)); } else { crm_info("#!!#!!# Timer %s already running (%d)", fsa_input2string(timer->fsa_input), timer->source_id); return FALSE; } return TRUE; } gboolean stopTimer(fsa_timer_t *timer) { if(((int)timer->source_id) > 0) { /* crm_verbose("#!!#!!# Stopping %s timer (%d)", fsa_input2string(timer->fsa_input), timer->source_id); */ g_source_remove(timer->source_id); timer->source_id = -2; } else { crm_info("#!!#!!# Timer %s already stopped (%d)", fsa_input2string(timer->fsa_input), timer->source_id); return FALSE; } return TRUE; } long long toggle_bit(long long action_list, long long action) { crm_trace("Toggling bit %.16llx", action); action_list ^= action; crm_trace("Result %.16llx", action_list & action); return action_list; } long long clear_bit(long long action_list, long long action) { crm_trace("Clearing bit\t%.16llx", action); /* ensure its set */ action_list |= action; /* then toggle */ action_list = action_list ^ action; return action_list; } long long set_bit(long long action_list, long long action) { crm_trace("Adding bit\t%.16llx", action); action_list |= action; return action_list; } void toggle_bit_inplace(long long *action_list, long long action) { *action_list = toggle_bit(*action_list, action); } void clear_bit_inplace(long long *action_list, long long action) { *action_list = clear_bit(*action_list, action); } void set_bit_inplace(long long *action_list, long long action) { *action_list = set_bit(*action_list, action); } gboolean is_set(long long action_list, long long action) { /* crm_verbose("Checking bit\t%.16llx", action); */ return ((action_list & action) == action); } const char * fsa_input2string(enum crmd_fsa_input input) { const char *inputAsText = NULL; switch(input){ case I_NULL: inputAsText = "I_NULL"; break; case I_CCM_EVENT: inputAsText = "I_CCM_EVENT"; break; case I_CIB_OP: inputAsText = "I_CIB_OP"; 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_INTEGRATION_TIMEOUT: inputAsText = "I_INTEGRATION_TIMEOUT"; break; case I_NODE_JOIN: inputAsText = "I_NODE_JOIN"; break; case I_NODE_LEFT: inputAsText = "I_NODE_LEFT"; 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_REQUEST: inputAsText = "I_REQUEST"; break; case I_ROUTER: inputAsText = "I_ROUTER"; break; case I_SHUTDOWN: inputAsText = "I_SHUTDOWN"; break; case I_STARTUP: inputAsText = "I_STARTUP"; break; case I_SUCCESS: inputAsText = "I_SUCCESS"; break; case I_TERMINATE: inputAsText = "I_TERMINATE"; break; case I_WELCOME: inputAsText = "I_WELCOME"; break; case I_WELCOME_ACK: inputAsText = "I_WELCOME_ACK"; 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_ILLEGAL: inputAsText = "I_ILLEGAL"; break; } if(inputAsText == NULL) { crm_err("Input %d is unknown", input); inputAsText = ""; } 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_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_RECOVERY_DC: stateAsText = "S_RECOVERY_DC"; 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_ILLEGAL: stateAsText = "S_ILLEGAL"; break; } if(stateAsText == NULL) { crm_err("State %d is unknown", state); stateAsText = ""; } 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_ILLEGAL: causeAsText = "C_ILLEGAL"; break; } if(causeAsText == NULL) { crm_err("Cause %d is unknown", cause); causeAsText = ""; } return causeAsText; } const char * fsa_action2string(long long action) { const char *actionAsText = NULL; switch(action){ case A_NOTHING: actionAsText = "A_NOTHING"; break; case A_READCONFIG: actionAsText = "A_READCONFIG"; break; case O_SHUTDOWN: actionAsText = "O_SHUTDOWN"; 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_DC_TIMER_RESTART: actionAsText = "O_DC_TIMER_RESTART"; 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_ELECTION_COUNT: actionAsText = "A_ELECTION_COUNT"; break; case A_ELECTION_TIMEOUT: actionAsText = "A_ELECTION_TIMEOUT"; break; case A_ELECT_TIMER_START: actionAsText = "A_ELECT_TIMER_START"; break; case A_ELECT_TIMER_STOP: actionAsText = "A_ELECT_TIMER_STOP"; break; case A_ELECTION_VOTE: actionAsText = "A_ELECTION_VOTE"; break; case A_ANNOUNCE: actionAsText = "A_ANNOUNCE"; break; case A_JOIN_ACK: actionAsText = "A_JOIN_ACK"; break; case A_JOIN_WELCOME: actionAsText = "A_JOIN_WELCOME"; break; case A_JOIN_WELCOME_ALL: actionAsText = "A_JOIN_WELCOME_ALL"; break; case A_JOIN_PROCESS_ACK: actionAsText = "A_JOIN_PROCESS_ACK"; break; case A_MSG_PROCESS: actionAsText = "A_MSG_PROCESS"; break; case A_MSG_ROUTE: actionAsText = "A_MSG_ROUTE"; break; case A_MSG_STORE: actionAsText = "A_MSG_STORE"; 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 A_CCM_EVENT: actionAsText = "A_CCM_EVENT"; break; case A_CCM_UPDATE_CACHE: actionAsText = "A_CCM_UPDATE_CACHE"; break; case A_CIB_BUMPGEN: actionAsText = "A_CIB_BUMPGEN"; break; case A_CIB_INVOKE: actionAsText = "A_CIB_INVOKE"; 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_CANCEL: actionAsText = "A_TE_CANCEL"; break; case A_TE_COPYTO: actionAsText = "A_TE_COPYTO"; 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; } if(actionAsText == NULL) { crm_err("Action %.16llx is unknown", action); actionAsText = ""; } return actionAsText; } void cleanup_subsystem(struct crm_subsystem_s *the_subsystem) { int pid_status = -1; the_subsystem->ipc = NULL; clear_bit_inplace(&fsa_input_register, the_subsystem->flag); /* Forcing client to die */ kill(the_subsystem->pid, -9); /* cleanup the ps entry */ waitpid(the_subsystem->pid, &pid_status, WNOHANG); the_subsystem->pid = -1; } enum crmd_fsa_input invoke_local_cib(xmlNodePtr msg_options, xmlNodePtr msg_data, const char *operation) { enum crmd_fsa_input result = I_NULL; xmlNodePtr request = NULL; msg_options = set_xml_attr(msg_options, XML_TAG_OPTIONS, XML_ATTR_OP, operation, TRUE); request = create_request(msg_options, msg_data, NULL, CRM_SYSTEM_CIB, AM_I_DC?CRM_SYSTEM_DC:CRM_SYSTEM_CRMD, NULL, NULL); result = do_cib_invoke(A_CIB_INVOKE_LOCAL, C_UNKNOWN, fsa_state, I_CIB_OP, request); free_xml(request); return result; } 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. */ xmlNodePtr tmp2 = NULL; xmlNodePtr tmp1 = create_xml_node(NULL, XML_CIB_TAG_NODE); crm_debug("Creating node entry for %s", uname); set_uuid(tmp1, XML_ATTR_UUID, uname); set_xml_property_copy(tmp1, XML_ATTR_UNAME, uname); set_xml_property_copy(tmp1, XML_ATTR_TYPE, type); tmp2 = create_cib_fragment(tmp1, NULL); /* do not forward this to the TE */ invoke_local_cib(NULL, tmp2, CRM_OP_UPDATE); free_xml(tmp2); free_xml(tmp1); } xmlNodePtr create_node_state(const char *uuid, const char *uname, const char *ccm_state, const char *crmd_state, const char *join_state) { xmlNodePtr node_state = create_xml_node(NULL, XML_CIB_TAG_STATE); crm_debug("Creating node state entry for %s", uname); set_uuid(node_state, XML_ATTR_UUID, uname); set_xml_property_copy(node_state, XML_ATTR_UNAME, uname); if(ccm_state != NULL) { - set_xml_property_copy(node_state, XML_CIB_ATTR_INCCM, ccm_state); + set_xml_property_copy( + node_state, XML_CIB_ATTR_INCCM, ccm_state); } if(crmd_state != NULL) { - set_xml_property_copy(node_state, XML_CIB_ATTR_CRMDSTATE, crmd_state); + set_xml_property_copy( + node_state, XML_CIB_ATTR_CRMDSTATE, crmd_state); } if(join_state != NULL) { - set_xml_property_copy(node_state, XML_CIB_ATTR_JOINSTATE, join_state); + set_xml_property_copy( + node_state, XML_CIB_ATTR_JOINSTATE, join_state); } crm_xml_devel(node_state, "created"); return node_state; } void set_uuid(xmlNodePtr node, const char *attr, const char *uname) { uuid_t uuid_raw; char *uuid_calc = NULL; crm_malloc(uuid_calc, sizeof(char)*50); if(uuid_calc != NULL) { if(fsa_cluster_conn->llc_ops->get_uuid_by_name( fsa_cluster_conn, uname, uuid_raw) == HA_FAIL) { crm_err("Could not calculate UUID for %s", uname); crm_free(uuid_calc); uuid_calc = crm_strdup(uname); } else { uuid_unparse(uuid_raw, uuid_calc); } set_xml_property_copy(node, attr, uuid_calc); } crm_free(uuid_calc); }