diff --git a/crmd/atest.c b/crmd/atest.c index c35b83cbcb..fa5e4957b0 100644 --- a/crmd/atest.c +++ b/crmd/atest.c @@ -1,83 +1,83 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include #define OPTARGS "V?X:I:" int -main(int argc, char ** argv) +main(int argc, char **argv) { int flag; xmlNode *top = NULL; xmlNode *xml = NULL; const char *xml_file = NULL; const char *xpath = NULL; - + crm_log_init(NULL, LOG_DEBUG, FALSE, TRUE, argc, argv); while (1) { - flag = getopt(argc, argv, OPTARGS); - if (flag == -1) - break; - - switch(flag) { - case 'X': - xml_file = optarg; - break; - case 'I': - xpath = optarg; - break; - case '?': - /* usage("ptest", 0); */ - break; - default: - printf("?? getopt returned character code 0%o ??\n", flag); - break; - } + flag = getopt(argc, argv, OPTARGS); + if (flag == -1) + break; + + switch (flag) { + case 'X': + xml_file = optarg; + break; + case 'I': + xpath = optarg; + break; + case '?': + /* usage("ptest", 0); */ + break; + default: + printf("?? getopt returned character code 0%o ??\n", flag); + break; + } } top = filename2xml(xml_file); validate_xml(top, NULL, FALSE); - if(xpath) { - xml = get_xpath_object(xpath, top, LOG_ERR); + if (xpath) { + xml = get_xpath_object(xpath, top, LOG_ERR); } - - if(xml) { - char *buf = dump_xml_formatted(xml); - printf("%s\n", buf); - crm_free(buf); + + if (xml) { + char *buf = dump_xml_formatted(xml); + + printf("%s\n", buf); + crm_free(buf); } free_xml(top); return 0; } - diff --git a/crmd/callbacks.c b/crmd/callbacks.c index f21c3c68aa..4361a718a7 100644 --- a/crmd/callbacks.c +++ b/crmd/callbacks.c @@ -1,693 +1,689 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include void crmd_ha_connection_destroy(gpointer user_data); -void crmd_ha_msg_filter(xmlNode *msg); +void crmd_ha_msg_filter(xmlNode * msg); /* From join_dc... */ -extern gboolean check_join_state( - enum crmd_fsa_state cur_state, const char *source); - +extern gboolean check_join_state(enum crmd_fsa_state cur_state, const char *source); #define trigger_fsa(source) crm_debug_3("Triggering FSA: %s", __FUNCTION__); \ mainloop_set_trigger(source); #if SUPPORT_HEARTBEAT gboolean -crmd_ha_msg_dispatch(ll_cluster_t *cluster_conn, gpointer user_data) +crmd_ha_msg_dispatch(ll_cluster_t * cluster_conn, gpointer user_data) { - IPC_Channel *channel = NULL; - gboolean stay_connected = TRUE; - - crm_debug_3("Invoked"); - - if(cluster_conn != NULL) { - channel = cluster_conn->llc_ops->ipcchan(cluster_conn); - } - - CRM_CHECK(cluster_conn != NULL, ;); - CRM_CHECK(channel != NULL, ;); - - if(channel != NULL && IPC_ISRCONN(channel)) { - if(cluster_conn->llc_ops->msgready(cluster_conn) == 0) { - crm_debug_2("no message ready yet"); - } - /* invoke the callbacks but dont block */ - cluster_conn->llc_ops->rcvmsg(cluster_conn, 0); - } - - if (channel == NULL || channel->ch_status != IPC_CONNECT) { - if(is_set(fsa_input_register, R_HA_DISCONNECTED) == FALSE) { - crm_crit("Lost connection to heartbeat service."); - } else { - crm_info("Lost connection to heartbeat service."); - } - trigger_fsa(fsa_source); - stay_connected = FALSE; - } - - return stay_connected; + IPC_Channel *channel = NULL; + gboolean stay_connected = TRUE; + + crm_debug_3("Invoked"); + + if (cluster_conn != NULL) { + channel = cluster_conn->llc_ops->ipcchan(cluster_conn); + } + + CRM_CHECK(cluster_conn != NULL,;); + CRM_CHECK(channel != NULL,;); + + if (channel != NULL && IPC_ISRCONN(channel)) { + if (cluster_conn->llc_ops->msgready(cluster_conn) == 0) { + crm_debug_2("no message ready yet"); + } + /* invoke the callbacks but dont block */ + cluster_conn->llc_ops->rcvmsg(cluster_conn, 0); + } + + if (channel == NULL || channel->ch_status != IPC_CONNECT) { + if (is_set(fsa_input_register, R_HA_DISCONNECTED) == FALSE) { + crm_crit("Lost connection to heartbeat service."); + } else { + crm_info("Lost connection to heartbeat service."); + } + trigger_fsa(fsa_source); + stay_connected = FALSE; + } + + return stay_connected; } #endif void crmd_ha_connection_destroy(gpointer user_data) { - crm_debug_3("Invoked"); - if(is_set(fsa_input_register, R_HA_DISCONNECTED)) { - /* we signed out, so this is expected */ - crm_info("Heartbeat disconnection complete"); - return; - } - - crm_crit("Lost connection to heartbeat service!"); - register_fsa_input(C_HA_DISCONNECT, I_ERROR, NULL); - trigger_fsa(fsa_source); + crm_debug_3("Invoked"); + if (is_set(fsa_input_register, R_HA_DISCONNECTED)) { + /* we signed out, so this is expected */ + crm_info("Heartbeat disconnection complete"); + return; + } + + crm_crit("Lost connection to heartbeat service!"); + register_fsa_input(C_HA_DISCONNECT, I_ERROR, NULL); + trigger_fsa(fsa_source); } void -crmd_ha_msg_filter(xmlNode *msg) +crmd_ha_msg_filter(xmlNode * msg) { - if(AM_I_DC) { - const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM); - if(safe_str_eq(sys_from, CRM_SYSTEM_DC)) { - const char *from = crm_element_value(msg, F_ORIG); - if(safe_str_neq(from, fsa_our_uname)) { - int level = LOG_INFO; - const char *op = crm_element_value(msg, F_CRM_TASK); - - /* make sure the election happens NOW */ - if(fsa_state != S_ELECTION) { - ha_msg_input_t new_input; - level = LOG_WARNING; - new_input.msg = msg; - register_fsa_error_adv( - C_FSA_INTERNAL, I_ELECTION, NULL, &new_input, __FUNCTION__); - } - - do_crm_log(level, "Another DC detected: %s (op=%s)", from, op); - goto done; - } - } + if (AM_I_DC) { + const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM); + + if (safe_str_eq(sys_from, CRM_SYSTEM_DC)) { + const char *from = crm_element_value(msg, F_ORIG); + + if (safe_str_neq(from, fsa_our_uname)) { + int level = LOG_INFO; + const char *op = crm_element_value(msg, F_CRM_TASK); + + /* make sure the election happens NOW */ + if (fsa_state != S_ELECTION) { + ha_msg_input_t new_input; + + level = LOG_WARNING; + new_input.msg = msg; + register_fsa_error_adv(C_FSA_INTERNAL, I_ELECTION, NULL, &new_input, + __FUNCTION__); + } + + do_crm_log(level, "Another DC detected: %s (op=%s)", from, op); + goto done; + } + } } else { - const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); - if(safe_str_eq(sys_to, CRM_SYSTEM_DC)) { - return; - } + const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); + + if (safe_str_eq(sys_to, CRM_SYSTEM_DC)) { + return; + } } - + /* crm_log_xml(LOG_MSG, "HA[inbound]", msg); */ route_message(C_HA_MESSAGE, msg); done: trigger_fsa(fsa_source); } #if SUPPORT_HEARTBEAT void -crmd_ha_msg_callback(HA_Message *hamsg, void* private_data) +crmd_ha_msg_callback(HA_Message * hamsg, void *private_data) { - int level = LOG_DEBUG; - crm_node_t *from_node = NULL; - - xmlNode *msg = convert_ha_message(NULL, hamsg, __FUNCTION__); - const char *from = crm_element_value(msg, F_ORIG); - const char *op = crm_element_value(msg, F_CRM_TASK); - const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM); - - CRM_CHECK(from != NULL, crm_log_xml_err(msg, "anon"); goto bail); - - crm_debug_2("HA[inbound]: %s from %s", op, from); - - if(crm_peer_cache == NULL || crm_active_members() == 0) { - crm_debug("Ignoring HA messages until we are" - " connected to the CCM (%s op from %s)", op, from); - crm_log_xml(LOG_MSG, "HA[inbound]: Ignore (No CCM)", msg); - goto bail; - } - - from_node = crm_get_peer(0, from); - if(crm_is_member_active(from_node) == FALSE) { - if(safe_str_eq(op, CRM_OP_VOTE)) { - level = LOG_WARNING; - - } else if(AM_I_DC && safe_str_eq(op, CRM_OP_JOIN_ANNOUNCE)) { - level = LOG_WARNING; - - } else if(safe_str_eq(sys_from, CRM_SYSTEM_DC)) { - level = LOG_WARNING; - } - do_crm_log(level, - "Ignoring HA message (op=%s) from %s: not in our" - " membership list (size=%d)", op, from, - crm_active_members()); - - crm_log_xml(LOG_MSG, "HA[inbound]: CCM Discard", msg); - - } else { - crmd_ha_msg_filter(msg); - } + int level = LOG_DEBUG; + crm_node_t *from_node = NULL; + + xmlNode *msg = convert_ha_message(NULL, hamsg, __FUNCTION__); + const char *from = crm_element_value(msg, F_ORIG); + const char *op = crm_element_value(msg, F_CRM_TASK); + const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM); + + CRM_CHECK(from != NULL, crm_log_xml_err(msg, "anon"); goto bail); + + crm_debug_2("HA[inbound]: %s from %s", op, from); + + if (crm_peer_cache == NULL || crm_active_members() == 0) { + crm_debug("Ignoring HA messages until we are" + " connected to the CCM (%s op from %s)", op, from); + crm_log_xml(LOG_MSG, "HA[inbound]: Ignore (No CCM)", msg); + goto bail; + } + + from_node = crm_get_peer(0, from); + if (crm_is_member_active(from_node) == FALSE) { + if (safe_str_eq(op, CRM_OP_VOTE)) { + level = LOG_WARNING; + + } else if (AM_I_DC && safe_str_eq(op, CRM_OP_JOIN_ANNOUNCE)) { + level = LOG_WARNING; + + } else if (safe_str_eq(sys_from, CRM_SYSTEM_DC)) { + level = LOG_WARNING; + } + do_crm_log(level, + "Ignoring HA message (op=%s) from %s: not in our" + " membership list (size=%d)", op, from, crm_active_members()); + + crm_log_xml(LOG_MSG, "HA[inbound]: CCM Discard", msg); + + } else { + crmd_ha_msg_filter(msg); + } bail: - free_xml(msg); - return; + free_xml(msg); + return; } #endif - /* * Apparently returning TRUE means "stay connected, keep doing stuff". * Returning FALSE means "we're all done, close the connection" */ gboolean -crmd_ipc_msg_callback(IPC_Channel *client, gpointer user_data) +crmd_ipc_msg_callback(IPC_Channel * client, gpointer user_data) { - int lpc = 0; - xmlNode *msg = NULL; - crmd_client_t *curr_client = (crmd_client_t*)user_data; - gboolean stay_connected = TRUE; - - crm_debug_2("Invoked: %s", - curr_client->table_key); - - while(IPC_ISRCONN(client)) { - if(client->ops->is_message_pending(client) == 0) { - break; - } - - msg = xmlfromIPC(client, MAX_IPC_DELAY); - if (msg == NULL) { - break; - } - + int lpc = 0; + xmlNode *msg = NULL; + crmd_client_t *curr_client = (crmd_client_t *) user_data; + gboolean stay_connected = TRUE; + + crm_debug_2("Invoked: %s", curr_client->table_key); + + while (IPC_ISRCONN(client)) { + if (client->ops->is_message_pending(client) == 0) { + break; + } + + msg = xmlfromIPC(client, MAX_IPC_DELAY); + if (msg == NULL) { + break; + } #if ENABLE_ACL - determine_request_user(&curr_client->user, client, msg, F_CRM_USER); + determine_request_user(&curr_client->user, client, msg, F_CRM_USER); #endif - lpc++; - crm_debug_2("Processing msg from %s", curr_client->table_key); - crm_log_xml(LOG_DEBUG_2, "CRMd[inbound]", msg); - - if(crmd_authorize_message(msg, curr_client)) { - route_message(C_IPC_MESSAGE, msg); - } - - free_xml(msg); - msg = NULL; - - if(client->ch_status != IPC_CONNECT) { - break; - } - } - - crm_debug_2("Processed %d messages", lpc); - - if (client->ch_status != IPC_CONNECT) { - stay_connected = FALSE; - process_client_disconnect(curr_client); - } - - trigger_fsa(fsa_source); - return stay_connected; -} + lpc++; + crm_debug_2("Processing msg from %s", curr_client->table_key); + crm_log_xml(LOG_DEBUG_2, "CRMd[inbound]", msg); + + if (crmd_authorize_message(msg, curr_client)) { + route_message(C_IPC_MESSAGE, msg); + } + + free_xml(msg); + msg = NULL; + + if (client->ch_status != IPC_CONNECT) { + break; + } + } + crm_debug_2("Processed %d messages", lpc); + if (client->ch_status != IPC_CONNECT) { + stay_connected = FALSE; + process_client_disconnect(curr_client); + } + + trigger_fsa(fsa_source); + return stay_connected; +} extern GCHSource *lrm_source; gboolean -lrm_dispatch(IPC_Channel *src_not_used, gpointer user_data) +lrm_dispatch(IPC_Channel * src_not_used, gpointer user_data) { - /* ?? src == lrm_channel ?? */ - ll_lrm_t *lrm = (ll_lrm_t*)user_data; - IPC_Channel *lrm_channel = lrm->lrm_ops->ipcchan(lrm); - - lrm->lrm_ops->rcvmsg(lrm, FALSE); - if(lrm_channel->ch_status != IPC_CONNECT) { - lrm_connection_destroy(NULL); - return FALSE; - } - return TRUE; + /* ?? src == lrm_channel ?? */ + ll_lrm_t *lrm = (ll_lrm_t *) user_data; + IPC_Channel *lrm_channel = lrm->lrm_ops->ipcchan(lrm); + + lrm->lrm_ops->rcvmsg(lrm, FALSE); + if (lrm_channel->ch_status != IPC_CONNECT) { + lrm_connection_destroy(NULL); + return FALSE; + } + return TRUE; } -extern gboolean process_lrm_event(lrm_op_t *op); +extern gboolean process_lrm_event(lrm_op_t * op); void -lrm_op_callback(lrm_op_t* op) +lrm_op_callback(lrm_op_t * op) { - CRM_CHECK(op != NULL, return); - process_lrm_event(op); + CRM_CHECK(op != NULL, return); + process_lrm_event(op); } -static void crmd_peer_update(crm_node_t *member, enum crm_proc_flag client) +static void +crmd_peer_update(crm_node_t * member, enum crm_proc_flag client) { const char *status = NULL; CRM_CHECK(member != NULL, return); - status = (member->processes&client)?ONLINESTATUS:OFFLINESTATUS; + status = (member->processes & client) ? ONLINESTATUS : OFFLINESTATUS; crm_notice("Status update: Client %s/%s now has status [%s] (DC=%s)", - member->uname, peer2text(client), status, - AM_I_DC?"true":crm_str(fsa_our_dc)); - - if((client & crm_proc_crmd) == 0) { - return; - } else if(is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) { - return; - } else if(fsa_state == S_STOPPING) { - return; - } - - if(safe_str_eq(member->uname, fsa_our_dc) && crm_is_full_member(member) == FALSE){ - /* Did the DC leave us? */ - crm_info("Got client status callback - our DC is dead"); - register_fsa_input(C_CRMD_STATUS_CALLBACK, I_ELECTION, NULL); - - } else if(AM_I_DC) { - xmlNode *update = NULL; - update = create_node_state( - member->uname, NULL, NULL, status, NULL, NULL, FALSE, __FUNCTION__); - - fsa_cib_anon_update( - XML_CIB_TAG_STATUS, update, cib_scope_local|cib_quorum_override|cib_can_create); - free_xml(update); - - if((member->processes & client) == 0) { - erase_node_from_join(member->uname); - check_join_state(fsa_state, __FUNCTION__); - fail_incompletable_actions(transition_graph, member->uuid); - - } else { - register_fsa_input_before(C_FSA_INTERNAL, I_NODE_JOIN, NULL); - } - } - + member->uname, peer2text(client), status, AM_I_DC ? "true" : crm_str(fsa_our_dc)); + + if ((client & crm_proc_crmd) == 0) { + return; + } else if (is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) { + return; + } else if (fsa_state == S_STOPPING) { + return; + } + + if (safe_str_eq(member->uname, fsa_our_dc) && crm_is_full_member(member) == FALSE) { + /* Did the DC leave us? */ + crm_info("Got client status callback - our DC is dead"); + register_fsa_input(C_CRMD_STATUS_CALLBACK, I_ELECTION, NULL); + + } else if (AM_I_DC) { + xmlNode *update = NULL; + + update = + create_node_state(member->uname, NULL, NULL, status, NULL, NULL, FALSE, __FUNCTION__); + + fsa_cib_anon_update(XML_CIB_TAG_STATUS, update, + cib_scope_local | cib_quorum_override | cib_can_create); + free_xml(update); + + if ((member->processes & client) == 0) { + erase_node_from_join(member->uname); + check_join_state(fsa_state, __FUNCTION__); + fail_incompletable_actions(transition_graph, member->uuid); + + } else { + register_fsa_input_before(C_FSA_INTERNAL, I_NODE_JOIN, NULL); + } + } + trigger_fsa(fsa_source); } -void ais_status_callback(enum crm_status_type type, crm_node_t *node, const void *data) +void +ais_status_callback(enum crm_status_type type, crm_node_t * node, const void *data) { gboolean reset_status_entry = FALSE; - uint32_t old = 0 ; + uint32_t old = 0; set_bit_inplace(fsa_input_register, R_PEER_DATA); - if(node->uname == NULL) { - return; - } - - switch(type) { - case crm_status_uname: - crm_info("status: %s is now %s", node->uname, node->state); - /* reset_status_entry = TRUE; */ - /* If we've never seen the node, then it also wont be in the status section */ - break; - case crm_status_nstate: - crm_info("status: %s is now %s (was %s)", node->uname, node->state, (const char *)data); - reset_status_entry = TRUE; - break; - case crm_status_processes: - if (data) { - old = *(const uint32_t *)data; - } - - if( (node->processes ^ old) & crm_proc_crmd ) { - crmd_peer_update(node, crm_proc_crmd); - } - break; + if (node->uname == NULL) { + return; } - /* Can this be removed now that do_cl_join_finalize_respond() does the same thing? */ - if(AM_I_DC && reset_status_entry && safe_str_eq(CRMD_STATE_ACTIVE, node->state)) { - crm_action_t *down = match_down_event(0, node->uname, NULL); - - erase_status_tag(node->uname, XML_CIB_TAG_LRM, cib_scope_local); - erase_status_tag(node->uname, XML_TAG_TRANSIENT_NODEATTRS, cib_scope_local); - if(down) { - const char *task = crm_element_value(down->xml, XML_LRM_ATTR_TASK); - if(safe_str_eq(task, CRM_OP_FENCE)) { - crm_info("Node return implies stonith of %s (action %d) completed", node->uname, down->id); - down->confirmed = TRUE; - } - } + switch (type) { + case crm_status_uname: + crm_info("status: %s is now %s", node->uname, node->state); + /* reset_status_entry = TRUE; */ + /* If we've never seen the node, then it also wont be in the status section */ + break; + case crm_status_nstate: + crm_info("status: %s is now %s (was %s)", node->uname, node->state, (const char *)data); + reset_status_entry = TRUE; + break; + case crm_status_processes: + if (data) { + old = *(const uint32_t *)data; + } + + if ((node->processes ^ old) & crm_proc_crmd) { + crmd_peer_update(node, crm_proc_crmd); + } + break; + } - /* TODO: potentially we also want to set XML_CIB_ATTR_JOINSTATE and XML_CIB_ATTR_EXPSTATE here */ + /* Can this be removed now that do_cl_join_finalize_respond() does the same thing? */ + if (AM_I_DC && reset_status_entry && safe_str_eq(CRMD_STATE_ACTIVE, node->state)) { + crm_action_t *down = match_down_event(0, node->uname, NULL); + + erase_status_tag(node->uname, XML_CIB_TAG_LRM, cib_scope_local); + erase_status_tag(node->uname, XML_TAG_TRANSIENT_NODEATTRS, cib_scope_local); + if (down) { + const char *task = crm_element_value(down->xml, XML_LRM_ATTR_TASK); + + if (safe_str_eq(task, CRM_OP_FENCE)) { + crm_info("Node return implies stonith of %s (action %d) completed", node->uname, + down->id); + down->confirmed = TRUE; + } + } + + /* TODO: potentially we also want to set XML_CIB_ATTR_JOINSTATE and XML_CIB_ATTR_EXPSTATE here */ } } void crmd_ha_status_callback(const char *node, const char *status, void *private) { - xmlNode *update = NULL; - crm_node_t *member = NULL; - crm_notice("Status update: Node %s now has status [%s]", node, status); - - member = crm_get_peer(0, node); - if(member == NULL || crm_is_member_active(member) == FALSE) { - /* Make sure it is created so crm_update_peer_proc() succeeds */ - const char *uuid = get_uuid(node); - member = crm_update_peer(0, 0, 0, -1, 0, uuid, node, NULL, NULL); - CRM_ASSERT(member); - } - - if(safe_str_eq(status, PINGSTATUS)) { - return; - } - - if(safe_str_eq(status, DEADSTATUS)) { - /* this node is toast */ - crm_update_peer_proc(node, crm_proc_ais, OFFLINESTATUS); - if(AM_I_DC) { - update = create_node_state( - node, DEADSTATUS, XML_BOOLEAN_NO, OFFLINESTATUS, - CRMD_JOINSTATE_DOWN, NULL, TRUE, __FUNCTION__); - } - - } else { - crm_update_peer_proc(node, crm_proc_ais, ONLINESTATUS); - if(AM_I_DC) { - update = create_node_state( - node, ACTIVESTATUS, NULL, NULL, - CRMD_JOINSTATE_PENDING, NULL, FALSE, __FUNCTION__); - } - } - - trigger_fsa(fsa_source); - - if(update != NULL) { - fsa_cib_anon_update( - XML_CIB_TAG_STATUS, update, cib_scope_local|cib_quorum_override|cib_can_create); - free_xml(update); - } + xmlNode *update = NULL; + crm_node_t *member = NULL; + + crm_notice("Status update: Node %s now has status [%s]", node, status); + + member = crm_get_peer(0, node); + if (member == NULL || crm_is_member_active(member) == FALSE) { + /* Make sure it is created so crm_update_peer_proc() succeeds */ + const char *uuid = get_uuid(node); + + member = crm_update_peer(0, 0, 0, -1, 0, uuid, node, NULL, NULL); + CRM_ASSERT(member); + } + + if (safe_str_eq(status, PINGSTATUS)) { + return; + } + + if (safe_str_eq(status, DEADSTATUS)) { + /* this node is toast */ + crm_update_peer_proc(node, crm_proc_ais, OFFLINESTATUS); + if (AM_I_DC) { + update = create_node_state(node, DEADSTATUS, XML_BOOLEAN_NO, OFFLINESTATUS, + CRMD_JOINSTATE_DOWN, NULL, TRUE, __FUNCTION__); + } + + } else { + crm_update_peer_proc(node, crm_proc_ais, ONLINESTATUS); + if (AM_I_DC) { + update = create_node_state(node, ACTIVESTATUS, NULL, NULL, + CRMD_JOINSTATE_PENDING, NULL, FALSE, __FUNCTION__); + } + } + + trigger_fsa(fsa_source); + + if (update != NULL) { + fsa_cib_anon_update(XML_CIB_TAG_STATUS, update, + cib_scope_local | cib_quorum_override | cib_can_create); + free_xml(update); + } } void -crmd_client_status_callback(const char * node, const char * client, - const char * status, void * private) +crmd_client_status_callback(const char *node, const char *client, const char *status, void *private) { - const char *join = NULL; - crm_node_t *member = NULL; - gboolean clear_shutdown = FALSE; - - crm_debug_3("Invoked"); - if(safe_str_neq(client, CRM_SYSTEM_CRMD)) { - return; - } - - if(safe_str_eq(status, JOINSTATUS)){ - clear_shutdown = TRUE; - status = ONLINESTATUS; - join = CRMD_JOINSTATE_PENDING; - - } else if(safe_str_eq(status, LEAVESTATUS)){ - status = OFFLINESTATUS; - join = CRMD_JOINSTATE_DOWN; + const char *join = NULL; + crm_node_t *member = NULL; + gboolean clear_shutdown = FALSE; + + crm_debug_3("Invoked"); + if (safe_str_neq(client, CRM_SYSTEM_CRMD)) { + return; + } + + if (safe_str_eq(status, JOINSTATUS)) { + clear_shutdown = TRUE; + status = ONLINESTATUS; + join = CRMD_JOINSTATE_PENDING; + + } else if (safe_str_eq(status, LEAVESTATUS)) { + status = OFFLINESTATUS; + join = CRMD_JOINSTATE_DOWN; /* clear_shutdown = TRUE; */ - } - - set_bit_inplace(fsa_input_register, R_PEER_DATA); - - crm_notice("Status update: Client %s/%s now has status [%s] (DC=%s)", - node, client, status, AM_I_DC?"true":"false"); - - if(safe_str_eq(status, ONLINESTATUS)) { - /* remove the cached value in case it changed */ - crm_debug_2("Uncaching UUID for %s", node); - unget_uuid(node); - } - - member = crm_get_peer(0, node); - if(member == NULL || crm_is_member_active(member) == FALSE) { - /* Make sure it is created so crm_update_peer_proc() succeeds */ - const char *uuid = get_uuid(node); - member = crm_update_peer(0, 0, 0, -1, 0, uuid, node, NULL, NULL); - CRM_ASSERT(member); - } - - if(AM_I_DC) { - xmlNode *update = NULL; - crm_debug_3("Got client status callback"); - update = create_node_state( - node, NULL, NULL, status, join, NULL, clear_shutdown, __FUNCTION__); - - fsa_cib_anon_update( - XML_CIB_TAG_STATUS, update, cib_scope_local|cib_quorum_override|cib_can_create); - free_xml(update); - } - crm_update_peer_proc(node, crm_proc_crmd, status); + } + + set_bit_inplace(fsa_input_register, R_PEER_DATA); + + crm_notice("Status update: Client %s/%s now has status [%s] (DC=%s)", + node, client, status, AM_I_DC ? "true" : "false"); + + if (safe_str_eq(status, ONLINESTATUS)) { + /* remove the cached value in case it changed */ + crm_debug_2("Uncaching UUID for %s", node); + unget_uuid(node); + } + + member = crm_get_peer(0, node); + if (member == NULL || crm_is_member_active(member) == FALSE) { + /* Make sure it is created so crm_update_peer_proc() succeeds */ + const char *uuid = get_uuid(node); + + member = crm_update_peer(0, 0, 0, -1, 0, uuid, node, NULL, NULL); + CRM_ASSERT(member); + } + + if (AM_I_DC) { + xmlNode *update = NULL; + + crm_debug_3("Got client status callback"); + update = + create_node_state(node, NULL, NULL, status, join, NULL, clear_shutdown, __FUNCTION__); + + fsa_cib_anon_update(XML_CIB_TAG_STATUS, update, + cib_scope_local | cib_quorum_override | cib_can_create); + free_xml(update); + } + crm_update_peer_proc(node, crm_proc_crmd, status); } void crmd_ipc_connection_destroy(gpointer user_data) { - GCHSource *source = NULL; - crmd_client_t *client = user_data; + GCHSource *source = NULL; + crmd_client_t *client = user_data; /* Calling this function on an _active_ connection results in: * crmd_ipc_connection_destroy (callbacks.c:431) * -> G_main_del_IPC_Channel (GSource.c:478) * -> g_source_unref * -> G_CH_destroy_int (GSource.c:647) * -> crmd_ipc_connection_destroy (callbacks.c:437)\ * * A better alternative is to call G_main_del_IPC_Channel() directly */ - if(client == NULL) { - crm_debug_4("No client to delete"); - return; - } - - crm_debug_2("Disconnecting client %s (%p)", client->table_key, client); - source = client->client_source; - client->client_source = NULL; - if(source != NULL) { - crm_debug_3("Deleting %s (%p) from mainloop", - client->table_key, source); - G_main_del_IPC_Channel(source); - } - crm_free(client->table_key); - crm_free(client->sub_sys); - crm_free(client->uuid); - crm_free(client->user); - crm_free(client); - - return; + if (client == NULL) { + crm_debug_4("No client to delete"); + return; + } + + crm_debug_2("Disconnecting client %s (%p)", client->table_key, client); + source = client->client_source; + client->client_source = NULL; + if (source != NULL) { + crm_debug_3("Deleting %s (%p) from mainloop", client->table_key, source); + G_main_del_IPC_Channel(source); + } + crm_free(client->table_key); + crm_free(client->sub_sys); + crm_free(client->uuid); + crm_free(client->user); + crm_free(client); + + return; } gboolean -crmd_client_connect(IPC_Channel *client_channel, gpointer user_data) +crmd_client_connect(IPC_Channel * client_channel, gpointer user_data) { - crm_debug_3("Invoked"); - if (client_channel == NULL) { - crm_err("Channel was NULL"); - - } else if (client_channel->ch_status == IPC_DISCONNECT) { - crm_err("Channel was disconnected"); - - } else { - crmd_client_t *blank_client = NULL; - crm_debug_3("Channel connected"); - crm_malloc0(blank_client, sizeof(crmd_client_t)); - CRM_ASSERT(blank_client != NULL); - - crm_debug_2("Created client: %p", blank_client); - - client_channel->ops->set_recv_qlen(client_channel, 1024); - client_channel->ops->set_send_qlen(client_channel, 1024); - - blank_client->client_channel = client_channel; - blank_client->sub_sys = NULL; - blank_client->uuid = NULL; - blank_client->table_key = NULL; - - blank_client->client_source = - G_main_add_IPC_Channel( - G_PRIORITY_LOW, client_channel, - FALSE, crmd_ipc_msg_callback, - blank_client, crmd_ipc_connection_destroy); - } - - return TRUE; -} + crm_debug_3("Invoked"); + if (client_channel == NULL) { + crm_err("Channel was NULL"); + + } else if (client_channel->ch_status == IPC_DISCONNECT) { + crm_err("Channel was disconnected"); + + } else { + crmd_client_t *blank_client = NULL; + + crm_debug_3("Channel connected"); + crm_malloc0(blank_client, sizeof(crmd_client_t)); + CRM_ASSERT(blank_client != NULL); + + crm_debug_2("Created client: %p", blank_client); + client_channel->ops->set_recv_qlen(client_channel, 1024); + client_channel->ops->set_send_qlen(client_channel, 1024); + + blank_client->client_channel = client_channel; + blank_client->sub_sys = NULL; + blank_client->uuid = NULL; + blank_client->table_key = NULL; + + blank_client->client_source = + G_main_add_IPC_Channel(G_PRIORITY_LOW, client_channel, + FALSE, crmd_ipc_msg_callback, + blank_client, crmd_ipc_connection_destroy); + } + + return TRUE; +} #if SUPPORT_HEARTBEAT static void *ccm_library = NULL; -int (*ccm_api_callback_done)(void *cookie) = NULL; -int (*ccm_api_handle_event)(const oc_ev_t *token) = NULL; +int (*ccm_api_callback_done) (void *cookie) = NULL; +int (*ccm_api_handle_event) (const oc_ev_t * token) = NULL; static gboolean fsa_have_quorum = FALSE; -gboolean ccm_dispatch(int fd, gpointer user_data) +gboolean +ccm_dispatch(int fd, gpointer user_data) { - int rc = 0; - oc_ev_t *ccm_token = (oc_ev_t*)user_data; - gboolean was_error = FALSE; - - crm_debug_3("Invoked"); - if(ccm_api_handle_event == NULL) { - ccm_api_handle_event = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_handle_event"); - } - rc = (*ccm_api_handle_event)(ccm_token); - - if(rc != 0) { - if(is_set(fsa_input_register, R_CCM_DISCONNECTED) == FALSE) { - /* we signed out, so this is expected */ - register_fsa_input(C_CCM_CALLBACK, I_ERROR, NULL); - crm_err("CCM connection appears to have failed: rc=%d.", - rc); - } - was_error = TRUE; - } - - trigger_fsa(fsa_source); - return !was_error; + int rc = 0; + oc_ev_t *ccm_token = (oc_ev_t *) user_data; + gboolean was_error = FALSE; + + crm_debug_3("Invoked"); + if (ccm_api_handle_event == NULL) { + ccm_api_handle_event = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_handle_event"); + } + rc = (*ccm_api_handle_event) (ccm_token); + + if (rc != 0) { + if (is_set(fsa_input_register, R_CCM_DISCONNECTED) == FALSE) { + /* we signed out, so this is expected */ + register_fsa_input(C_CCM_CALLBACK, I_ERROR, NULL); + crm_err("CCM connection appears to have failed: rc=%d.", rc); + } + was_error = TRUE; + } + + trigger_fsa(fsa_source); + return !was_error; } -void -crmd_ccm_msg_callback( - oc_ed_t event, void *cookie, size_t size, const void *data) +void +crmd_ccm_msg_callback(oc_ed_t event, void *cookie, size_t size, const void *data) { - gboolean update_cache = FALSE; - const oc_ev_membership_t *membership = data; - - gboolean update_quorum = FALSE; - - crm_debug_3("Invoked"); - CRM_ASSERT(data != NULL); - - crm_info("Quorum %s after event=%s (id=%d)", - ccm_have_quorum(event)?"(re)attained":"lost", - ccm_event_name(event), membership->m_instance); - - if(crm_peer_seq > membership->m_instance) { - crm_err("Membership instance ID went backwards! %llu->%d", - crm_peer_seq, membership->m_instance); - CRM_ASSERT(crm_peer_seq <= membership->m_instance); - return; - } - - /* - * OC_EV_MS_NEW_MEMBERSHIP: membership with quorum - * OC_EV_MS_MS_INVALID: membership without quorum - * OC_EV_MS_NOT_PRIMARY: previous membership no longer valid - * OC_EV_MS_PRIMARY_RESTORED: previous membership restored - * OC_EV_MS_EVICTED: the client is evicted from ccm. - */ - - switch(event) { - case OC_EV_MS_NEW_MEMBERSHIP: - case OC_EV_MS_INVALID: - update_cache = TRUE; - update_quorum = TRUE; - break; - case OC_EV_MS_NOT_PRIMARY: - break; - case OC_EV_MS_PRIMARY_RESTORED: - update_cache = TRUE; - crm_peer_seq = membership->m_instance; - break; - case OC_EV_MS_EVICTED: - update_quorum = TRUE; - register_fsa_input(C_FSA_INTERNAL, I_STOP, NULL); - crm_err("Shutting down after CCM event: %s", - ccm_event_name(event)); - break; - default: - crm_err("Unknown CCM event: %d", event); - } - - if(update_quorum) { - crm_have_quorum = ccm_have_quorum(event); - crm_update_quorum(crm_have_quorum, FALSE); - - if(crm_have_quorum == FALSE) { - /* did we just loose quorum? */ - if(fsa_have_quorum) { - crm_info("Quorum lost: %s", ccm_event_name(event)); - } - } - } - - if(update_cache) { - crm_debug_2("Updating cache after event %s", ccm_event_name(event)); - do_ccm_update_cache(C_CCM_CALLBACK, fsa_state, event, data, NULL); - - } else if(event != OC_EV_MS_NOT_PRIMARY) { - crm_peer_seq = membership->m_instance; - register_fsa_action(A_TE_CANCEL); - } - - if(ccm_api_callback_done == NULL) { - ccm_api_callback_done = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_callback_done"); - } - (*ccm_api_callback_done)(cookie); - return; + gboolean update_cache = FALSE; + const oc_ev_membership_t *membership = data; + + gboolean update_quorum = FALSE; + + crm_debug_3("Invoked"); + CRM_ASSERT(data != NULL); + + crm_info("Quorum %s after event=%s (id=%d)", + ccm_have_quorum(event) ? "(re)attained" : "lost", + ccm_event_name(event), membership->m_instance); + + if (crm_peer_seq > membership->m_instance) { + crm_err("Membership instance ID went backwards! %llu->%d", + crm_peer_seq, membership->m_instance); + CRM_ASSERT(crm_peer_seq <= membership->m_instance); + return; + } + + /* + * OC_EV_MS_NEW_MEMBERSHIP: membership with quorum + * OC_EV_MS_MS_INVALID: membership without quorum + * OC_EV_MS_NOT_PRIMARY: previous membership no longer valid + * OC_EV_MS_PRIMARY_RESTORED: previous membership restored + * OC_EV_MS_EVICTED: the client is evicted from ccm. + */ + + switch (event) { + case OC_EV_MS_NEW_MEMBERSHIP: + case OC_EV_MS_INVALID: + update_cache = TRUE; + update_quorum = TRUE; + break; + case OC_EV_MS_NOT_PRIMARY: + break; + case OC_EV_MS_PRIMARY_RESTORED: + update_cache = TRUE; + crm_peer_seq = membership->m_instance; + break; + case OC_EV_MS_EVICTED: + update_quorum = TRUE; + register_fsa_input(C_FSA_INTERNAL, I_STOP, NULL); + crm_err("Shutting down after CCM event: %s", ccm_event_name(event)); + break; + default: + crm_err("Unknown CCM event: %d", event); + } + + if (update_quorum) { + crm_have_quorum = ccm_have_quorum(event); + crm_update_quorum(crm_have_quorum, FALSE); + + if (crm_have_quorum == FALSE) { + /* did we just loose quorum? */ + if (fsa_have_quorum) { + crm_info("Quorum lost: %s", ccm_event_name(event)); + } + } + } + + if (update_cache) { + crm_debug_2("Updating cache after event %s", ccm_event_name(event)); + do_ccm_update_cache(C_CCM_CALLBACK, fsa_state, event, data, NULL); + + } else if (event != OC_EV_MS_NOT_PRIMARY) { + crm_peer_seq = membership->m_instance; + register_fsa_action(A_TE_CANCEL); + } + + if (ccm_api_callback_done == NULL) { + ccm_api_callback_done = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_callback_done"); + } + (*ccm_api_callback_done) (cookie); + return; } #endif void crmd_cib_connection_destroy(gpointer user_data) { - CRM_CHECK(user_data == fsa_cib_conn, ;); - - crm_debug_3("Invoked"); - trigger_fsa(fsa_source); - fsa_cib_conn->state = cib_disconnected; - - if(is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) { - crm_info("Connection to the CIB terminated..."); - return; - } - - /* eventually this will trigger a reconnect, not a shutdown */ - crm_err("Connection to the CIB terminated..."); - register_fsa_input(C_FSA_INTERNAL, I_ERROR, NULL); - clear_bit_inplace(fsa_input_register, R_CIB_CONNECTED); - - return; -} + CRM_CHECK(user_data == fsa_cib_conn,;); + + crm_debug_3("Invoked"); + trigger_fsa(fsa_source); + fsa_cib_conn->state = cib_disconnected; + if (is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) { + crm_info("Connection to the CIB terminated..."); + return; + } + + /* eventually this will trigger a reconnect, not a shutdown */ + crm_err("Connection to the CIB terminated..."); + register_fsa_input(C_FSA_INTERNAL, I_ERROR, NULL); + clear_bit_inplace(fsa_input_register, R_CIB_CONNECTED); + + return; +} gboolean -crm_fsa_trigger(gpointer user_data) +crm_fsa_trigger(gpointer user_data) { - crm_debug_2("Invoked (queue len: %d)", g_list_length(fsa_message_queue)); - s_crmd_fsa(C_FSA_INTERNAL); - crm_debug_2("Exited (queue len: %d)", g_list_length(fsa_message_queue)); - return TRUE; + crm_debug_2("Invoked (queue len: %d)", g_list_length(fsa_message_queue)); + s_crmd_fsa(C_FSA_INTERNAL); + crm_debug_2("Exited (queue len: %d)", g_list_length(fsa_message_queue)); + return TRUE; } diff --git a/crmd/ccm.c b/crmd/ccm.c index 4d9f9ea0c0..b046602d10 100644 --- a/crmd/ccm.c +++ b/crmd/ccm.c @@ -1,499 +1,482 @@ /* * 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 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 */ /* put these first so that uuid_t is defined without conflicts */ #include #if SUPPORT_HEARTBEAT -#include -#include +# include +# include static void *ccm_library = NULL; #endif #include #include #include #include #include #include #include #include #include #include #include gboolean membership_flux_hack = FALSE; void post_cache_update(int instance); #if SUPPORT_HEARTBEAT oc_ev_t *fsa_ev_token; -void oc_ev_special(const oc_ev_t *, oc_ev_class_t , int ); +void oc_ev_special(const oc_ev_t *, oc_ev_class_t, int); -void crmd_ccm_msg_callback( - oc_ed_t event, void *cookie, size_t size, const void *data); +void crmd_ccm_msg_callback(oc_ed_t event, void *cookie, size_t size, const void *data); #endif void ghash_update_cib_node(gpointer key, gpointer value, gpointer user_data); -void check_dead_member(const char *uname, GHashTable *members); +void check_dead_member(const char *uname, GHashTable * members); void reap_dead_ccm_nodes(gpointer key, gpointer value, gpointer user_data); #define CCM_EVENT_DETAIL 0 #define CCM_EVENT_DETAIL_PARTIAL 0 int num_ccm_register_fails = 0; int max_ccm_register_fails = 30; int last_peer_update = 0; extern GHashTable *voted; -struct update_data_s -{ - const char *state; - const char *caller; - xmlNode *updates; - gboolean overwrite_join; +struct update_data_s { + const char *state; + const char *caller; + xmlNode *updates; + gboolean overwrite_join; }; -void reap_dead_ccm_nodes(gpointer key, gpointer value, gpointer user_data) +void +reap_dead_ccm_nodes(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; - if(crm_is_member_active(node) == FALSE) { - check_dead_member(node->uname, NULL); - fail_incompletable_actions(transition_graph, node->uuid); + + if (crm_is_member_active(node) == FALSE) { + check_dead_member(node->uname, NULL); + fail_incompletable_actions(transition_graph, node->uuid); } } extern gboolean check_join_state(enum crmd_fsa_state cur_state, const char *source); void -check_dead_member(const char *uname, GHashTable *members) +check_dead_member(const char *uname, GHashTable * members) { - CRM_CHECK(uname != NULL, return); - if(members != NULL && g_hash_table_lookup(members, uname) != NULL) { - crm_err("%s didnt really leave the membership!", uname); - return; - } - erase_node_from_join(uname); - if(voted != NULL) { - g_hash_table_remove(voted, uname); - } - - if(safe_str_eq(fsa_our_uname, uname)) { - crm_err("We're not part of the cluster anymore"); - register_fsa_input(C_FSA_INTERNAL, I_ERROR, NULL); - - } else if(AM_I_DC == FALSE && safe_str_eq(uname, fsa_our_dc)) { - crm_warn("Our DC node (%s) left the cluster", uname); - register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL); - - } else if(fsa_state == S_INTEGRATION || fsa_state == S_FINALIZE_JOIN) { - check_join_state(fsa_state, __FUNCTION__); - } + CRM_CHECK(uname != NULL, return); + if (members != NULL && g_hash_table_lookup(members, uname) != NULL) { + crm_err("%s didnt really leave the membership!", uname); + return; + } + erase_node_from_join(uname); + if (voted != NULL) { + g_hash_table_remove(voted, uname); + } + + if (safe_str_eq(fsa_our_uname, uname)) { + crm_err("We're not part of the cluster anymore"); + register_fsa_input(C_FSA_INTERNAL, I_ERROR, NULL); + + } else if (AM_I_DC == FALSE && safe_str_eq(uname, fsa_our_dc)) { + crm_warn("Our DC node (%s) left the cluster", uname); + register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL); + + } else if (fsa_state == S_INTEGRATION || fsa_state == S_FINALIZE_JOIN) { + check_join_state(fsa_state, __FUNCTION__); + } } /* A_CCM_CONNECT */ void do_ccm_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) -{ + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) +{ #if SUPPORT_HEARTBEAT - if(is_heartbeat_cluster()) { - int (*ccm_api_register)(oc_ev_t **token) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_register"); - - int (*ccm_api_set_callback)(const oc_ev_t *token, - oc_ev_class_t class, - oc_ev_callback_t *fn, - oc_ev_callback_t **prev_fn) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_set_callback"); - - - void (*ccm_api_special)(const oc_ev_t *, oc_ev_class_t , int ) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_special"); - int (*ccm_api_activate)(const oc_ev_t *token, int *fd) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_activate"); - int (*ccm_api_unregister)(oc_ev_t *token) = find_library_function( - &ccm_library, CCM_LIBRARY, "oc_ev_unregister"); - - if(action & A_CCM_DISCONNECT){ - set_bit_inplace(fsa_input_register, R_CCM_DISCONNECTED); - (*ccm_api_unregister)(fsa_ev_token); - } - - if(action & A_CCM_CONNECT) { - int ret; - int fsa_ev_fd; - gboolean did_fail = FALSE; - crm_debug_3("Registering with CCM"); - clear_bit_inplace(fsa_input_register, R_CCM_DISCONNECTED); - ret = (*ccm_api_register)(&fsa_ev_token); - if (ret != 0) { - crm_warn("CCM registration failed"); - did_fail = TRUE; - } - - if(did_fail == FALSE) { - crm_debug_3("Setting up CCM callbacks"); - ret = (*ccm_api_set_callback)(fsa_ev_token, OC_EV_MEMB_CLASS, - crmd_ccm_msg_callback, NULL); - if (ret != 0) { - crm_warn("CCM callback not set"); - did_fail = TRUE; - } - } - if(did_fail == FALSE) { - (*ccm_api_special)(fsa_ev_token, OC_EV_MEMB_CLASS, 0/*don't care*/); - - crm_debug_3("Activating CCM token"); - ret = (*ccm_api_activate)(fsa_ev_token, &fsa_ev_fd); - if (ret != 0){ - crm_warn("CCM Activation failed"); - did_fail = TRUE; - } - } - - if(did_fail) { - num_ccm_register_fails++; - (*ccm_api_unregister)(fsa_ev_token); - - if(num_ccm_register_fails < max_ccm_register_fails) { - crm_warn("CCM Connection failed" - " %d times (%d max)", - num_ccm_register_fails, - max_ccm_register_fails); - - crm_timer_start(wait_timer); - crmd_fsa_stall(NULL); - return; - - } else { - crm_err("CCM Activation failed %d (max) times", - num_ccm_register_fails); - register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); - return; - } - } - - - crm_info("CCM connection established..." - " waiting for first callback"); - - G_main_add_fd(G_PRIORITY_HIGH, fsa_ev_fd, FALSE, ccm_dispatch, - fsa_ev_token, default_ipc_connection_destroy); - - } + if (is_heartbeat_cluster()) { + int (*ccm_api_register) (oc_ev_t ** token) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_register"); + + int (*ccm_api_set_callback) (const oc_ev_t * token, + oc_ev_class_t class, + oc_ev_callback_t * fn, + oc_ev_callback_t ** prev_fn) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_set_callback"); + + void (*ccm_api_special) (const oc_ev_t *, oc_ev_class_t, int) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_special"); + int (*ccm_api_activate) (const oc_ev_t * token, int *fd) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_activate"); + int (*ccm_api_unregister) (oc_ev_t * token) = + find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_unregister"); + + if (action & A_CCM_DISCONNECT) { + set_bit_inplace(fsa_input_register, R_CCM_DISCONNECTED); + (*ccm_api_unregister) (fsa_ev_token); + } + + if (action & A_CCM_CONNECT) { + int ret; + int fsa_ev_fd; + gboolean did_fail = FALSE; + + crm_debug_3("Registering with CCM"); + clear_bit_inplace(fsa_input_register, R_CCM_DISCONNECTED); + ret = (*ccm_api_register) (&fsa_ev_token); + if (ret != 0) { + crm_warn("CCM registration failed"); + did_fail = TRUE; + } + + if (did_fail == FALSE) { + crm_debug_3("Setting up CCM callbacks"); + ret = (*ccm_api_set_callback) (fsa_ev_token, OC_EV_MEMB_CLASS, + crmd_ccm_msg_callback, NULL); + if (ret != 0) { + crm_warn("CCM callback not set"); + did_fail = TRUE; + } + } + if (did_fail == FALSE) { + (*ccm_api_special) (fsa_ev_token, OC_EV_MEMB_CLASS, 0 /*don't care */ ); + + crm_debug_3("Activating CCM token"); + ret = (*ccm_api_activate) (fsa_ev_token, &fsa_ev_fd); + if (ret != 0) { + crm_warn("CCM Activation failed"); + did_fail = TRUE; + } + } + + if (did_fail) { + num_ccm_register_fails++; + (*ccm_api_unregister) (fsa_ev_token); + + if (num_ccm_register_fails < max_ccm_register_fails) { + crm_warn("CCM Connection failed" + " %d times (%d max)", num_ccm_register_fails, max_ccm_register_fails); + + crm_timer_start(wait_timer); + crmd_fsa_stall(NULL); + return; + + } else { + crm_err("CCM Activation failed %d (max) times", num_ccm_register_fails); + register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); + return; + } + } + + crm_info("CCM connection established..." " waiting for first callback"); + + G_main_add_fd(G_PRIORITY_HIGH, fsa_ev_fd, FALSE, ccm_dispatch, + fsa_ev_token, default_ipc_connection_destroy); + + } } #endif - - if(action & ~(A_CCM_CONNECT|A_CCM_DISCONNECT)) { - crm_err("Unexpected action %s in %s", - fsa_action2string(action), __FUNCTION__); + + if (action & ~(A_CCM_CONNECT | A_CCM_DISCONNECT)) { + crm_err("Unexpected action %s in %s", fsa_action2string(action), __FUNCTION__); } } #if SUPPORT_HEARTBEAT void -ccm_event_detail(const oc_ev_membership_t *oc, oc_ed_t event) +ccm_event_detail(const oc_ev_membership_t * oc, oc_ed_t event) { - int lpc; - gboolean member = FALSE; - member = FALSE; - - crm_debug_2("-----------------------"); - crm_info("%s: trans=%d, nodes=%d, new=%d, lost=%d n_idx=%d, " - "new_idx=%d, old_idx=%d", - ccm_event_name(event), - oc->m_instance, - oc->m_n_member, - oc->m_n_in, - oc->m_n_out, - oc->m_memb_idx, - oc->m_in_idx, - oc->m_out_idx); - -#if !CCM_EVENT_DETAIL_PARTIAL - for(lpc=0; lpc < oc->m_n_member; lpc++) { - crm_info("\tCURRENT: %s [nodeid=%d, born=%d]", - oc->m_array[oc->m_memb_idx+lpc].node_uname, - oc->m_array[oc->m_memb_idx+lpc].node_id, - oc->m_array[oc->m_memb_idx+lpc].node_born_on); - - if(safe_str_eq(fsa_our_uname, - oc->m_array[oc->m_memb_idx+lpc].node_uname)) { - member = TRUE; - } - } - if (member == FALSE) { - crm_warn("MY NODE IS NOT IN CCM THE MEMBERSHIP LIST"); - } -#endif - for(lpc=0; lpc<(int)oc->m_n_in; lpc++) { - crm_info("\tNEW: %s [nodeid=%d, born=%d]", - oc->m_array[oc->m_in_idx+lpc].node_uname, - oc->m_array[oc->m_in_idx+lpc].node_id, - oc->m_array[oc->m_in_idx+lpc].node_born_on); - } - - for(lpc=0; lpc<(int)oc->m_n_out; lpc++) { - crm_info("\tLOST: %s [nodeid=%d, born=%d]", - oc->m_array[oc->m_out_idx+lpc].node_uname, - oc->m_array[oc->m_out_idx+lpc].node_id, - oc->m_array[oc->m_out_idx+lpc].node_born_on); - } - - crm_debug_2("-----------------------"); - + int lpc; + gboolean member = FALSE; + + member = FALSE; + + crm_debug_2("-----------------------"); + crm_info("%s: trans=%d, nodes=%d, new=%d, lost=%d n_idx=%d, " + "new_idx=%d, old_idx=%d", + ccm_event_name(event), + oc->m_instance, + oc->m_n_member, oc->m_n_in, oc->m_n_out, oc->m_memb_idx, oc->m_in_idx, oc->m_out_idx); + +# if !CCM_EVENT_DETAIL_PARTIAL + for (lpc = 0; lpc < oc->m_n_member; lpc++) { + crm_info("\tCURRENT: %s [nodeid=%d, born=%d]", + oc->m_array[oc->m_memb_idx + lpc].node_uname, + oc->m_array[oc->m_memb_idx + lpc].node_id, + oc->m_array[oc->m_memb_idx + lpc].node_born_on); + + if (safe_str_eq(fsa_our_uname, oc->m_array[oc->m_memb_idx + lpc].node_uname)) { + member = TRUE; + } + } + if (member == FALSE) { + crm_warn("MY NODE IS NOT IN CCM THE MEMBERSHIP LIST"); + } +# endif + for (lpc = 0; lpc < (int)oc->m_n_in; lpc++) { + crm_info("\tNEW: %s [nodeid=%d, born=%d]", + oc->m_array[oc->m_in_idx + lpc].node_uname, + oc->m_array[oc->m_in_idx + lpc].node_id, + oc->m_array[oc->m_in_idx + lpc].node_born_on); + } + + for (lpc = 0; lpc < (int)oc->m_n_out; lpc++) { + crm_info("\tLOST: %s [nodeid=%d, born=%d]", + oc->m_array[oc->m_out_idx + lpc].node_uname, + oc->m_array[oc->m_out_idx + lpc].node_id, + oc->m_array[oc->m_out_idx + lpc].node_born_on); + } + + crm_debug_2("-----------------------"); + } #endif gboolean ever_had_quorum = FALSE; void -post_cache_update(int instance) +post_cache_update(int instance) { xmlNode *no_op = NULL; - + crm_peer_seq = instance; crm_debug("Updated cache after membership event %d.", instance); - g_hash_table_foreach(crm_peer_cache, reap_dead_ccm_nodes, NULL); + g_hash_table_foreach(crm_peer_cache, reap_dead_ccm_nodes, NULL); set_bit_inplace(fsa_input_register, R_CCM_DATA); - - if(AM_I_DC) { - populate_cib_nodes(FALSE); - do_update_cib_nodes(FALSE, __FUNCTION__); + + if (AM_I_DC) { + populate_cib_nodes(FALSE); + do_update_cib_nodes(FALSE, __FUNCTION__); } /* * If we lost nodes, we should re-check the election status * Safe to call outside of an election */ register_fsa_action(A_ELECTION_CHECK); - + /* Membership changed, remind everyone we're here. * This will aid detection of duplicate DCs */ - no_op = create_request( - CRM_OP_NOOP, NULL, NULL, CRM_SYSTEM_CRMD, - AM_I_DC?CRM_SYSTEM_DC:CRM_SYSTEM_CRMD, NULL); + no_op = create_request(CRM_OP_NOOP, NULL, NULL, CRM_SYSTEM_CRMD, + AM_I_DC ? CRM_SYSTEM_DC : CRM_SYSTEM_CRMD, NULL); send_cluster_message(NULL, crm_msg_crmd, no_op, FALSE); free_xml(no_op); } - /* A_CCM_UPDATE_CACHE */ /* * Take the opportunity to update the node status in the CIB as well */ #if SUPPORT_HEARTBEAT void -do_ccm_update_cache( - enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, - oc_ed_t event, const oc_ev_membership_t *oc, xmlNode *xml) +do_ccm_update_cache(enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, + oc_ed_t event, const oc_ev_membership_t * oc, xmlNode * xml) { - unsigned long long instance = 0; - unsigned int lpc = 0; - - if(is_heartbeat_cluster()) { - CRM_ASSERT(oc != NULL); - instance = oc->m_instance; - } - - CRM_ASSERT(crm_peer_seq <= instance); - - switch(cur_state) { - case S_STOPPING: - case S_TERMINATE: - case S_HALT: - crm_debug("Ignoring %s CCM event %llu, we're in state %s", - ccm_event_name(event), instance, - fsa_state2string(cur_state)); - return; - case S_ELECTION: - register_fsa_action(A_ELECTION_CHECK); - break; - default: - break; - } - - if(is_heartbeat_cluster()) { - ccm_event_detail(oc, event); - - /*--*-- Recently Dead Member Nodes --*--*/ - for(lpc=0; lpc < oc->m_n_out; lpc++) { - crm_update_ccm_node(oc, lpc+oc->m_out_idx, CRM_NODE_LOST, instance); - } - - /*--*-- All Member Nodes --*--*/ - for(lpc=0; lpc < oc->m_n_member; lpc++) { - crm_update_ccm_node(oc, lpc+oc->m_memb_idx, CRM_NODE_ACTIVE, instance); - } - } - - if(event == OC_EV_MS_EVICTED) { - crm_update_peer( - 0, 0, 0, -1, 0, - fsa_our_uuid, fsa_our_uname, NULL, CRM_NODE_EVICTED); - - /* todo: drop back to S_PENDING instead */ - /* get out... NOW! - * - * go via the error recovery process so that HA will - * restart us if required - */ - register_fsa_error_adv(cause, I_ERROR, NULL, NULL, __FUNCTION__); - } - - post_cache_update(instance); - return; + unsigned long long instance = 0; + unsigned int lpc = 0; + + if (is_heartbeat_cluster()) { + CRM_ASSERT(oc != NULL); + instance = oc->m_instance; + } + + CRM_ASSERT(crm_peer_seq <= instance); + + switch (cur_state) { + case S_STOPPING: + case S_TERMINATE: + case S_HALT: + crm_debug("Ignoring %s CCM event %llu, we're in state %s", + ccm_event_name(event), instance, fsa_state2string(cur_state)); + return; + case S_ELECTION: + register_fsa_action(A_ELECTION_CHECK); + break; + default: + break; + } + + if (is_heartbeat_cluster()) { + ccm_event_detail(oc, event); + + /*--*-- Recently Dead Member Nodes --*--*/ + for (lpc = 0; lpc < oc->m_n_out; lpc++) { + crm_update_ccm_node(oc, lpc + oc->m_out_idx, CRM_NODE_LOST, instance); + } + + /*--*-- All Member Nodes --*--*/ + for (lpc = 0; lpc < oc->m_n_member; lpc++) { + crm_update_ccm_node(oc, lpc + oc->m_memb_idx, CRM_NODE_ACTIVE, instance); + } + } + + if (event == OC_EV_MS_EVICTED) { + crm_update_peer(0, 0, 0, -1, 0, fsa_our_uuid, fsa_our_uname, NULL, CRM_NODE_EVICTED); + + /* todo: drop back to S_PENDING instead */ + /* get out... NOW! + * + * go via the error recovery process so that HA will + * restart us if required + */ + register_fsa_error_adv(cause, I_ERROR, NULL, NULL, __FUNCTION__); + } + + post_cache_update(instance); + return; } #endif static void -ccm_node_update_complete(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +ccm_node_update_complete(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - fsa_data_t *msg_data = NULL; - last_peer_update = 0; - - if(rc == cib_ok) { - crm_debug_2("Node update %d complete", call_id); - - } else { - crm_err("Node update %d failed", call_id); - crm_log_xml(LOG_DEBUG, "failed", msg); - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - } + fsa_data_t *msg_data = NULL; + + last_peer_update = 0; + + if (rc == cib_ok) { + crm_debug_2("Node update %d complete", call_id); + + } else { + crm_err("Node update %d failed", call_id); + crm_log_xml(LOG_DEBUG, "failed", msg); + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + } } void ghash_update_cib_node(gpointer key, gpointer value, gpointer user_data) { xmlNode *tmp1 = NULL; const char *join = NULL; crm_node_t *node = value; - struct update_data_s* data = (struct update_data_s*)user_data; + struct update_data_s *data = (struct update_data_s *)user_data; data->state = XML_BOOLEAN_NO; - if(safe_str_eq(node->state, CRM_NODE_ACTIVE)) { - data->state = XML_BOOLEAN_YES; + if (safe_str_eq(node->state, CRM_NODE_ACTIVE)) { + data->state = XML_BOOLEAN_YES; } - + crm_debug("Updating %s: %s (overwrite=%s) hash_size=%d", - node->uname, data->state, data->overwrite_join?"true":"false", - g_hash_table_size(confirmed_nodes)); - - if(data->overwrite_join) { - if((node->processes & crm_proc_crmd) == FALSE) { - join = CRMD_JOINSTATE_DOWN; - - } else { - const char *peer_member = g_hash_table_lookup( - confirmed_nodes, node->uname); - if(peer_member != NULL) { - join = CRMD_JOINSTATE_MEMBER; - } else { - join = CRMD_JOINSTATE_PENDING; - } - } + node->uname, data->state, data->overwrite_join ? "true" : "false", + g_hash_table_size(confirmed_nodes)); + + if (data->overwrite_join) { + if ((node->processes & crm_proc_crmd) == FALSE) { + join = CRMD_JOINSTATE_DOWN; + + } else { + const char *peer_member = g_hash_table_lookup(confirmed_nodes, node->uname); + + if (peer_member != NULL) { + join = CRMD_JOINSTATE_MEMBER; + } else { + join = CRMD_JOINSTATE_PENDING; + } + } } - - tmp1 = create_node_state( - node->uname, (node->processes&crm_proc_ais)?ACTIVESTATUS:DEADSTATUS, - data->state, (node->processes&crm_proc_crmd)?ONLINESTATUS:OFFLINESTATUS, - join, NULL, FALSE, data->caller); - + + tmp1 = + create_node_state(node->uname, (node->processes & crm_proc_ais) ? ACTIVESTATUS : DEADSTATUS, + data->state, + (node->processes & crm_proc_crmd) ? ONLINESTATUS : OFFLINESTATUS, join, + NULL, FALSE, data->caller); + add_node_copy(data->updates, tmp1); free_xml(tmp1); } void do_update_cib_nodes(gboolean overwrite, const char *caller) { int call_id = 0; - int call_options = cib_scope_local|cib_quorum_override; + int call_options = cib_scope_local | cib_quorum_override; struct update_data_s update_data; xmlNode *fragment = NULL; - - if(crm_peer_cache == NULL) { - /* We got a replace notification before being connected to - * the CCM. - * So there is no need to update the local CIB with our values - * - since we have none. - */ - return; - - } else if(AM_I_DC == FALSE) { - return; + + if (crm_peer_cache == NULL) { + /* We got a replace notification before being connected to + * the CCM. + * So there is no need to update the local CIB with our values + * - since we have none. + */ + return; + + } else if (AM_I_DC == FALSE) { + return; } - + fragment = create_xml_node(NULL, XML_CIB_TAG_STATUS); - + update_data.caller = caller; update_data.updates = fragment; update_data.overwrite_join = overwrite; - + g_hash_table_foreach(crm_peer_cache, ghash_update_cib_node, &update_data); - + fsa_cib_update(XML_CIB_TAG_STATUS, fragment, call_options, call_id, NULL); add_cib_op_callback(fsa_cib_conn, call_id, FALSE, NULL, ccm_node_update_complete); last_peer_update = call_id; - + free_xml(fragment); } -static void cib_quorum_update_complete( - xmlNode *msg, int call_id, int rc, xmlNode *output, void *user_data) +static void +cib_quorum_update_complete(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - fsa_data_t *msg_data = NULL; - - if(rc == cib_ok) { - crm_debug_2("Quorum update %d complete", call_id); - - } else { - crm_err("Quorum update %d failed", call_id); - crm_log_xml(LOG_DEBUG, "failed", msg); - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - } -} - -void crm_update_quorum(gboolean quorum, gboolean force_update) + fsa_data_t *msg_data = NULL; + + if (rc == cib_ok) { + crm_debug_2("Quorum update %d complete", call_id); + + } else { + crm_err("Quorum update %d failed", call_id); + crm_log_xml(LOG_DEBUG, "failed", msg); + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + } +} + +void +crm_update_quorum(gboolean quorum, gboolean force_update) { ever_had_quorum |= quorum; - if(AM_I_DC && (force_update || fsa_has_quorum != quorum)) { - int call_id = 0; - xmlNode *update = NULL; - int call_options = cib_scope_local|cib_quorum_override; - - update = create_xml_node(NULL, XML_TAG_CIB); - crm_xml_add_int(update, XML_ATTR_HAVE_QUORUM, quorum); - set_uuid(update, XML_ATTR_DC_UUID, fsa_our_uname); - - fsa_cib_update(XML_TAG_CIB, update, call_options, call_id, NULL); - crm_info("Updating quorum status to %s (call=%d)", quorum?"true":"false", call_id); - add_cib_op_callback(fsa_cib_conn, call_id, FALSE, NULL, cib_quorum_update_complete); - free_xml(update); + if (AM_I_DC && (force_update || fsa_has_quorum != quorum)) { + int call_id = 0; + xmlNode *update = NULL; + int call_options = cib_scope_local | cib_quorum_override; + + update = create_xml_node(NULL, XML_TAG_CIB); + crm_xml_add_int(update, XML_ATTR_HAVE_QUORUM, quorum); + set_uuid(update, XML_ATTR_DC_UUID, fsa_our_uname); + + fsa_cib_update(XML_TAG_CIB, update, call_options, call_id, NULL); + crm_info("Updating quorum status to %s (call=%d)", quorum ? "true" : "false", call_id); + add_cib_op_callback(fsa_cib_conn, call_id, FALSE, NULL, cib_quorum_update_complete); + free_xml(update); } fsa_has_quorum = quorum; } - diff --git a/crmd/cib.c b/crmd/cib.c index 01e679263d..e642ca7c9b 100644 --- a/crmd/cib.c +++ b/crmd/cib.c @@ -1,232 +1,217 @@ /* * 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 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 #include #include #include #include #include -#include /* for access */ +#include /* for access */ +#include /* for calls to open */ +#include /* for calls to open */ +#include /* for calls to open */ +#include /* for getpwuid */ +#include /* for initgroups */ -#include /* for calls to open */ -#include /* for calls to open */ -#include /* for calls to open */ -#include /* for getpwuid */ -#include /* for initgroups */ - -#include /* for getrlimit */ -#include /* for getrlimit */ +#include /* for getrlimit */ +#include /* for getrlimit */ #include #include #include #include #include #include #include - struct crm_subsystem_s *cib_subsystem = NULL; int cib_retries = 0; static void -do_cib_updated(const char *event, xmlNode *msg) +do_cib_updated(const char *event, xmlNode * msg) { int rc = -1; xmlNode *diff = NULL; - + CRM_CHECK(msg != NULL, return); - crm_element_value_int(msg, F_CIB_RC, &rc); - if(rc < cib_ok) { - crm_debug_3("Filter rc=%d (%s)", rc, cib_error2string(rc)); - return; + crm_element_value_int(msg, F_CIB_RC, &rc); + if (rc < cib_ok) { + crm_debug_3("Filter rc=%d (%s)", rc, cib_error2string(rc)); + return; } diff = get_message_xml(msg, F_CIB_UPDATE_RESULT); - if(get_xpath_object( - "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_CIB_TAG_CRMCONFIG, - diff, LOG_DEBUG) != NULL) { - mainloop_set_trigger(config_read); + if (get_xpath_object + ("//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_CIB_TAG_CRMCONFIG, diff, + LOG_DEBUG) != NULL) { + mainloop_set_trigger(config_read); } } static void -revision_check_callback(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +revision_check_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - int cmp = -1; - const char *revision = NULL; - xmlNode *generation = NULL; - - if(rc != cib_ok) { - fsa_data_t *msg_data = NULL; - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - return; - } - - generation = output; - CRM_CHECK(safe_str_eq(crm_element_name(generation), XML_TAG_CIB), crm_log_xml_err(output, __FUNCTION__); return); - - crm_debug_3("Checking our feature revision is allowed: %s", CIB_FEATURE_SET); - - revision = crm_element_value(generation, XML_ATTR_CRM_VERSION); - cmp = compare_version(revision, CRM_FEATURE_SET); - - if(cmp > 0) { - crm_err("This build (%s) does not support the current" - " resource configuration", VERSION); - crm_err("We can only support up to CRM feature set %s (current=%s)", - CRM_FEATURE_SET, revision); - crm_err("Shutting down the CRM"); - /* go into a stall state */ - register_fsa_error_adv( - C_FSA_INTERNAL, I_SHUTDOWN, NULL, NULL, __FUNCTION__); - return; - } + int cmp = -1; + const char *revision = NULL; + xmlNode *generation = NULL; + + if (rc != cib_ok) { + fsa_data_t *msg_data = NULL; + + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + return; + } + + generation = output; + CRM_CHECK(safe_str_eq(crm_element_name(generation), XML_TAG_CIB), + crm_log_xml_err(output, __FUNCTION__); return); + + crm_debug_3("Checking our feature revision is allowed: %s", CIB_FEATURE_SET); + + revision = crm_element_value(generation, XML_ATTR_CRM_VERSION); + cmp = compare_version(revision, CRM_FEATURE_SET); + + if (cmp > 0) { + crm_err("This build (%s) does not support the current" " resource configuration", VERSION); + crm_err("We can only support up to CRM feature set %s (current=%s)", + CRM_FEATURE_SET, revision); + crm_err("Shutting down the CRM"); + /* go into a stall state */ + register_fsa_error_adv(C_FSA_INTERNAL, I_SHUTDOWN, NULL, NULL, __FUNCTION__); + return; + } } static void -do_cib_replaced(const char *event, xmlNode *msg) +do_cib_replaced(const char *event, xmlNode * msg) { - crm_debug("Updating the CIB after a replace: DC=%s", AM_I_DC?"true":"false"); - if(AM_I_DC == FALSE) { - return; - - } else if(fsa_state == S_FINALIZE_JOIN - && is_set(fsa_input_register, R_CIB_ASKED)) { - /* no need to restart the join - we asked for this replace op */ - return; + crm_debug("Updating the CIB after a replace: DC=%s", AM_I_DC ? "true" : "false"); + if (AM_I_DC == FALSE) { + return; + + } else if (fsa_state == S_FINALIZE_JOIN && is_set(fsa_input_register, R_CIB_ASKED)) { + /* no need to restart the join - we asked for this replace op */ + return; } - + /* start the join process again so we get everyone's LRM status */ populate_cib_nodes(FALSE); do_update_cib_nodes(TRUE, __FUNCTION__); register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL); } /* A_CIB_STOP, A_CIB_START, A_CIB_RESTART, */ void do_cib_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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - struct crm_subsystem_s *this_subsys = cib_subsystem; - - long long stop_actions = A_CIB_STOP; - long long start_actions = A_CIB_START; - - if(action & stop_actions) { - crm_info("Disconnecting CIB"); - clear_bit_inplace(fsa_input_register, R_CIB_CONNECTED); - CRM_ASSERT(fsa_cib_conn != NULL); - - fsa_cib_conn->cmds->del_notify_callback( - fsa_cib_conn, T_CIB_DIFF_NOTIFY, do_cib_updated); - - if(fsa_cib_conn->state != cib_disconnected) { - fsa_cib_conn->cmds->set_slave( - fsa_cib_conn, cib_scope_local); - fsa_cib_conn->cmds->signoff(fsa_cib_conn); - } - } - - if(action & start_actions) { - int rc = cib_ok; - - CRM_ASSERT(fsa_cib_conn != NULL); - - if(cur_state == S_STOPPING) { - crm_err("Ignoring request to start %s after shutdown", - this_subsys->name); - return; - } - - rc = fsa_cib_conn->cmds->signon( - fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command); - - if(rc != cib_ok) { - /* a short wait that usually avoids stalling the FSA */ - sleep(1); - rc = fsa_cib_conn->cmds->signon( - fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command); - } - - if(rc != cib_ok){ - crm_info("Could not connect to the CIB service: %s", cib_error2string(rc)); - - } else if(cib_ok != fsa_cib_conn->cmds->set_connection_dnotify( - fsa_cib_conn, crmd_cib_connection_destroy)) { - crm_err("Could not set dnotify callback"); - - } else if(cib_ok != fsa_cib_conn->cmds->add_notify_callback( - fsa_cib_conn, T_CIB_REPLACE_NOTIFY, - do_cib_replaced)) { - crm_err("Could not set CIB notification callback"); - - } else if(cib_ok != fsa_cib_conn->cmds->add_notify_callback( - fsa_cib_conn, T_CIB_DIFF_NOTIFY, do_cib_updated)) { - crm_err("Could not set CIB notification callback"); - - } else { - set_bit_inplace( - fsa_input_register, R_CIB_CONNECTED); - } - - if(is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) { - - cib_retries++; - crm_warn("Couldn't complete CIB registration %d" - " times... pause and retry", - cib_retries); - - if(cib_retries < 30) { - crm_timer_start(wait_timer); - crmd_fsa_stall(NULL); - - } else { - crm_err("Could not complete CIB" - " registration %d times..." - " hard error", cib_retries); - register_fsa_error( - C_FSA_INTERNAL, I_ERROR, NULL); - } - } else { - int call_id = 0; - - crm_info("CIB connection established"); - - call_id = fsa_cib_conn->cmds->query( - fsa_cib_conn, NULL, NULL, cib_scope_local); - - add_cib_op_callback(fsa_cib_conn, call_id, FALSE, NULL, - revision_check_callback); - cib_retries = 0; - } - } -} + struct crm_subsystem_s *this_subsys = cib_subsystem; + + long long stop_actions = A_CIB_STOP; + long long start_actions = A_CIB_START; + + if (action & stop_actions) { + crm_info("Disconnecting CIB"); + clear_bit_inplace(fsa_input_register, R_CIB_CONNECTED); + CRM_ASSERT(fsa_cib_conn != NULL); + + fsa_cib_conn->cmds->del_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY, do_cib_updated); + + if (fsa_cib_conn->state != cib_disconnected) { + fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local); + fsa_cib_conn->cmds->signoff(fsa_cib_conn); + } + } + if (action & start_actions) { + int rc = cib_ok; + + CRM_ASSERT(fsa_cib_conn != NULL); + + if (cur_state == S_STOPPING) { + crm_err("Ignoring request to start %s after shutdown", this_subsys->name); + return; + } + + rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command); + + if (rc != cib_ok) { + /* a short wait that usually avoids stalling the FSA */ + sleep(1); + rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command); + } + + if (rc != cib_ok) { + crm_info("Could not connect to the CIB service: %s", cib_error2string(rc)); + + } else if (cib_ok != + fsa_cib_conn->cmds->set_connection_dnotify(fsa_cib_conn, + crmd_cib_connection_destroy)) { + crm_err("Could not set dnotify callback"); + + } else if (cib_ok != + fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_REPLACE_NOTIFY, + do_cib_replaced)) { + crm_err("Could not set CIB notification callback"); + + } else if (cib_ok != + fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY, + do_cib_updated)) { + crm_err("Could not set CIB notification callback"); + + } else { + set_bit_inplace(fsa_input_register, R_CIB_CONNECTED); + } + + if (is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) { + + cib_retries++; + crm_warn("Couldn't complete CIB registration %d" + " times... pause and retry", cib_retries); + + if (cib_retries < 30) { + crm_timer_start(wait_timer); + crmd_fsa_stall(NULL); + + } else { + crm_err("Could not complete CIB" + " registration %d times..." " hard error", cib_retries); + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + } + } else { + int call_id = 0; + + crm_info("CIB connection established"); + + call_id = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local); + + add_cib_op_callback(fsa_cib_conn, call_id, FALSE, NULL, revision_check_callback); + cib_retries = 0; + } + } +} diff --git a/crmd/control.c b/crmd/control.c index 42933b1b17..a21a9ae974 100644 --- a/crmd/control.c +++ b/crmd/control.c @@ -1,939 +1,903 @@ /* * 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 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 #include #include #include #include #include #include #include "../lib/common/stack.h" #include #include #include #include #include #include #include #include #include - char *ipc_server = 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; +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) + 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(); + gboolean registered = FALSE; + + if (action & A_HA_DISCONNECT) { + if (is_openais_cluster()) { + crm_peer_destroy(); #if SUPPORT_COROSYNC - terminate_ais_connection(); + terminate_ais_connection(); #endif - crm_info("Disconnected from OpenAIS"); + crm_info("Disconnected from OpenAIS"); #if SUPPORT_HEARTBEAT - } else if(fsa_cluster_conn != NULL) { - set_bit_inplace(fsa_input_register, R_HA_DISCONNECTED); - fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn, FALSE); - crm_info("Disconnected from Heartbeat"); + } else if (fsa_cluster_conn != NULL) { + set_bit_inplace(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(&ais_status_callback); + } + } + + if (action & A_HA_CONNECT) { + crm_set_status_callback(&ais_status_callback); - if(is_openais_cluster()) { + if (is_openais_cluster()) { #if SUPPORT_COROSYNC - registered = crm_connect_corosync(); + registered = crm_connect_corosync(); #endif - } else if(is_heartbeat_cluster()) { + } 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); + 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_debug_3("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_debug_3("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_debug_3("Requesting an initial dump of CRMD client_status"); - fsa_cluster_conn->llc_ops->client_status( - fsa_cluster_conn, NULL, CRM_SYSTEM_CRMD, -1); - } - } + if (is_heartbeat_cluster()) { + crm_debug_3("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_debug_3("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_debug_3("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_inplace(fsa_input_register, R_HA_DISCONNECTED); - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - return; - } - - clear_bit_inplace(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__); - } + if (registered == FALSE) { + set_bit_inplace(fsa_input_register, R_HA_DISCONNECTED); + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + return; + } + + clear_bit_inplace(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) + 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_inplace(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_inplace(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_inplace(fsa_input_register, R_ST_REQUIRED); - - crm_info("Disconnecting STONITH..."); - stonith_api->cmds->disconnect(stonith_api); - } + /* just in case */ + set_bit_inplace(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_inplace(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_inplace(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) + 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 DC: %s", crm_str(fsa_our_dc)); - msg = create_request( - CRM_OP_SHUTDOWN_REQ, NULL, NULL, - CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); - + xmlNode *msg = NULL; + + crm_info("Sending shutdown request to DC: %s", crm_str(fsa_our_dc)); + msg = create_request(CRM_OP_SHUTDOWN_REQ, NULL, NULL, CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); + /* set_bit_inplace(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); + if (send_cluster_message(NULL, crm_msg_crmd, msg, TRUE) == FALSE) { + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + } + free_xml(msg); } 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); -} + 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) +static void +free_mem(fsa_data_t * msg_data) { - g_main_loop_quit(crmd_mainloop); - g_main_loop_unref(crmd_mainloop); - + 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 - slist_destroy(fsa_data_t, fsa_data, fsa_message_queue, - 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); - ); - delete_fsa_input(msg_data); - - if(ipc_clients) { - crm_debug("Number of connected clients: %d", - g_hash_table_size(ipc_clients)); + if (fsa_cluster_conn) { + fsa_cluster_conn->llc_ops->delete(fsa_cluster_conn); + fsa_cluster_conn = NULL; + } +#endif + slist_destroy(fsa_data_t, fsa_data, fsa_message_queue, + 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); + ); + 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_inplace(fsa_input_register, R_CCM_DATA); - - if(te_subsystem->client && te_subsystem->client->client_source) { - crm_debug("Full destroy: TE"); - G_main_del_IPC_Channel(te_subsystem->client->client_source); - } else { - crm_debug("Partial destroy: TE"); - crmd_ipc_connection_destroy(te_subsystem->client); - } - crm_free(te_subsystem); - - if(pe_subsystem->client && pe_subsystem->client->client_source) { - crm_debug("Full destroy: PE"); - G_main_del_IPC_Channel(pe_subsystem->client->client_source); - } else { - crm_debug("Partial destroy: PE"); - crmd_ipc_connection_destroy(pe_subsystem->client); - } - crm_free(pe_subsystem); - - crm_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) { - fsa_lrm_conn->lrm_ops->delete(fsa_lrm_conn); - } - - crm_free(transition_timer); - crm_free(integration_timer); - crm_free(finalization_timer); - crm_free(election_trigger); - crm_free(election_timeout); - crm_free(shutdown_escalation_timer); - crm_free(wait_timer); - crm_free(recheck_timer); - - crm_free(fsa_our_dc_version); - crm_free(fsa_our_uname); - crm_free(fsa_our_uuid); - crm_free(fsa_our_dc); - crm_free(ipc_server); - - crm_free(max_generation_from); - free_xml(max_generation_xml); - - crm_xml_cleanup(); + g_hash_table_destroy(ipc_clients); + } + + empty_uuid_cache(); + crm_peer_destroy(); + clear_bit_inplace(fsa_input_register, R_CCM_DATA); + + if (te_subsystem->client && te_subsystem->client->client_source) { + crm_debug("Full destroy: TE"); + G_main_del_IPC_Channel(te_subsystem->client->client_source); + } else { + crm_debug("Partial destroy: TE"); + crmd_ipc_connection_destroy(te_subsystem->client); + } + crm_free(te_subsystem); + + if (pe_subsystem->client && pe_subsystem->client->client_source) { + crm_debug("Full destroy: PE"); + G_main_del_IPC_Channel(pe_subsystem->client->client_source); + } else { + crm_debug("Partial destroy: PE"); + crmd_ipc_connection_destroy(pe_subsystem->client); + } + crm_free(pe_subsystem); + + crm_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) { + fsa_lrm_conn->lrm_ops->delete(fsa_lrm_conn); + } + + crm_free(transition_timer); + crm_free(integration_timer); + crm_free(finalization_timer); + crm_free(election_trigger); + crm_free(election_timeout); + crm_free(shutdown_escalation_timer); + crm_free(wait_timer); + crm_free(recheck_timer); + + crm_free(fsa_our_dc_version); + crm_free(fsa_our_uname); + crm_free(fsa_our_uuid); + crm_free(fsa_our_dc); + crm_free(ipc_server); + + crm_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) + 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; - } - - free_mem(msg_data); - - crm_info("[%s] stopped (%d)", crm_system_name, exit_code); - cl_flush_logs(); - exit(exit_code); + 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; + } + + free_mem(msg_data); + + crm_info("[%s] stopped (%d)", crm_system_name, exit_code); + cl_flush_logs(); + 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) + 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 = ll_lrm_new(XML_CIB_TAG_LRM); - - /* set up the timers */ - crm_malloc0(transition_timer, sizeof(fsa_timer_t)); - crm_malloc0(integration_timer, sizeof(fsa_timer_t)); - crm_malloc0(finalization_timer, sizeof(fsa_timer_t)); - crm_malloc0(election_trigger, sizeof(fsa_timer_t)); - crm_malloc0(election_timeout, sizeof(fsa_timer_t)); - crm_malloc0(shutdown_escalation_timer, sizeof(fsa_timer_t)); - crm_malloc0(wait_timer, sizeof(fsa_timer_t)); - crm_malloc0(recheck_timer, 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 */ - crm_malloc0(cib_subsystem, sizeof(struct crm_subsystem_s)); - crm_malloc0(te_subsystem, sizeof(struct crm_subsystem_s)); - crm_malloc0(pe_subsystem, sizeof(struct crm_subsystem_s)); - - if(cib_subsystem != NULL) { - cib_subsystem->pid = -1; - cib_subsystem->path = CRM_DAEMON_DIR; - cib_subsystem->name = CRM_SYSTEM_CIB; - cib_subsystem->command = CRM_DAEMON_DIR"/"CRM_SYSTEM_CIB; - cib_subsystem->args = "-VVc"; - 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->path = CRM_DAEMON_DIR; - te_subsystem->name = CRM_SYSTEM_TENGINE; - te_subsystem->command = CRM_DAEMON_DIR"/"CRM_SYSTEM_TENGINE; - te_subsystem->args = NULL; - 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) { - 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); - - set_sigchld_proctrack(G_PRIORITY_HIGH,DEFAULT_MAXDISPATCHTIME); + 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 = ll_lrm_new(XML_CIB_TAG_LRM); + + /* set up the timers */ + crm_malloc0(transition_timer, sizeof(fsa_timer_t)); + crm_malloc0(integration_timer, sizeof(fsa_timer_t)); + crm_malloc0(finalization_timer, sizeof(fsa_timer_t)); + crm_malloc0(election_trigger, sizeof(fsa_timer_t)); + crm_malloc0(election_timeout, sizeof(fsa_timer_t)); + crm_malloc0(shutdown_escalation_timer, sizeof(fsa_timer_t)); + crm_malloc0(wait_timer, sizeof(fsa_timer_t)); + crm_malloc0(recheck_timer, 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 */ + crm_malloc0(cib_subsystem, sizeof(struct crm_subsystem_s)); + crm_malloc0(te_subsystem, sizeof(struct crm_subsystem_s)); + crm_malloc0(pe_subsystem, sizeof(struct crm_subsystem_s)); + + if (cib_subsystem != NULL) { + cib_subsystem->pid = -1; + cib_subsystem->path = CRM_DAEMON_DIR; + cib_subsystem->name = CRM_SYSTEM_CIB; + cib_subsystem->command = CRM_DAEMON_DIR "/" CRM_SYSTEM_CIB; + cib_subsystem->args = "-VVc"; + 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->path = CRM_DAEMON_DIR; + te_subsystem->name = CRM_SYSTEM_TENGINE; + te_subsystem->command = CRM_DAEMON_DIR "/" CRM_SYSTEM_TENGINE; + te_subsystem->args = NULL; + 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) { + 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); + + set_sigchld_proctrack(G_PRIORITY_HIGH, DEFAULT_MAXDISPATCHTIME); } /* 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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { 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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - if(cur_state != S_STARTING) { - crm_err("Start cancelled... %s", fsa_state2string(cur_state)); - return; - - } else if(is_set(fsa_input_register, R_CCM_DATA) == FALSE) { - crm_info("Delaying start, no membership data (%.16llx)", R_CCM_DATA); + if (cur_state != S_STARTING) { + crm_err("Start cancelled... %s", fsa_state2string(cur_state)); + return; + + } else if (is_set(fsa_input_register, R_CCM_DATA) == FALSE) { + crm_info("Delaying start, no membership data (%.16llx)", R_CCM_DATA); - crmd_fsa_stall(NULL); - return; + 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); + } 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; + 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); + } 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; + 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); + } 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; + crmd_fsa_stall(NULL); + return; - } else if(is_set(fsa_input_register, R_PEER_DATA) == FALSE) { - HA_Message *msg = NULL; + } else if (is_set(fsa_input_register, R_PEER_DATA) == FALSE) { + HA_Message *msg = NULL; - /* try reading from HA */ - crm_info("Delaying start, No peer data (%.16llx)", R_PEER_DATA); + /* try reading from HA */ + crm_info("Delaying start, No peer data (%.16llx)", R_PEER_DATA); - crm_debug_3("Looking for a HA message"); + crm_debug_3("Looking for a HA message"); #if SUPPORT_HEARTBEAT - if(is_heartbeat_cluster()) { - msg = fsa_cluster_conn->llc_ops->readmsg(fsa_cluster_conn, 0); - } -#endif - if(msg != NULL) { - crm_debug_3("There was a HA message"); - crm_msg_del(msg); - } - crmd_fsa_stall(NULL); - return; - } - - crm_debug("Init server comms"); - if(ipc_server == NULL) { - ipc_server = crm_strdup(CRM_SYSTEM_CRMD); - } - - if(init_server_ipc_comms(ipc_server, crmd_client_connect, - default_ipc_connection_destroy)) { - 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_inplace(fsa_input_register, R_ST_REQUIRED); - mainloop_set_trigger(stonith_reconnect); - - crm_info("The local CRM is operational"); - clear_bit_inplace(fsa_input_register, R_STARTING); - register_fsa_input(msg_data->fsa_cause, I_PENDING, NULL); + if (is_heartbeat_cluster()) { + msg = fsa_cluster_conn->llc_ops->readmsg(fsa_cluster_conn, 0); + } +#endif + if (msg != NULL) { + crm_debug_3("There was a HA message"); + crm_msg_del(msg); + } + crmd_fsa_stall(NULL); + return; + } + + crm_debug("Init server comms"); + if (ipc_server == NULL) { + ipc_server = crm_strdup(CRM_SYSTEM_CRMD); + } + + if (init_server_ipc_comms(ipc_server, crmd_client_connect, default_ipc_connection_destroy)) { + 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_inplace(fsa_input_register, R_ST_REQUIRED); + mainloop_set_trigger(stonith_reconnect); + + crm_info("The local CRM is operational"); + clear_bit_inplace(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - set_bit_inplace(fsa_input_register, R_IN_RECOVERY); - crm_err("Action %s (%.16llx) not supported", - fsa_action2string(action), action); + set_bit_inplace(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); + 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)); + 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_crmd_options(GHashTable * options) { - verify_all_options(options, crmd_opts, DIMOF(crmd_opts)); + verify_all_options(options, crmd_opts, DIMOF(crmd_opts)); } static const char * -crmd_pref(GHashTable *options, const char *name) +crmd_pref(GHashTable * options, const char *name) { - return get_cluster_pref(options, crmd_opts, DIMOF(crmd_opts), 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) +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 != cib_ok) { - fsa_data_t *msg_data = NULL; - crm_err("Local CIB query resulted in an error: %s", - cib_error2string(rc)); - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - - if(rc == cib_bad_permissions - || rc == cib_dtd_validation - || rc == cib_bad_digest - || rc == cib_bad_config) { - crm_err("The cluster is mis-configured - shutting down and staying down"); - set_bit_inplace(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_info("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_info("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); + const char *value = NULL; + GHashTable *config_hash = NULL; + ha_time_t *now = new_ha_date(TRUE); + + if (rc != cib_ok) { + fsa_data_t *msg_data = NULL; + + crm_err("Local CIB query resulted in an error: %s", cib_error2string(rc)); + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + + if (rc == cib_bad_permissions + || rc == cib_dtd_validation || rc == cib_bad_digest || rc == cib_bad_config) { + crm_err("The cluster is mis-configured - shutting down and staying down"); + set_bit_inplace(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_info("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_info("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_info("Sending expected-votes=%s to corosync", value); - send_ais_text(crm_class_quorum, value, TRUE, NULL, crm_msg_ais); - } + if (is_classic_ais_cluster()) { + value = crmd_pref(config_hash, XML_ATTR_EXPECTED_VOTES); + crm_info("Sending expected-votes=%s to corosync", value); + send_ais_text(crm_class_quorum, value, TRUE, NULL, crm_msg_ais); + } #endif - - set_bit_inplace(fsa_input_register, R_READ_CONFIG); - crm_debug_3("Triggering FSA: %s", __FUNCTION__); - mainloop_set_trigger(fsa_source); - - g_hash_table_destroy(config_hash); + + set_bit_inplace(fsa_input_register, R_READ_CONFIG); + crm_debug_3("Triggering FSA: %s", __FUNCTION__); + mainloop_set_trigger(fsa_source); + + g_hash_table_destroy(config_hash); bail: - free_ha_date(now); + 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); - + 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_debug_2("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) + 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); + 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 { - crm_info("Requesting shutdown"); - set_bit_inplace(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_info("Using default shutdown escalation: %dms", msec); - shutdown_escalation_timer->period_ms = msec; - } - - /* cant rely on this... */ - crm_notice("Forcing shutdown in: %dms", shutdown_escalation_timer->period_ms); - crm_timer_start(shutdown_escalation_timer); - } - - } else { - crm_info("exit from shutdown"); - exit(LSB_EXIT_OK); - - } + 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 { + crm_info("Requesting shutdown"); + set_bit_inplace(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_info("Using default shutdown escalation: %dms", msec); + shutdown_escalation_timer->period_ms = msec; + } + + /* cant rely on this... */ + crm_notice("Forcing shutdown in: %dms", shutdown_escalation_timer->period_ms); + crm_timer_start(shutdown_escalation_timer); + } + + } else { + crm_info("exit from shutdown"); + exit(LSB_EXIT_OK); + + } } static void -default_cib_update_callback(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +default_cib_update_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - if(rc != cib_ok) { - fsa_data_t *msg_data = NULL; - crm_err("CIB Update failed: %s", cib_error2string(rc)); - crm_log_xml_warn(output, "update:failed"); - - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - } + if (rc != cib_ok) { + fsa_data_t *msg_data = NULL; + + crm_err("CIB Update failed: %s", cib_error2string(rc)); + crm_log_xml_warn(output, "update:failed"); + + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + } } #if SUPPORT_HEARTBEAT static void populate_cib_nodes_ha(gboolean with_client_status) { - int call_id = 0; - const char *ha_node = NULL; - xmlNode *cib_node_list = NULL; - - if(fsa_cluster_conn == NULL) { - crm_debug("Not connected"); - return; - } - - /* Async get client status information in the cluster */ - crm_info("Requesting the list of configured nodes"); - fsa_cluster_conn->llc_ops->init_nodewalk(fsa_cluster_conn); - - cib_node_list = create_xml_node(NULL, XML_CIB_TAG_NODES); - do { - const char *ha_node_type = NULL; - const char *ha_node_uuid = NULL; - xmlNode *cib_new_node = NULL; - - ha_node = fsa_cluster_conn->llc_ops->nextnode(fsa_cluster_conn); - if(ha_node == NULL) { - continue; - } - - ha_node_type = fsa_cluster_conn->llc_ops->node_type( - fsa_cluster_conn, ha_node); - if(safe_str_neq(NORMALNODE, ha_node_type)) { - crm_debug("Node %s: skipping '%s'", - ha_node, ha_node_type); - continue; - } - - ha_node_uuid = get_uuid(ha_node); - if(ha_node_uuid == NULL) { - crm_warn("Node %s: no uuid found", ha_node); - continue; - } - - crm_debug("Node: %s (uuid: %s)", ha_node, ha_node_uuid); - cib_new_node = create_xml_node(cib_node_list, XML_CIB_TAG_NODE); - crm_xml_add(cib_new_node, XML_ATTR_ID, ha_node_uuid); - crm_xml_add(cib_new_node, XML_ATTR_UNAME, ha_node); - crm_xml_add(cib_new_node, XML_ATTR_TYPE, ha_node_type); - - } while(ha_node != NULL); - - fsa_cluster_conn->llc_ops->end_nodewalk(fsa_cluster_conn); - - /* Now update the CIB with the list of nodes */ - 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_debug_2("Complete"); + int call_id = 0; + const char *ha_node = NULL; + xmlNode *cib_node_list = NULL; + + if (fsa_cluster_conn == NULL) { + crm_debug("Not connected"); + return; + } + + /* Async get client status information in the cluster */ + crm_info("Requesting the list of configured nodes"); + fsa_cluster_conn->llc_ops->init_nodewalk(fsa_cluster_conn); + + cib_node_list = create_xml_node(NULL, XML_CIB_TAG_NODES); + do { + const char *ha_node_type = NULL; + const char *ha_node_uuid = NULL; + xmlNode *cib_new_node = NULL; + + ha_node = fsa_cluster_conn->llc_ops->nextnode(fsa_cluster_conn); + if (ha_node == NULL) { + continue; + } + + ha_node_type = fsa_cluster_conn->llc_ops->node_type(fsa_cluster_conn, ha_node); + if (safe_str_neq(NORMALNODE, ha_node_type)) { + crm_debug("Node %s: skipping '%s'", ha_node, ha_node_type); + continue; + } + + ha_node_uuid = get_uuid(ha_node); + if (ha_node_uuid == NULL) { + crm_warn("Node %s: no uuid found", ha_node); + continue; + } + + crm_debug("Node: %s (uuid: %s)", ha_node, ha_node_uuid); + cib_new_node = create_xml_node(cib_node_list, XML_CIB_TAG_NODE); + crm_xml_add(cib_new_node, XML_ATTR_ID, ha_node_uuid); + crm_xml_add(cib_new_node, XML_ATTR_UNAME, ha_node); + crm_xml_add(cib_new_node, XML_ATTR_TYPE, ha_node_type); + + } while (ha_node != NULL); + + fsa_cluster_conn->llc_ops->end_nodewalk(fsa_cluster_conn); + + /* Now update the CIB with the list of nodes */ + 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_debug_2("Complete"); } #endif -static void create_cib_node_definition( - gpointer key, gpointer value, gpointer user_data) +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; - + 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_ID, node->uuid); crm_xml_add(cib_new_node, XML_ATTR_UNAME, node->uname); - crm_xml_add(cib_new_node, XML_ATTR_TYPE, NORMALNODE); + 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; + if (is_heartbeat_cluster()) { + populate_cib_nodes_ha(with_client_status); + return; } -#endif +#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); + 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_debug_2("Complete"); } diff --git a/crmd/corosync.c b/crmd/corosync.c index 34c1cea23c..52bd485b6e 100644 --- a/crmd/corosync.c +++ b/crmd/corosync.c @@ -1,174 +1,179 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include #include #include #include - extern void post_cache_update(int seq); extern void crmd_ha_connection_destroy(gpointer user_data); /* A_HA_CONNECT */ -#if SUPPORT_COROSYNC +#if SUPPORT_COROSYNC extern void crmd_ha_msg_filter(xmlNode * msg); -static gboolean crmd_ais_dispatch(AIS_Message *wrapper, char *data, int sender) +static gboolean +crmd_ais_dispatch(AIS_Message * wrapper, char *data, int sender) { int seq = 0; xmlNode *xml = NULL; const char *seq_s = NULL; xml = string2xml(data); - if(xml == NULL) { - crm_err("Could not parse message content (%d): %.100s", wrapper->header.id, data); - return TRUE; + if (xml == NULL) { + crm_err("Could not parse message content (%d): %.100s", wrapper->header.id, data); + return TRUE; } - - switch(wrapper->header.id) { - case crm_class_members: - seq_s = crm_element_value(xml, "id"); - seq = crm_int_helper(seq_s, NULL); - set_bit_inplace(fsa_input_register, R_PEER_DATA); - post_cache_update(seq); - - /* fall through */ - case crm_class_quorum: - crm_update_quorum(crm_have_quorum, FALSE); - if(AM_I_DC) { - const char *votes = crm_element_value(xml, "expected"); - if(votes == NULL || check_number(votes) == FALSE) { - crm_log_xml_err(xml, "Invalid quorum/membership update"); - - } else { - int rc = update_attr( - fsa_cib_conn, cib_quorum_override|cib_scope_local|cib_inhibit_notify, - XML_CIB_TAG_CRMCONFIG, NULL, NULL, NULL, NULL, XML_ATTR_EXPECTED_VOTES, votes, FALSE); - - crm_info("Setting expected votes to %s", votes); - if(cib_ok > rc) { - crm_err("Quorum update failed: %s", cib_error2string(rc)); - } - } - } - break; - - case crm_class_cluster: - crm_xml_add(xml, F_ORIG, wrapper->sender.uname); - crm_xml_add_int(xml, F_SEQ, wrapper->id); - crmd_ha_msg_filter(xml); - break; - - case crm_class_rmpeer: - /* Ignore */ - break; - - case crm_class_notify: - case crm_class_nodeid: - crm_err("Unexpected message class (%d): %.100s", wrapper->header.id, data); - break; - - default: - crm_err("Invalid message class (%d): %.100s", wrapper->header.id, data); + + switch (wrapper->header.id) { + case crm_class_members: + seq_s = crm_element_value(xml, "id"); + seq = crm_int_helper(seq_s, NULL); + set_bit_inplace(fsa_input_register, R_PEER_DATA); + post_cache_update(seq); + + /* fall through */ + case crm_class_quorum: + crm_update_quorum(crm_have_quorum, FALSE); + if (AM_I_DC) { + const char *votes = crm_element_value(xml, "expected"); + + if (votes == NULL || check_number(votes) == FALSE) { + crm_log_xml_err(xml, "Invalid quorum/membership update"); + + } else { + int rc = update_attr(fsa_cib_conn, + cib_quorum_override | cib_scope_local | cib_inhibit_notify, + XML_CIB_TAG_CRMCONFIG, NULL, NULL, NULL, NULL, + XML_ATTR_EXPECTED_VOTES, votes, FALSE); + + crm_info("Setting expected votes to %s", votes); + if (cib_ok > rc) { + crm_err("Quorum update failed: %s", cib_error2string(rc)); + } + } + } + break; + + case crm_class_cluster: + crm_xml_add(xml, F_ORIG, wrapper->sender.uname); + crm_xml_add_int(xml, F_SEQ, wrapper->id); + crmd_ha_msg_filter(xml); + break; + + case crm_class_rmpeer: + /* Ignore */ + break; + + case crm_class_notify: + case crm_class_nodeid: + crm_err("Unexpected message class (%d): %.100s", wrapper->header.id, data); + break; + + default: + crm_err("Invalid message class (%d): %.100s", wrapper->header.id, data); } - - free_xml(xml); + + free_xml(xml); return TRUE; } -static gboolean crmd_cman_dispatch(unsigned long long seq, gboolean quorate) +static gboolean +crmd_cman_dispatch(unsigned long long seq, gboolean quorate) { crm_update_quorum(quorate, FALSE); post_cache_update(seq); return TRUE; } static void crmd_cman_destroy(gpointer user_data) { - if(is_set(fsa_input_register, R_HA_DISCONNECTED)) { - crm_err("connection terminated"); - exit(1); + if (is_set(fsa_input_register, R_HA_DISCONNECTED)) { + crm_err("connection terminated"); + exit(1); } else { - crm_info("connection closed"); + crm_info("connection closed"); } } static void crmd_quorum_destroy(gpointer user_data) { - if(is_set(fsa_input_register, R_HA_DISCONNECTED)) { - crm_err("connection terminated"); - exit(1); + if (is_set(fsa_input_register, R_HA_DISCONNECTED)) { + crm_err("connection terminated"); + exit(1); } else { - crm_info("connection closed"); + crm_info("connection closed"); } } static void crmd_ais_destroy(gpointer user_data) { - if(is_set(fsa_input_register, R_HA_DISCONNECTED)) { - crm_err("connection terminated"); - exit(1); + if (is_set(fsa_input_register, R_HA_DISCONNECTED)) { + crm_err("connection terminated"); + exit(1); } else { - crm_info("connection closed"); + crm_info("connection closed"); } } extern gboolean crm_connect_corosync(void); -gboolean crm_connect_corosync(void) +gboolean +crm_connect_corosync(void) { gboolean rc = FALSE; - if(is_openais_cluster()) { - crm_set_status_callback(&ais_status_callback); - rc = crm_cluster_connect( - &fsa_our_uname, &fsa_our_uuid, crmd_ais_dispatch, crmd_ais_destroy, NULL); + + if (is_openais_cluster()) { + crm_set_status_callback(&ais_status_callback); + rc = crm_cluster_connect(&fsa_our_uname, &fsa_our_uuid, crmd_ais_dispatch, crmd_ais_destroy, + NULL); } - - if(rc && is_corosync_cluster()) { - init_quorum_connection(crmd_cman_dispatch, crmd_quorum_destroy); + + if (rc && is_corosync_cluster()) { + init_quorum_connection(crmd_cman_dispatch, crmd_quorum_destroy); } - - if(rc && is_cman_cluster()) { - init_cman_connection(crmd_cman_dispatch, crmd_cman_destroy); - set_bit_inplace(fsa_input_register, R_CCM_DATA); + + if (rc && is_cman_cluster()) { + init_cman_connection(crmd_cman_dispatch, crmd_cman_destroy); + set_bit_inplace(fsa_input_register, R_CCM_DATA); } return rc; } #endif diff --git a/crmd/election.c b/crmd/election.c index 412397d078..886bf07062 100644 --- a/crmd/election.c +++ b/crmd/election.c @@ -1,573 +1,564 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include #include GHashTable *voted = NULL; uint highest_born_on = -1; static int current_election_id = 1; static int crm_uptime(struct timeval *output) { struct rusage info; int rc = getrusage(RUSAGE_SELF, &info); + output->tv_sec = 0; output->tv_usec = 0; - - if(rc < 0) { - crm_perror(LOG_ERR, "Could not calculate the current uptime"); - return -1; + + if (rc < 0) { + crm_perror(LOG_ERR, "Could not calculate the current uptime"); + return -1; } output->tv_sec = info.ru_utime.tv_sec; output->tv_usec = info.ru_utime.tv_usec; - crm_debug("Current CPU usage is: %lds, %ldus", (long)info.ru_utime.tv_sec, (long)info.ru_utime.tv_usec); + crm_debug("Current CPU usage is: %lds, %ldus", (long)info.ru_utime.tv_sec, + (long)info.ru_utime.tv_usec); return 1; } -static int crm_compare_age(struct timeval your_age) +static int +crm_compare_age(struct timeval your_age) { int fuzz = 10000; struct timeval our_age; - if(crm_uptime(&our_age) < 0) { - return -1; + + if (crm_uptime(&our_age) < 0) { + return -1; } /* We want these times to be "significantly" different */ - if(our_age.tv_sec > your_age.tv_sec) { - crm_debug("Win: %ld vs %ld (seconds)", (long)our_age.tv_sec, (long)your_age.tv_sec); - return 1; - } else if(our_age.tv_sec < your_age.tv_sec) { - crm_debug("Loose: %ld vs %ld (seconds)", (long)our_age.tv_sec, (long)your_age.tv_sec); - return -1; - } else if(our_age.tv_usec > (your_age.tv_usec + fuzz)) { - crm_debug("Win: %ld vs %ld (nano seconds)", (long)our_age.tv_usec, (long)your_age.tv_usec); - return 1; - } else if(our_age.tv_usec < (your_age.tv_usec - fuzz)) { - crm_debug("Loose: %ld vs %ld(nano seconds)", (long)our_age.tv_usec, (long)your_age.tv_usec); - return -1; + if (our_age.tv_sec > your_age.tv_sec) { + crm_debug("Win: %ld vs %ld (seconds)", (long)our_age.tv_sec, (long)your_age.tv_sec); + return 1; + } else if (our_age.tv_sec < your_age.tv_sec) { + crm_debug("Loose: %ld vs %ld (seconds)", (long)our_age.tv_sec, (long)your_age.tv_sec); + return -1; + } else if (our_age.tv_usec > (your_age.tv_usec + fuzz)) { + crm_debug("Win: %ld vs %ld (nano seconds)", (long)our_age.tv_usec, (long)your_age.tv_usec); + return 1; + } else if (our_age.tv_usec < (your_age.tv_usec - fuzz)) { + crm_debug("Loose: %ld vs %ld(nano seconds)", (long)our_age.tv_usec, (long)your_age.tv_usec); + return -1; } return 0; } /* A_ELECTION_VOTE */ void do_election_vote(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - struct timeval age; - xmlNode *vote = NULL; - gboolean not_voting = FALSE; - - /* don't vote if we're in one of these states or wanting to shut down */ - switch(cur_state) { - case S_STARTING: - case S_RECOVERY: - case S_STOPPING: - case S_TERMINATE: - crm_warn("Not voting in election, we're in state %s", - fsa_state2string(cur_state)); - not_voting = TRUE; - break; - default: - break; - } - - if(not_voting == FALSE) { - if(is_set(fsa_input_register, R_STARTING)) { - not_voting = TRUE; - } - } - - if(not_voting) { - if(AM_I_DC) { - register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL); - - } else { - register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL); - } - return; - } - - vote = create_request( - CRM_OP_VOTE, NULL, NULL, - CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL); - - current_election_id++; - crm_xml_add(vote, F_CRM_ELECTION_OWNER, fsa_our_uuid); - crm_xml_add_int(vote, F_CRM_ELECTION_ID, current_election_id); - - crm_uptime(&age); - crm_xml_add_int(vote, F_CRM_ELECTION_AGE_S, age.tv_sec); - crm_xml_add_int(vote, F_CRM_ELECTION_AGE_US, age.tv_usec); - - - send_cluster_message(NULL, crm_msg_crmd, vote, TRUE); - free_xml(vote); - - crm_debug("Started election %d", current_election_id); - if(voted) { - g_hash_table_destroy(voted); - } - voted = NULL; - - if(cur_state == S_ELECTION || cur_state == S_RELEASE_DC) { - crm_timer_start(election_timeout); - - } else if(cur_state != S_INTEGRATION) { - crm_err("Broken? Voting in state %s", - fsa_state2string(cur_state)); - } - - return; + struct timeval age; + xmlNode *vote = NULL; + gboolean not_voting = FALSE; + + /* don't vote if we're in one of these states or wanting to shut down */ + switch (cur_state) { + case S_STARTING: + case S_RECOVERY: + case S_STOPPING: + case S_TERMINATE: + crm_warn("Not voting in election, we're in state %s", fsa_state2string(cur_state)); + not_voting = TRUE; + break; + default: + break; + } + + if (not_voting == FALSE) { + if (is_set(fsa_input_register, R_STARTING)) { + not_voting = TRUE; + } + } + + if (not_voting) { + if (AM_I_DC) { + register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL); + + } else { + register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL); + } + return; + } + + vote = create_request(CRM_OP_VOTE, NULL, NULL, CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL); + + current_election_id++; + crm_xml_add(vote, F_CRM_ELECTION_OWNER, fsa_our_uuid); + crm_xml_add_int(vote, F_CRM_ELECTION_ID, current_election_id); + + crm_uptime(&age); + crm_xml_add_int(vote, F_CRM_ELECTION_AGE_S, age.tv_sec); + crm_xml_add_int(vote, F_CRM_ELECTION_AGE_US, age.tv_usec); + + send_cluster_message(NULL, crm_msg_crmd, vote, TRUE); + free_xml(vote); + + crm_debug("Started election %d", current_election_id); + if (voted) { + g_hash_table_destroy(voted); + } + voted = NULL; + + if (cur_state == S_ELECTION || cur_state == S_RELEASE_DC) { + crm_timer_start(election_timeout); + + } else if (cur_state != S_INTEGRATION) { + crm_err("Broken? Voting in state %s", fsa_state2string(cur_state)); + } + + return; } char *dc_hb_msg = NULL; int beat_num = 0; gboolean do_dc_heartbeat(gpointer data) { - return TRUE; + return TRUE; } -struct election_data_s -{ - const char *winning_uname; - unsigned int winning_bornon; +struct election_data_s { + const char *winning_uname; + unsigned int winning_bornon; }; static void log_member_uname(gpointer key, gpointer value, gpointer user_data) { const crm_node_t *node = value; - if(crm_is_member_active(node)) { - crm_err("%s: %s proc=%.32x", (char*)user_data, (char*)key, node->processes); + + if (crm_is_member_active(node)) { + crm_err("%s: %s proc=%.32x", (char *)user_data, (char *)key, node->processes); } } static void log_node(gpointer key, gpointer value, gpointer user_data) { - crm_err("%s: %s", (char*)user_data, (char*)key); + crm_err("%s: %s", (char *)user_data, (char *)key); } void do_election_check(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - int voted_size = 0; - int num_members = crm_active_members(); - - if(voted) { - voted_size = g_hash_table_size(voted); - } - /* in the case of #voted > #members, it is better to - * wait for the timeout and give the cluster time to - * stabilize - */ - if(fsa_state != S_ELECTION) { - crm_debug("Ignore election check: we not in an election"); - - } else if(voted_size >= num_members) { - /* we won and everyone has voted */ - crm_timer_stop(election_timeout); - register_fsa_input(C_FSA_INTERNAL, I_ELECTION_DC, NULL); - if(voted_size > num_members) { - char *data = NULL; - - data = crm_strdup("member"); - g_hash_table_foreach(crm_peer_cache, log_member_uname, data); - crm_free(data); - - data = crm_strdup("voted"); - g_hash_table_foreach(voted, log_node, data); - crm_free(data); - - } - crm_debug("Destroying voted hash"); - g_hash_table_destroy(voted); - voted = NULL; - - } else { - crm_debug("Still waiting on %d non-votes (%d total)", - num_members - voted_size, num_members); - } - - return; + int voted_size = 0; + int num_members = crm_active_members(); + + if (voted) { + voted_size = g_hash_table_size(voted); + } + /* in the case of #voted > #members, it is better to + * wait for the timeout and give the cluster time to + * stabilize + */ + if (fsa_state != S_ELECTION) { + crm_debug("Ignore election check: we not in an election"); + + } else if (voted_size >= num_members) { + /* we won and everyone has voted */ + crm_timer_stop(election_timeout); + register_fsa_input(C_FSA_INTERNAL, I_ELECTION_DC, NULL); + if (voted_size > num_members) { + char *data = NULL; + + data = crm_strdup("member"); + g_hash_table_foreach(crm_peer_cache, log_member_uname, data); + crm_free(data); + + data = crm_strdup("voted"); + g_hash_table_foreach(voted, log_node, data); + crm_free(data); + + } + crm_debug("Destroying voted hash"); + g_hash_table_destroy(voted); + voted = NULL; + + } else { + crm_debug("Still waiting on %d non-votes (%d total)", + num_members - voted_size, num_members); + } + + return; } -#define win_dampen 1 /* in seconds */ -#define loss_dampen 2 /* in seconds */ +#define win_dampen 1 /* in seconds */ +#define loss_dampen 2 /* in seconds */ /* A_ELECTION_COUNT */ void do_election_count_vote(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - struct timeval your_age; - int election_id = -1; - int log_level = LOG_INFO; - gboolean use_born_on = FALSE; - gboolean done = FALSE; - gboolean we_loose = FALSE; - const char *op = NULL; - const char *vote_from = NULL; - const char *your_version = NULL; - const char *election_owner = NULL; - const char *reason = "unknown"; - crm_node_t *our_node = NULL, *your_node = NULL; - ha_msg_input_t *vote = fsa_typed_data(fsa_dt_ha_msg); - - static time_t last_election_win = 0; - static time_t last_election_loss = 0; - - /* if the membership copy is NULL we REALLY shouldnt be voting - * the question is how we managed to get here. - */ - - CRM_CHECK(msg_data != NULL, return); - CRM_CHECK(crm_peer_cache != NULL, return); - CRM_CHECK(vote != NULL, crm_err("Bogus data from %s", msg_data->origin); return); - CRM_CHECK(vote->msg != NULL, crm_err("Bogus data from %s", msg_data->origin); return); - - your_age.tv_sec = 0; - your_age.tv_usec = 0; - - op = crm_element_value(vote->msg, F_CRM_TASK); - vote_from = crm_element_value(vote->msg, F_CRM_HOST_FROM); - your_version = crm_element_value(vote->msg, F_CRM_VERSION); - election_owner = crm_element_value(vote->msg, F_CRM_ELECTION_OWNER); - crm_element_value_int(vote->msg, F_CRM_ELECTION_ID, &election_id); - crm_element_value_int(vote->msg, F_CRM_ELECTION_AGE_S, (int*)&(your_age.tv_sec)); - crm_element_value_int(vote->msg, F_CRM_ELECTION_AGE_US, (int*)&(your_age.tv_usec)); - - CRM_CHECK(vote_from != NULL, vote_from = fsa_our_uname); - - your_node = crm_get_peer(0, vote_from); - our_node = crm_get_peer(0, fsa_our_uname); - - if(voted == NULL) { - crm_debug("Created voted hash"); - voted = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); - } - - if(is_heartbeat_cluster()) { - use_born_on = TRUE; - } else if(is_classic_ais_cluster()) { - use_born_on = TRUE; - } - - if(cur_state == S_STARTING) { - reason = "Still starting"; - we_loose = TRUE; - - } else if(our_node == NULL || crm_is_member_active(our_node) == FALSE) { - reason = "We are not part of the cluster"; - log_level = LOG_ERR; - we_loose = TRUE; - - } else if(your_node == NULL || crm_is_member_active(your_node) == FALSE) { - reason = "Peer is not part of our cluster"; - log_level = LOG_WARNING; - done = TRUE; - - } else if(election_id != current_election_id - && crm_str_eq(fsa_our_uuid, election_owner, TRUE)) { - log_level = LOG_DEBUG_2; - reason = "Superceeded"; - done = TRUE; - - } else if(crm_str_eq(op, CRM_OP_NOVOTE, TRUE)) { - char *op_copy = crm_strdup(op); - char *uname_copy = crm_strdup(vote_from); - CRM_ASSERT(crm_str_eq(fsa_our_uuid, election_owner, TRUE)); - - /* update the list of nodes that have voted */ - g_hash_table_replace(voted, uname_copy, op_copy); - reason = "Recorded"; - done = TRUE; - - } else if(crm_str_eq(vote_from, fsa_our_uname, TRUE)) { - char *op_copy = crm_strdup(op); - char *uname_copy = crm_strdup(vote_from); - CRM_ASSERT(crm_str_eq(fsa_our_uuid, election_owner, TRUE)); - - /* update ourselves in the list of nodes that have voted */ - g_hash_table_replace(voted, uname_copy, op_copy); - reason = "Recorded"; - done = TRUE; - - } else if(compare_version(your_version, CRM_FEATURE_SET) < 0) { - reason = "Version"; - we_loose = TRUE; - - } else if(compare_version(your_version, CRM_FEATURE_SET) > 0) { - reason = "Version"; - - } else if(crm_compare_age(your_age) < 0) { - reason = "Uptime"; - we_loose = TRUE; - - } else if(crm_compare_age(your_age) > 0) { - reason = "Uptime"; - - /* TODO: Check for y(our) born < 0 */ - } else if(use_born_on && your_node->born < our_node->born) { - reason = "Born"; - we_loose = TRUE; - - } else if(use_born_on && your_node->born > our_node->born) { - reason = "Born"; - - } else if(fsa_our_uname == NULL) { - reason = "Unknown host name"; - we_loose = TRUE; - - } else if(strcasecmp(fsa_our_uname, vote_from) > 0) { - reason = "Host name"; - we_loose = TRUE; - - } else { - reason = "Host name"; - CRM_ASSERT(strcmp(fsa_our_uname, vote_from) != 0); + struct timeval your_age; + int election_id = -1; + int log_level = LOG_INFO; + gboolean use_born_on = FALSE; + gboolean done = FALSE; + gboolean we_loose = FALSE; + const char *op = NULL; + const char *vote_from = NULL; + const char *your_version = NULL; + const char *election_owner = NULL; + const char *reason = "unknown"; + crm_node_t *our_node = NULL, *your_node = NULL; + ha_msg_input_t *vote = fsa_typed_data(fsa_dt_ha_msg); + + static time_t last_election_win = 0; + static time_t last_election_loss = 0; + + /* if the membership copy is NULL we REALLY shouldnt be voting + * the question is how we managed to get here. + */ + + CRM_CHECK(msg_data != NULL, return); + CRM_CHECK(crm_peer_cache != NULL, return); + CRM_CHECK(vote != NULL, crm_err("Bogus data from %s", msg_data->origin); return); + CRM_CHECK(vote->msg != NULL, crm_err("Bogus data from %s", msg_data->origin); return); + + your_age.tv_sec = 0; + your_age.tv_usec = 0; + + op = crm_element_value(vote->msg, F_CRM_TASK); + vote_from = crm_element_value(vote->msg, F_CRM_HOST_FROM); + your_version = crm_element_value(vote->msg, F_CRM_VERSION); + election_owner = crm_element_value(vote->msg, F_CRM_ELECTION_OWNER); + crm_element_value_int(vote->msg, F_CRM_ELECTION_ID, &election_id); + crm_element_value_int(vote->msg, F_CRM_ELECTION_AGE_S, (int *)&(your_age.tv_sec)); + crm_element_value_int(vote->msg, F_CRM_ELECTION_AGE_US, (int *)&(your_age.tv_usec)); + + CRM_CHECK(vote_from != NULL, vote_from = fsa_our_uname); + + your_node = crm_get_peer(0, vote_from); + our_node = crm_get_peer(0, fsa_our_uname); + + if (voted == NULL) { + crm_debug("Created voted hash"); + voted = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, g_hash_destroy_str); + } + + if (is_heartbeat_cluster()) { + use_born_on = TRUE; + } else if (is_classic_ais_cluster()) { + use_born_on = TRUE; + } + + if (cur_state == S_STARTING) { + reason = "Still starting"; + we_loose = TRUE; + + } else if (our_node == NULL || crm_is_member_active(our_node) == FALSE) { + reason = "We are not part of the cluster"; + log_level = LOG_ERR; + we_loose = TRUE; + + } else if (your_node == NULL || crm_is_member_active(your_node) == FALSE) { + reason = "Peer is not part of our cluster"; + log_level = LOG_WARNING; + done = TRUE; + + } else if (election_id != current_election_id && crm_str_eq(fsa_our_uuid, election_owner, TRUE)) { + log_level = LOG_DEBUG_2; + reason = "Superceeded"; + done = TRUE; + + } else if (crm_str_eq(op, CRM_OP_NOVOTE, TRUE)) { + char *op_copy = crm_strdup(op); + char *uname_copy = crm_strdup(vote_from); + + CRM_ASSERT(crm_str_eq(fsa_our_uuid, election_owner, TRUE)); + + /* update the list of nodes that have voted */ + g_hash_table_replace(voted, uname_copy, op_copy); + reason = "Recorded"; + done = TRUE; + + } else if (crm_str_eq(vote_from, fsa_our_uname, TRUE)) { + char *op_copy = crm_strdup(op); + char *uname_copy = crm_strdup(vote_from); + + CRM_ASSERT(crm_str_eq(fsa_our_uuid, election_owner, TRUE)); + + /* update ourselves in the list of nodes that have voted */ + g_hash_table_replace(voted, uname_copy, op_copy); + reason = "Recorded"; + done = TRUE; + + } else if (compare_version(your_version, CRM_FEATURE_SET) < 0) { + reason = "Version"; + we_loose = TRUE; + + } else if (compare_version(your_version, CRM_FEATURE_SET) > 0) { + reason = "Version"; + + } else if (crm_compare_age(your_age) < 0) { + reason = "Uptime"; + we_loose = TRUE; + + } else if (crm_compare_age(your_age) > 0) { + reason = "Uptime"; + + /* TODO: Check for y(our) born < 0 */ + } else if (use_born_on && your_node->born < our_node->born) { + reason = "Born"; + we_loose = TRUE; + + } else if (use_born_on && your_node->born > our_node->born) { + reason = "Born"; + + } else if (fsa_our_uname == NULL) { + reason = "Unknown host name"; + we_loose = TRUE; + + } else if (strcasecmp(fsa_our_uname, vote_from) > 0) { + reason = "Host name"; + we_loose = TRUE; + + } else { + reason = "Host name"; + CRM_ASSERT(strcmp(fsa_our_uname, vote_from) != 0); /* cant happen... * } else if(strcasecmp(fsa_our_uname, vote_from) == 0) { * * default... * } else { // strcasecmp(fsa_our_uname, vote_from) < 0 * we win */ - } - - if(done) { - do_crm_log(log_level+1, "Election %d (current: %d, owner: %s): Processed %s from %s (%s)", - election_id, current_election_id, election_owner, op, vote_from, reason); - - } else if(we_loose) { - xmlNode *novote = create_request( - CRM_OP_NOVOTE, NULL, vote_from, - CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL); - - do_crm_log(log_level+1, "Election %d (owner: %s) lost: %s from %s (%s)", - election_id, election_owner, op, vote_from, reason); - update_dc(NULL); - - crm_timer_stop(election_timeout); - if(fsa_input_register & R_THE_DC) { - crm_debug_3("Give up the DC to %s", vote_from); - register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL); - - } else if(cur_state != S_STARTING) { - crm_debug_3("We werent the DC anyway"); - register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL); - } - - crm_xml_add(novote, F_CRM_ELECTION_OWNER, election_owner); - crm_xml_add_int(novote, F_CRM_ELECTION_ID, election_id); - - send_cluster_message(vote_from, crm_msg_crmd, novote, TRUE); - free_xml(novote); - - fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local); - - last_election_loss = time(NULL); - last_election_win = 0; - - } else { - do_crm_log(log_level, "Election %d (owner: %s) pass: %s from %s (%s)", - election_id, election_owner, op, vote_from, reason); - - if(last_election_loss) { - time_t tm_now = time(NULL); - if(tm_now - last_election_loss < (time_t)loss_dampen) { - crm_info("Election %d ignore: We already lost an election less than %ds ago", - election_id, loss_dampen); - update_dc(NULL); - return; - } - last_election_loss = 0; - } + } + + if (done) { + do_crm_log(log_level + 1, "Election %d (current: %d, owner: %s): Processed %s from %s (%s)", + election_id, current_election_id, election_owner, op, vote_from, reason); + + } else if (we_loose) { + xmlNode *novote = create_request(CRM_OP_NOVOTE, NULL, vote_from, + CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL); + + do_crm_log(log_level + 1, "Election %d (owner: %s) lost: %s from %s (%s)", + election_id, election_owner, op, vote_from, reason); + update_dc(NULL); + + crm_timer_stop(election_timeout); + if (fsa_input_register & R_THE_DC) { + crm_debug_3("Give up the DC to %s", vote_from); + register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL); + + } else if (cur_state != S_STARTING) { + crm_debug_3("We werent the DC anyway"); + register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL); + } + crm_xml_add(novote, F_CRM_ELECTION_OWNER, election_owner); + crm_xml_add_int(novote, F_CRM_ELECTION_ID, election_id); + + send_cluster_message(vote_from, crm_msg_crmd, novote, TRUE); + free_xml(novote); + + fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local); + + last_election_loss = time(NULL); + last_election_win = 0; + + } else { + do_crm_log(log_level, "Election %d (owner: %s) pass: %s from %s (%s)", + election_id, election_owner, op, vote_from, reason); + + if (last_election_loss) { + time_t tm_now = time(NULL); + + if (tm_now - last_election_loss < (time_t) loss_dampen) { + crm_info("Election %d ignore: We already lost an election less than %ds ago", + election_id, loss_dampen); + update_dc(NULL); + return; + } + last_election_loss = 0; + } #if 0 - /* Enabling this code can lead to multiple DCs during SimulStart. - * Specifically when a node comes up after our last 'win' vote. - * - * Fixing and enabling this functionality might become important when - * we start running realy big clusters, but for now leave it disabled. - */ - if(last_election_win) { - time_t tm_now = time(NULL); - if(tm_now - last_election_win < (time_t)win_dampen) { - crm_info("Election %d ignore: We already won an election less than %ds ago", - election_id, win_dampen); - return; - } - } - - last_election_win = time(NULL); + /* Enabling this code can lead to multiple DCs during SimulStart. + * Specifically when a node comes up after our last 'win' vote. + * + * Fixing and enabling this functionality might become important when + * we start running realy big clusters, but for now leave it disabled. + */ + if (last_election_win) { + time_t tm_now = time(NULL); + + if (tm_now - last_election_win < (time_t) win_dampen) { + crm_info("Election %d ignore: We already won an election less than %ds ago", + election_id, win_dampen); + return; + } + } + + last_election_win = time(NULL); #endif - register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL); - g_hash_table_destroy(voted); - voted = NULL; - } + register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL); + g_hash_table_destroy(voted); + voted = NULL; + } } /* A_ELECT_TIMER_START, A_ELECTION_TIMEOUT */ /* we won */ void do_election_timer_ctrl(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { } - static void -feature_update_callback(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +feature_update_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - if(rc != cib_ok) { - fsa_data_t *msg_data = NULL; - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - } + if (rc != cib_ok) { + fsa_data_t *msg_data = NULL; + + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + } } /* A_DC_TAKEOVER */ void do_dc_takeover(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - int rc = cib_ok; - xmlNode *cib = NULL; - GListPtr gIter = NULL; - static const char *cluster_type = NULL; - - if(cluster_type == NULL) { - cluster_type = getenv("HA_cluster_type"); - } - if(cluster_type == NULL) { - cluster_type = "Heartbeat"; - } - - crm_info("Taking over DC status for this partition"); - set_bit_inplace(fsa_input_register, R_THE_DC); - - for(gIter = stonith_cleanup_list; gIter != NULL; gIter = gIter->next) { - char *target = gIter->data; - const char *uuid = get_uuid(target); - send_stonith_update(NULL, target, uuid); - crm_free(target); - } - g_list_free(stonith_cleanup_list); - stonith_cleanup_list = NULL; - + int rc = cib_ok; + xmlNode *cib = NULL; + GListPtr gIter = NULL; + static const char *cluster_type = NULL; + + if (cluster_type == NULL) { + cluster_type = getenv("HA_cluster_type"); + } + if (cluster_type == NULL) { + cluster_type = "Heartbeat"; + } + + crm_info("Taking over DC status for this partition"); + set_bit_inplace(fsa_input_register, R_THE_DC); + + for (gIter = stonith_cleanup_list; gIter != NULL; gIter = gIter->next) { + char *target = gIter->data; + const char *uuid = get_uuid(target); + + send_stonith_update(NULL, target, uuid); + crm_free(target); + } + g_list_free(stonith_cleanup_list); + stonith_cleanup_list = NULL; + #if SUPPORT_COROSYNC - if(is_classic_ais_cluster()) { - send_ais_text(crm_class_quorum, NULL, TRUE, NULL, crm_msg_ais); - } + if (is_classic_ais_cluster()) { + send_ais_text(crm_class_quorum, NULL, TRUE, NULL, crm_msg_ais); + } #endif - - if(voted != NULL) { - crm_debug_2("Destroying voted hash"); - g_hash_table_destroy(voted); - voted = NULL; - } - - set_bit_inplace(fsa_input_register, R_JOIN_OK); - set_bit_inplace(fsa_input_register, R_INVOKE_PE); - - fsa_cib_conn->cmds->set_master(fsa_cib_conn, cib_scope_local); - - cib = create_xml_node(NULL, XML_TAG_CIB); - crm_xml_add(cib, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET); - fsa_cib_update(XML_TAG_CIB, cib, cib_quorum_override, rc, NULL); - add_cib_op_callback(fsa_cib_conn, rc, FALSE, NULL, feature_update_callback); - - update_attr(fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG, - NULL, NULL, NULL, NULL, "dc-version", VERSION"-"BUILD_VERSION, FALSE); - - update_attr(fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG, - NULL, NULL, NULL, NULL, "cluster-infrastructure", cluster_type, FALSE); - - mainloop_set_trigger(config_read); - free_xml(cib); -} + if (voted != NULL) { + crm_debug_2("Destroying voted hash"); + g_hash_table_destroy(voted); + voted = NULL; + } + + set_bit_inplace(fsa_input_register, R_JOIN_OK); + set_bit_inplace(fsa_input_register, R_INVOKE_PE); + + fsa_cib_conn->cmds->set_master(fsa_cib_conn, cib_scope_local); + + cib = create_xml_node(NULL, XML_TAG_CIB); + crm_xml_add(cib, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET); + fsa_cib_update(XML_TAG_CIB, cib, cib_quorum_override, rc, NULL); + add_cib_op_callback(fsa_cib_conn, rc, FALSE, NULL, feature_update_callback); + + update_attr(fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG, + NULL, NULL, NULL, NULL, "dc-version", VERSION "-" BUILD_VERSION, FALSE); + + update_attr(fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG, + NULL, NULL, NULL, NULL, "cluster-infrastructure", cluster_type, FALSE); + + mainloop_set_trigger(config_read); + free_xml(cib); +} /* A_DC_RELEASE */ void do_dc_release(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - if(action & A_DC_RELEASE) { - crm_debug("Releasing the role of DC"); - clear_bit_inplace(fsa_input_register, R_THE_DC); - - } else if (action & A_DC_RELEASED) { - crm_info("DC role released"); + if (action & A_DC_RELEASE) { + crm_debug("Releasing the role of DC"); + clear_bit_inplace(fsa_input_register, R_THE_DC); + + } else if (action & A_DC_RELEASED) { + crm_info("DC role released"); #if 0 - if( are there errors ) { - /* we cant stay up if not healthy */ - /* or perhaps I_ERROR and go to S_RECOVER? */ - result = I_SHUTDOWN; - } + if (are there errors) { + /* we cant stay up if not healthy */ + /* or perhaps I_ERROR and go to S_RECOVER? */ + result = I_SHUTDOWN; + } #endif - register_fsa_input(C_FSA_INTERNAL, I_RELEASE_SUCCESS, NULL); - - } else { - crm_err("Unknown action %s", fsa_action2string(action)); - } + register_fsa_input(C_FSA_INTERNAL, I_RELEASE_SUCCESS, NULL); - crm_debug_2("Am I still the DC? %s", AM_I_DC?XML_BOOLEAN_YES:XML_BOOLEAN_NO); + } else { + crm_err("Unknown action %s", fsa_action2string(action)); + } -} + crm_debug_2("Am I still the DC? %s", AM_I_DC ? XML_BOOLEAN_YES : XML_BOOLEAN_NO); +} diff --git a/crmd/fsa.c b/crmd/fsa.c index af813a61c4..9978405cd5 100644 --- a/crmd/fsa.c +++ b/crmd/fsa.c @@ -1,707 +1,670 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include -char *fsa_our_dc = NULL; -cib_t *fsa_cib_conn = NULL; -char *fsa_our_dc_version = NULL; +char *fsa_our_dc = NULL; +cib_t *fsa_cib_conn = NULL; +char *fsa_our_dc_version = NULL; -ll_lrm_t *fsa_lrm_conn; -char *fsa_our_uuid = NULL; -char *fsa_our_uname = NULL; +ll_lrm_t *fsa_lrm_conn; +char *fsa_our_uuid = NULL; +char *fsa_our_uname = NULL; #if SUPPORT_HEARTBEAT -ll_cluster_t *fsa_cluster_conn; +ll_cluster_t *fsa_cluster_conn; #endif fsa_timer_t *wait_timer = NULL; fsa_timer_t *recheck_timer = NULL; fsa_timer_t *election_trigger = NULL; fsa_timer_t *election_timeout = NULL; fsa_timer_t *transition_timer = NULL; fsa_timer_t *integration_timer = NULL; fsa_timer_t *finalization_timer = NULL; fsa_timer_t *shutdown_escalation_timer = NULL; volatile gboolean do_fsa_stall = FALSE; volatile long long fsa_input_register = 0; volatile long long fsa_actions = A_NOTHING; volatile enum crmd_fsa_state fsa_state = S_STARTING; extern uint highest_born_on; extern uint num_join_invites; extern GHashTable *welcomed_nodes; extern GHashTable *finalized_nodes; extern GHashTable *confirmed_nodes; extern GHashTable *integrated_nodes; extern void initialize_join(gboolean before); #define DOT_PREFIX "actions:trace: " #define do_dot_log(fmt, args...) do_crm_log_unlikely(LOG_DEBUG_2, fmt, ##args) long long do_state_transition(long long actions, - enum crmd_fsa_state cur_state, - enum crmd_fsa_state next_state, - fsa_data_t *msg_data); + enum crmd_fsa_state cur_state, + enum crmd_fsa_state next_state, fsa_data_t * msg_data); void dump_rsc_info(void); -void dump_rsc_info_callback(const xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data); +void dump_rsc_info_callback(const xmlNode * msg, int call_id, int rc, + xmlNode * output, void *user_data); void ghash_print_node(gpointer key, gpointer value, gpointer user_data); -void s_crmd_fsa_actions(fsa_data_t *fsa_data); -void log_fsa_input(fsa_data_t *stored_msg); +void s_crmd_fsa_actions(fsa_data_t * fsa_data); +void log_fsa_input(fsa_data_t * stored_msg); void init_dotfile(void); void init_dotfile(void) { - do_dot_log(DOT_PREFIX"digraph \"g\" {"); - do_dot_log(DOT_PREFIX" size = \"30,30\""); - do_dot_log(DOT_PREFIX" graph ["); - do_dot_log(DOT_PREFIX" fontsize = \"12\""); - do_dot_log(DOT_PREFIX" fontname = \"Times-Roman\""); - do_dot_log(DOT_PREFIX" fontcolor = \"black\""); - do_dot_log(DOT_PREFIX" bb = \"0,0,398.922306,478.927856\""); - do_dot_log(DOT_PREFIX" color = \"black\""); - do_dot_log(DOT_PREFIX" ]"); - do_dot_log(DOT_PREFIX" node ["); - do_dot_log(DOT_PREFIX" fontsize = \"12\""); - do_dot_log(DOT_PREFIX" fontname = \"Times-Roman\""); - do_dot_log(DOT_PREFIX" fontcolor = \"black\""); - do_dot_log(DOT_PREFIX" shape = \"ellipse\""); - do_dot_log(DOT_PREFIX" color = \"black\""); - do_dot_log(DOT_PREFIX" ]"); - do_dot_log(DOT_PREFIX" edge ["); - do_dot_log(DOT_PREFIX" fontsize = \"12\""); - do_dot_log(DOT_PREFIX" fontname = \"Times-Roman\""); - do_dot_log(DOT_PREFIX" fontcolor = \"black\""); - do_dot_log(DOT_PREFIX" color = \"black\""); - do_dot_log(DOT_PREFIX" ]"); - do_dot_log(DOT_PREFIX"// special nodes"); - do_dot_log(DOT_PREFIX" \"S_PENDING\" "); - do_dot_log(DOT_PREFIX" ["); - do_dot_log(DOT_PREFIX" color = \"blue\""); - do_dot_log(DOT_PREFIX" fontcolor = \"blue\""); - do_dot_log(DOT_PREFIX" ]"); - do_dot_log(DOT_PREFIX" \"S_TERMINATE\" "); - do_dot_log(DOT_PREFIX" ["); - do_dot_log(DOT_PREFIX" color = \"red\""); - do_dot_log(DOT_PREFIX" fontcolor = \"red\""); - do_dot_log(DOT_PREFIX" ]"); - do_dot_log(DOT_PREFIX"// DC only nodes"); - do_dot_log(DOT_PREFIX" \"S_INTEGRATION\" [ fontcolor = \"green\" ]"); - do_dot_log(DOT_PREFIX" \"S_POLICY_ENGINE\" [ fontcolor = \"green\" ]"); - do_dot_log(DOT_PREFIX" \"S_TRANSITION_ENGINE\" [ fontcolor = \"green\" ]"); - do_dot_log(DOT_PREFIX" \"S_RELEASE_DC\" [ fontcolor = \"green\" ]"); - do_dot_log(DOT_PREFIX" \"S_IDLE\" [ fontcolor = \"green\" ]"); + do_dot_log(DOT_PREFIX "digraph \"g\" {"); + do_dot_log(DOT_PREFIX " size = \"30,30\""); + do_dot_log(DOT_PREFIX " graph ["); + do_dot_log(DOT_PREFIX " fontsize = \"12\""); + do_dot_log(DOT_PREFIX " fontname = \"Times-Roman\""); + do_dot_log(DOT_PREFIX " fontcolor = \"black\""); + do_dot_log(DOT_PREFIX " bb = \"0,0,398.922306,478.927856\""); + do_dot_log(DOT_PREFIX " color = \"black\""); + do_dot_log(DOT_PREFIX " ]"); + do_dot_log(DOT_PREFIX " node ["); + do_dot_log(DOT_PREFIX " fontsize = \"12\""); + do_dot_log(DOT_PREFIX " fontname = \"Times-Roman\""); + do_dot_log(DOT_PREFIX " fontcolor = \"black\""); + do_dot_log(DOT_PREFIX " shape = \"ellipse\""); + do_dot_log(DOT_PREFIX " color = \"black\""); + do_dot_log(DOT_PREFIX " ]"); + do_dot_log(DOT_PREFIX " edge ["); + do_dot_log(DOT_PREFIX " fontsize = \"12\""); + do_dot_log(DOT_PREFIX " fontname = \"Times-Roman\""); + do_dot_log(DOT_PREFIX " fontcolor = \"black\""); + do_dot_log(DOT_PREFIX " color = \"black\""); + do_dot_log(DOT_PREFIX " ]"); + do_dot_log(DOT_PREFIX "// special nodes"); + do_dot_log(DOT_PREFIX " \"S_PENDING\" "); + do_dot_log(DOT_PREFIX " ["); + do_dot_log(DOT_PREFIX " color = \"blue\""); + do_dot_log(DOT_PREFIX " fontcolor = \"blue\""); + do_dot_log(DOT_PREFIX " ]"); + do_dot_log(DOT_PREFIX " \"S_TERMINATE\" "); + do_dot_log(DOT_PREFIX " ["); + do_dot_log(DOT_PREFIX " color = \"red\""); + do_dot_log(DOT_PREFIX " fontcolor = \"red\""); + do_dot_log(DOT_PREFIX " ]"); + do_dot_log(DOT_PREFIX "// DC only nodes"); + do_dot_log(DOT_PREFIX " \"S_INTEGRATION\" [ fontcolor = \"green\" ]"); + do_dot_log(DOT_PREFIX " \"S_POLICY_ENGINE\" [ fontcolor = \"green\" ]"); + do_dot_log(DOT_PREFIX " \"S_TRANSITION_ENGINE\" [ fontcolor = \"green\" ]"); + do_dot_log(DOT_PREFIX " \"S_RELEASE_DC\" [ fontcolor = \"green\" ]"); + do_dot_log(DOT_PREFIX " \"S_IDLE\" [ fontcolor = \"green\" ]"); } static void -do_fsa_action(fsa_data_t *fsa_data, long long an_action, - void (*function)(long long action, - enum crmd_fsa_cause cause, - enum crmd_fsa_state cur_state, - enum crmd_fsa_input cur_input, - fsa_data_t *msg_data)) +do_fsa_action(fsa_data_t * fsa_data, long long an_action, + void (*function) (long long action, + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input cur_input, fsa_data_t * msg_data)) { - int action_log_level = LOG_DEBUG; - - /* The calls to fsa_action2string() is expensive, - * only make it if we will use the result - */ - - if(an_action & A_MSG_ROUTE) { - action_log_level = LOG_DEBUG_2; - } - - fsa_actions &= ~an_action; - do_crm_log(action_log_level, DOT_PREFIX"\t// %s", fsa_action2string(an_action)); - function(an_action, fsa_data->fsa_cause, fsa_state, fsa_data->fsa_input, fsa_data); + int action_log_level = LOG_DEBUG; + + /* The calls to fsa_action2string() is expensive, + * only make it if we will use the result + */ + + if (an_action & A_MSG_ROUTE) { + action_log_level = LOG_DEBUG_2; + } + + fsa_actions &= ~an_action; + do_crm_log(action_log_level, DOT_PREFIX "\t// %s", fsa_action2string(an_action)); + function(an_action, fsa_data->fsa_cause, fsa_state, fsa_data->fsa_input, fsa_data); } -static long long startup_actions = A_STARTUP|A_CIB_START|A_LRM_CONNECT|A_CCM_CONNECT|A_HA_CONNECT|A_READCONFIG|A_STARTED|A_CL_JOIN_QUERY; +static long long startup_actions = + A_STARTUP | A_CIB_START | A_LRM_CONNECT | A_CCM_CONNECT | A_HA_CONNECT | A_READCONFIG | + A_STARTED | A_CL_JOIN_QUERY; enum crmd_fsa_state s_crmd_fsa(enum crmd_fsa_cause cause) { - fsa_data_t *fsa_data = NULL; - long long register_copy = fsa_input_register; - long long new_actions = A_NOTHING; - enum crmd_fsa_state last_state = fsa_state; - - crm_debug_2("FSA invoked with Cause: %s\tState: %s", - fsa_cause2string(cause), - fsa_state2string(fsa_state)); - - do_fsa_stall = FALSE; - if(is_message() == FALSE && fsa_actions != A_NOTHING) { - /* fake the first message so we can get into the loop */ - crm_malloc0(fsa_data, sizeof(fsa_data_t)); - fsa_data->fsa_input = I_NULL; - fsa_data->fsa_cause = C_FSA_INTERNAL; - fsa_data->origin = __FUNCTION__; - fsa_data->data_type = fsa_dt_none; - fsa_message_queue = g_list_append(fsa_message_queue, fsa_data); - fsa_data = NULL; - } - while(is_message() && do_fsa_stall == FALSE) { - crm_debug_2("Checking messages (%d remaining)", - g_list_length(fsa_message_queue)); - - fsa_data = get_message(); - CRM_CHECK(fsa_data != NULL, continue); - - log_fsa_input(fsa_data); - - /* add any actions back to the queue */ - fsa_actions |= fsa_data->actions; - - /* get the next batch of actions */ - new_actions = crmd_fsa_actions[fsa_data->fsa_input][fsa_state]; - fsa_actions |= new_actions; - - if(fsa_data->fsa_input != I_NULL - && fsa_data->fsa_input != I_ROUTER) { - crm_debug("Processing %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); - } - + fsa_data_t *fsa_data = NULL; + long long register_copy = fsa_input_register; + long long new_actions = A_NOTHING; + enum crmd_fsa_state last_state = fsa_state; + + crm_debug_2("FSA invoked with Cause: %s\tState: %s", + fsa_cause2string(cause), fsa_state2string(fsa_state)); + + do_fsa_stall = FALSE; + if (is_message() == FALSE && fsa_actions != A_NOTHING) { + /* fake the first message so we can get into the loop */ + crm_malloc0(fsa_data, sizeof(fsa_data_t)); + fsa_data->fsa_input = I_NULL; + fsa_data->fsa_cause = C_FSA_INTERNAL; + fsa_data->origin = __FUNCTION__; + fsa_data->data_type = fsa_dt_none; + fsa_message_queue = g_list_append(fsa_message_queue, fsa_data); + fsa_data = NULL; + } + while (is_message() && do_fsa_stall == FALSE) { + crm_debug_2("Checking messages (%d remaining)", g_list_length(fsa_message_queue)); + + fsa_data = get_message(); + CRM_CHECK(fsa_data != NULL, continue); + + log_fsa_input(fsa_data); + + /* add any actions back to the queue */ + fsa_actions |= fsa_data->actions; + + /* get the next batch of actions */ + new_actions = crmd_fsa_actions[fsa_data->fsa_input][fsa_state]; + fsa_actions |= new_actions; + + if (fsa_data->fsa_input != I_NULL && fsa_data->fsa_input != I_ROUTER) { + crm_debug("Processing %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); + } #ifdef FSA_TRACE - if(new_actions != A_NOTHING) { - crm_debug_2("Adding FSA actions %.16llx for %s/%s", - new_actions, fsa_input2string(fsa_data->fsa_input), - fsa_state2string(fsa_state)); - fsa_dump_actions(new_actions, "\tFSA scheduled"); - - } else if(fsa_data->fsa_input != I_NULL && new_actions == A_NOTHING) { - crm_debug("No action specified for input,state (%s,%s)", - fsa_input2string(fsa_data->fsa_input), - fsa_state2string(fsa_state)); - } - if(fsa_data->actions != A_NOTHING) { - crm_debug_2("Adding input actions %.16llx for %s/%s", - new_actions, fsa_input2string(fsa_data->fsa_input), - fsa_state2string(fsa_state)); - fsa_dump_actions(fsa_data->actions,"\tInput scheduled"); - } + if (new_actions != A_NOTHING) { + crm_debug_2("Adding FSA actions %.16llx for %s/%s", + new_actions, fsa_input2string(fsa_data->fsa_input), + fsa_state2string(fsa_state)); + fsa_dump_actions(new_actions, "\tFSA scheduled"); + + } else if (fsa_data->fsa_input != I_NULL && new_actions == A_NOTHING) { + crm_debug("No action specified for input,state (%s,%s)", + fsa_input2string(fsa_data->fsa_input), fsa_state2string(fsa_state)); + } + if (fsa_data->actions != A_NOTHING) { + crm_debug_2("Adding input actions %.16llx for %s/%s", + new_actions, fsa_input2string(fsa_data->fsa_input), + fsa_state2string(fsa_state)); + fsa_dump_actions(fsa_data->actions, "\tInput scheduled"); + } #endif - /* logging : *before* the state is changed */ - if(is_set(fsa_actions, A_ERROR)) { - do_fsa_action(fsa_data, A_ERROR, do_log); - } - if(is_set(fsa_actions, A_WARN)) { - do_fsa_action(fsa_data, A_WARN, do_log); - } - if(is_set(fsa_actions, A_LOG)) { - do_fsa_action(fsa_data, A_LOG, do_log); - } - - /* update state variables */ - last_state = fsa_state; - fsa_state = crmd_fsa_state[fsa_data->fsa_input][fsa_state]; - - /* - * Remove certain actions during shutdown - */ - if(fsa_state == S_STOPPING || ((fsa_input_register & R_SHUTDOWN) == R_SHUTDOWN)) { - clear_bit_inplace(fsa_actions, startup_actions); - } - - /* - * Hook for change of state. - * Allows actions to be added or removed when entering a state - */ - if(last_state != fsa_state){ - fsa_actions = do_state_transition( - fsa_actions, last_state, fsa_state, fsa_data); - } else { - do_dot_log(DOT_PREFIX"\t// FSA input: State=%s \tCause=%s" - " \tInput=%s \tOrigin=%s() \tid=%d", - fsa_state2string(fsa_state), - fsa_cause2string(fsa_data->fsa_cause), - fsa_input2string(fsa_data->fsa_input), - fsa_data->origin, fsa_data->id); - } - - - /* start doing things... */ - s_crmd_fsa_actions(fsa_data); - delete_fsa_input(fsa_data); - fsa_data = NULL; - } - - if(g_list_length(fsa_message_queue) > 0 - || fsa_actions != A_NOTHING || do_fsa_stall) { - crm_debug("Exiting the FSA: queue=%d, fsa_actions=0x%llx, stalled=%s", - g_list_length(fsa_message_queue), fsa_actions, - do_fsa_stall?"true":"false"); - } else { - crm_debug_2("Exiting the FSA"); - } - - /* cleanup inputs? */ - if(register_copy != fsa_input_register) { - long long same = register_copy & fsa_input_register; - fsa_dump_inputs(LOG_DEBUG, "Added input:", - fsa_input_register ^ same); - fsa_dump_inputs(LOG_DEBUG, "Removed input:", - register_copy ^ same); - } - - fsa_dump_queue(LOG_DEBUG); - - return fsa_state; + /* logging : *before* the state is changed */ + if (is_set(fsa_actions, A_ERROR)) { + do_fsa_action(fsa_data, A_ERROR, do_log); + } + if (is_set(fsa_actions, A_WARN)) { + do_fsa_action(fsa_data, A_WARN, do_log); + } + if (is_set(fsa_actions, A_LOG)) { + do_fsa_action(fsa_data, A_LOG, do_log); + } + + /* update state variables */ + last_state = fsa_state; + fsa_state = crmd_fsa_state[fsa_data->fsa_input][fsa_state]; + + /* + * Remove certain actions during shutdown + */ + if (fsa_state == S_STOPPING || ((fsa_input_register & R_SHUTDOWN) == R_SHUTDOWN)) { + clear_bit_inplace(fsa_actions, startup_actions); + } + + /* + * Hook for change of state. + * Allows actions to be added or removed when entering a state + */ + if (last_state != fsa_state) { + fsa_actions = do_state_transition(fsa_actions, last_state, fsa_state, fsa_data); + } else { + do_dot_log(DOT_PREFIX "\t// FSA input: State=%s \tCause=%s" + " \tInput=%s \tOrigin=%s() \tid=%d", + fsa_state2string(fsa_state), + fsa_cause2string(fsa_data->fsa_cause), + fsa_input2string(fsa_data->fsa_input), fsa_data->origin, fsa_data->id); + } + + /* start doing things... */ + s_crmd_fsa_actions(fsa_data); + delete_fsa_input(fsa_data); + fsa_data = NULL; + } + + if (g_list_length(fsa_message_queue) > 0 || fsa_actions != A_NOTHING || do_fsa_stall) { + crm_debug("Exiting the FSA: queue=%d, fsa_actions=0x%llx, stalled=%s", + g_list_length(fsa_message_queue), fsa_actions, do_fsa_stall ? "true" : "false"); + } else { + crm_debug_2("Exiting the FSA"); + } + + /* cleanup inputs? */ + if (register_copy != fsa_input_register) { + long long same = register_copy & fsa_input_register; + + fsa_dump_inputs(LOG_DEBUG, "Added input:", fsa_input_register ^ same); + fsa_dump_inputs(LOG_DEBUG, "Removed input:", register_copy ^ same); + } + + fsa_dump_queue(LOG_DEBUG); + + return fsa_state; } - void -s_crmd_fsa_actions(fsa_data_t *fsa_data) +s_crmd_fsa_actions(fsa_data_t * fsa_data) { - /* - * Process actions in order of priority but do only one - * action at a time to avoid complicating the ordering. - */ - CRM_CHECK(fsa_data != NULL, return); - while(fsa_actions != A_NOTHING && do_fsa_stall == FALSE) { - - /* regular action processing in order of action priority - * - * Make sure all actions that connect to required systems - * are performed first - */ - if(fsa_actions & A_ERROR) { - do_fsa_action(fsa_data, A_ERROR, do_log); - } else if(fsa_actions & A_WARN) { - do_fsa_action(fsa_data, A_WARN, do_log); - } else if(fsa_actions & A_LOG) { - do_fsa_action(fsa_data, A_LOG, do_log); - - /* get out of here NOW! before anything worse happens */ - } else if(fsa_actions & A_EXIT_1) { - do_fsa_action(fsa_data, A_EXIT_1, do_exit); - - /* essential start tasks */ - } else if(fsa_actions & A_STARTUP) { - do_fsa_action(fsa_data, A_STARTUP, do_startup); - } else if(fsa_actions & A_CIB_START) { - do_fsa_action(fsa_data, A_CIB_START, do_cib_control); - } else if(fsa_actions & A_HA_CONNECT) { - do_fsa_action(fsa_data, A_HA_CONNECT, do_ha_control); - } else if(fsa_actions & A_READCONFIG) { - do_fsa_action(fsa_data, A_READCONFIG, do_read_config); - - /* sub-system start/connect */ - } else if(fsa_actions & A_LRM_CONNECT) { - do_fsa_action(fsa_data, A_LRM_CONNECT, do_lrm_control); - } else if(fsa_actions & A_CCM_CONNECT) { - do_fsa_action(fsa_data, A_CCM_CONNECT, do_ccm_control); - } else if(fsa_actions & A_TE_START) { - do_fsa_action(fsa_data, A_TE_START, do_te_control); - } else if(fsa_actions & A_PE_START) { - do_fsa_action(fsa_data, A_PE_START, do_pe_control); - - /* sub-system restart */ - } else if((fsa_actions & O_CIB_RESTART) == O_CIB_RESTART) { - do_fsa_action(fsa_data, O_CIB_RESTART, do_cib_control); - } else if((fsa_actions & O_PE_RESTART) == O_PE_RESTART) { - do_fsa_action(fsa_data, O_PE_RESTART, do_pe_control); - } else if((fsa_actions & O_TE_RESTART) == O_TE_RESTART) { - do_fsa_action(fsa_data, O_TE_RESTART, do_te_control); - - /* Timers */ + /* + * Process actions in order of priority but do only one + * action at a time to avoid complicating the ordering. + */ + CRM_CHECK(fsa_data != NULL, return); + while (fsa_actions != A_NOTHING && do_fsa_stall == FALSE) { + + /* regular action processing in order of action priority + * + * Make sure all actions that connect to required systems + * are performed first + */ + if (fsa_actions & A_ERROR) { + do_fsa_action(fsa_data, A_ERROR, do_log); + } else if (fsa_actions & A_WARN) { + do_fsa_action(fsa_data, A_WARN, do_log); + } else if (fsa_actions & A_LOG) { + do_fsa_action(fsa_data, A_LOG, do_log); + + /* get out of here NOW! before anything worse happens */ + } else if (fsa_actions & A_EXIT_1) { + do_fsa_action(fsa_data, A_EXIT_1, do_exit); + + /* essential start tasks */ + } else if (fsa_actions & A_STARTUP) { + do_fsa_action(fsa_data, A_STARTUP, do_startup); + } else if (fsa_actions & A_CIB_START) { + do_fsa_action(fsa_data, A_CIB_START, do_cib_control); + } else if (fsa_actions & A_HA_CONNECT) { + do_fsa_action(fsa_data, A_HA_CONNECT, do_ha_control); + } else if (fsa_actions & A_READCONFIG) { + do_fsa_action(fsa_data, A_READCONFIG, do_read_config); + + /* sub-system start/connect */ + } else if (fsa_actions & A_LRM_CONNECT) { + do_fsa_action(fsa_data, A_LRM_CONNECT, do_lrm_control); + } else if (fsa_actions & A_CCM_CONNECT) { + do_fsa_action(fsa_data, A_CCM_CONNECT, do_ccm_control); + } else if (fsa_actions & A_TE_START) { + do_fsa_action(fsa_data, A_TE_START, do_te_control); + } else if (fsa_actions & A_PE_START) { + do_fsa_action(fsa_data, A_PE_START, do_pe_control); + + /* sub-system restart */ + } else if ((fsa_actions & O_CIB_RESTART) == O_CIB_RESTART) { + do_fsa_action(fsa_data, O_CIB_RESTART, do_cib_control); + } else if ((fsa_actions & O_PE_RESTART) == O_PE_RESTART) { + do_fsa_action(fsa_data, O_PE_RESTART, do_pe_control); + } else if ((fsa_actions & O_TE_RESTART) == O_TE_RESTART) { + do_fsa_action(fsa_data, O_TE_RESTART, do_te_control); + + /* Timers */ /* else if(fsa_actions & O_DC_TIMER_RESTART) { - do_fsa_action(fsa_data, O_DC_TIMER_RESTART, do_timer_control) */; - } else if(fsa_actions & A_DC_TIMER_STOP) { - do_fsa_action(fsa_data, A_DC_TIMER_STOP, do_timer_control); - } else if(fsa_actions & A_INTEGRATE_TIMER_STOP) { - do_fsa_action(fsa_data, A_INTEGRATE_TIMER_STOP, do_timer_control); - } else if(fsa_actions & A_INTEGRATE_TIMER_START) { - do_fsa_action(fsa_data, A_INTEGRATE_TIMER_START,do_timer_control); - } else if(fsa_actions & A_FINALIZE_TIMER_STOP) { - do_fsa_action(fsa_data, A_FINALIZE_TIMER_STOP, do_timer_control); - } else if(fsa_actions & A_FINALIZE_TIMER_START) { - do_fsa_action(fsa_data, A_FINALIZE_TIMER_START, do_timer_control); - - /* - * Highest priority actions - */ - } else if(fsa_actions & A_MSG_ROUTE) { - do_fsa_action(fsa_data, A_MSG_ROUTE, do_msg_route); - } else if(fsa_actions & A_RECOVER) { - do_fsa_action(fsa_data, A_RECOVER, do_recover); - } else if(fsa_actions & A_CL_JOIN_RESULT) { - do_fsa_action(fsa_data, A_CL_JOIN_RESULT, do_cl_join_finalize_respond); - } else if(fsa_actions & A_CL_JOIN_REQUEST) { - do_fsa_action(fsa_data, A_CL_JOIN_REQUEST, do_cl_join_offer_respond); - } else if(fsa_actions & A_SHUTDOWN_REQ) { - do_fsa_action(fsa_data, A_SHUTDOWN_REQ, do_shutdown_req); - } else if(fsa_actions & A_ELECTION_VOTE) { - do_fsa_action(fsa_data, A_ELECTION_VOTE, do_election_vote); - } else if(fsa_actions & A_ELECTION_COUNT) { - do_fsa_action(fsa_data, A_ELECTION_COUNT, do_election_count_vote); - } else if(fsa_actions & A_LRM_EVENT) { - do_fsa_action(fsa_data, A_LRM_EVENT, do_lrm_event); - - /* - * High priority actions - */ - } else if(fsa_actions & A_STARTED) { - do_fsa_action(fsa_data, A_STARTED, do_started); - } else if(fsa_actions & A_CL_JOIN_QUERY) { - do_fsa_action(fsa_data, A_CL_JOIN_QUERY, do_cl_join_query); - } else if(fsa_actions & A_DC_TIMER_START) { - do_fsa_action(fsa_data, A_DC_TIMER_START, do_timer_control); - - /* - * Medium priority actions - */ - } else if(fsa_actions & A_DC_TAKEOVER) { - do_fsa_action(fsa_data, A_DC_TAKEOVER, do_dc_takeover); - } else if(fsa_actions & A_DC_RELEASE) { - do_fsa_action(fsa_data, A_DC_RELEASE, do_dc_release); - } else if(fsa_actions & A_DC_JOIN_FINAL) { - do_fsa_action(fsa_data, A_DC_JOIN_FINAL, do_dc_join_final); - } else if(fsa_actions & A_ELECTION_CHECK) { - do_fsa_action(fsa_data, A_ELECTION_CHECK, do_election_check); - } else if(fsa_actions & A_ELECTION_START) { - do_fsa_action(fsa_data, A_ELECTION_START, do_election_vote); - } else if(fsa_actions & A_TE_HALT) { - do_fsa_action(fsa_data, A_TE_HALT, do_te_invoke); - } else if(fsa_actions & A_TE_CANCEL) { - do_fsa_action(fsa_data, A_TE_CANCEL, do_te_invoke); - } else if(fsa_actions & A_DC_JOIN_OFFER_ALL) { - do_fsa_action(fsa_data, A_DC_JOIN_OFFER_ALL, do_dc_join_offer_all); - } else if(fsa_actions & A_DC_JOIN_OFFER_ONE) { - do_fsa_action(fsa_data, A_DC_JOIN_OFFER_ONE, do_dc_join_offer_all); - } else if(fsa_actions & A_DC_JOIN_PROCESS_REQ) { - do_fsa_action(fsa_data, A_DC_JOIN_PROCESS_REQ, do_dc_join_filter_offer); - } else if(fsa_actions & A_DC_JOIN_PROCESS_ACK) { - do_fsa_action(fsa_data, A_DC_JOIN_PROCESS_ACK, do_dc_join_ack); - - /* - * Low(er) priority actions - * Make sure the CIB is always updated before invoking the - * PE, and the PE before the TE - */ - } else if(fsa_actions & A_DC_JOIN_FINALIZE) { - do_fsa_action(fsa_data, A_DC_JOIN_FINALIZE, do_dc_join_finalize); - } else if(fsa_actions & A_LRM_INVOKE) { - do_fsa_action(fsa_data, A_LRM_INVOKE, do_lrm_invoke); - } else if(fsa_actions & A_PE_INVOKE) { - do_fsa_action(fsa_data, A_PE_INVOKE, do_pe_invoke); - } else if(fsa_actions & A_TE_INVOKE) { - do_fsa_action(fsa_data, A_TE_INVOKE, do_te_invoke); - } else if(fsa_actions & A_CL_JOIN_ANNOUNCE) { - do_fsa_action(fsa_data, A_CL_JOIN_ANNOUNCE, do_cl_join_announce); - - /* sub-system stop */ - } else if(fsa_actions & A_DC_RELEASED) { - do_fsa_action(fsa_data, A_DC_RELEASED, do_dc_release); - } else if(fsa_actions & A_PE_STOP) { - do_fsa_action(fsa_data, A_PE_STOP, do_pe_control); - } else if(fsa_actions & A_TE_STOP) { - do_fsa_action(fsa_data, A_TE_STOP, do_te_control); - } else if(fsa_actions & A_SHUTDOWN) { - do_fsa_action(fsa_data, A_SHUTDOWN, do_shutdown); - } else if(fsa_actions & A_LRM_DISCONNECT) { - do_fsa_action(fsa_data, A_LRM_DISCONNECT, do_lrm_control); - } else if(fsa_actions & A_CCM_DISCONNECT) { - do_fsa_action(fsa_data, A_CCM_DISCONNECT, do_ccm_control); - } else if(fsa_actions & A_HA_DISCONNECT) { - do_fsa_action(fsa_data, A_HA_DISCONNECT, do_ha_control); - } else if(fsa_actions & A_CIB_STOP) { - do_fsa_action(fsa_data, A_CIB_STOP, do_cib_control); - } else if(fsa_actions & A_STOP) { - do_fsa_action(fsa_data, A_STOP, do_stop); - - /* exit gracefully */ - } else if(fsa_actions & A_EXIT_0) { - do_fsa_action(fsa_data, A_EXIT_0, do_exit); - - /* Error checking and reporting */ - } else { - crm_err("Action %s (0x%llx) not supported ", - fsa_action2string(fsa_actions), fsa_actions); - register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, - fsa_data, NULL, __FUNCTION__); - } - } + do_fsa_action(fsa_data, O_DC_TIMER_RESTART, do_timer_control) */ ; + } else if (fsa_actions & A_DC_TIMER_STOP) { + do_fsa_action(fsa_data, A_DC_TIMER_STOP, do_timer_control); + } else if (fsa_actions & A_INTEGRATE_TIMER_STOP) { + do_fsa_action(fsa_data, A_INTEGRATE_TIMER_STOP, do_timer_control); + } else if (fsa_actions & A_INTEGRATE_TIMER_START) { + do_fsa_action(fsa_data, A_INTEGRATE_TIMER_START, do_timer_control); + } else if (fsa_actions & A_FINALIZE_TIMER_STOP) { + do_fsa_action(fsa_data, A_FINALIZE_TIMER_STOP, do_timer_control); + } else if (fsa_actions & A_FINALIZE_TIMER_START) { + do_fsa_action(fsa_data, A_FINALIZE_TIMER_START, do_timer_control); + + /* + * Highest priority actions + */ + } else if (fsa_actions & A_MSG_ROUTE) { + do_fsa_action(fsa_data, A_MSG_ROUTE, do_msg_route); + } else if (fsa_actions & A_RECOVER) { + do_fsa_action(fsa_data, A_RECOVER, do_recover); + } else if (fsa_actions & A_CL_JOIN_RESULT) { + do_fsa_action(fsa_data, A_CL_JOIN_RESULT, do_cl_join_finalize_respond); + } else if (fsa_actions & A_CL_JOIN_REQUEST) { + do_fsa_action(fsa_data, A_CL_JOIN_REQUEST, do_cl_join_offer_respond); + } else if (fsa_actions & A_SHUTDOWN_REQ) { + do_fsa_action(fsa_data, A_SHUTDOWN_REQ, do_shutdown_req); + } else if (fsa_actions & A_ELECTION_VOTE) { + do_fsa_action(fsa_data, A_ELECTION_VOTE, do_election_vote); + } else if (fsa_actions & A_ELECTION_COUNT) { + do_fsa_action(fsa_data, A_ELECTION_COUNT, do_election_count_vote); + } else if (fsa_actions & A_LRM_EVENT) { + do_fsa_action(fsa_data, A_LRM_EVENT, do_lrm_event); + + /* + * High priority actions + */ + } else if (fsa_actions & A_STARTED) { + do_fsa_action(fsa_data, A_STARTED, do_started); + } else if (fsa_actions & A_CL_JOIN_QUERY) { + do_fsa_action(fsa_data, A_CL_JOIN_QUERY, do_cl_join_query); + } else if (fsa_actions & A_DC_TIMER_START) { + do_fsa_action(fsa_data, A_DC_TIMER_START, do_timer_control); + + /* + * Medium priority actions + */ + } else if (fsa_actions & A_DC_TAKEOVER) { + do_fsa_action(fsa_data, A_DC_TAKEOVER, do_dc_takeover); + } else if (fsa_actions & A_DC_RELEASE) { + do_fsa_action(fsa_data, A_DC_RELEASE, do_dc_release); + } else if (fsa_actions & A_DC_JOIN_FINAL) { + do_fsa_action(fsa_data, A_DC_JOIN_FINAL, do_dc_join_final); + } else if (fsa_actions & A_ELECTION_CHECK) { + do_fsa_action(fsa_data, A_ELECTION_CHECK, do_election_check); + } else if (fsa_actions & A_ELECTION_START) { + do_fsa_action(fsa_data, A_ELECTION_START, do_election_vote); + } else if (fsa_actions & A_TE_HALT) { + do_fsa_action(fsa_data, A_TE_HALT, do_te_invoke); + } else if (fsa_actions & A_TE_CANCEL) { + do_fsa_action(fsa_data, A_TE_CANCEL, do_te_invoke); + } else if (fsa_actions & A_DC_JOIN_OFFER_ALL) { + do_fsa_action(fsa_data, A_DC_JOIN_OFFER_ALL, do_dc_join_offer_all); + } else if (fsa_actions & A_DC_JOIN_OFFER_ONE) { + do_fsa_action(fsa_data, A_DC_JOIN_OFFER_ONE, do_dc_join_offer_all); + } else if (fsa_actions & A_DC_JOIN_PROCESS_REQ) { + do_fsa_action(fsa_data, A_DC_JOIN_PROCESS_REQ, do_dc_join_filter_offer); + } else if (fsa_actions & A_DC_JOIN_PROCESS_ACK) { + do_fsa_action(fsa_data, A_DC_JOIN_PROCESS_ACK, do_dc_join_ack); + + /* + * Low(er) priority actions + * Make sure the CIB is always updated before invoking the + * PE, and the PE before the TE + */ + } else if (fsa_actions & A_DC_JOIN_FINALIZE) { + do_fsa_action(fsa_data, A_DC_JOIN_FINALIZE, do_dc_join_finalize); + } else if (fsa_actions & A_LRM_INVOKE) { + do_fsa_action(fsa_data, A_LRM_INVOKE, do_lrm_invoke); + } else if (fsa_actions & A_PE_INVOKE) { + do_fsa_action(fsa_data, A_PE_INVOKE, do_pe_invoke); + } else if (fsa_actions & A_TE_INVOKE) { + do_fsa_action(fsa_data, A_TE_INVOKE, do_te_invoke); + } else if (fsa_actions & A_CL_JOIN_ANNOUNCE) { + do_fsa_action(fsa_data, A_CL_JOIN_ANNOUNCE, do_cl_join_announce); + + /* sub-system stop */ + } else if (fsa_actions & A_DC_RELEASED) { + do_fsa_action(fsa_data, A_DC_RELEASED, do_dc_release); + } else if (fsa_actions & A_PE_STOP) { + do_fsa_action(fsa_data, A_PE_STOP, do_pe_control); + } else if (fsa_actions & A_TE_STOP) { + do_fsa_action(fsa_data, A_TE_STOP, do_te_control); + } else if (fsa_actions & A_SHUTDOWN) { + do_fsa_action(fsa_data, A_SHUTDOWN, do_shutdown); + } else if (fsa_actions & A_LRM_DISCONNECT) { + do_fsa_action(fsa_data, A_LRM_DISCONNECT, do_lrm_control); + } else if (fsa_actions & A_CCM_DISCONNECT) { + do_fsa_action(fsa_data, A_CCM_DISCONNECT, do_ccm_control); + } else if (fsa_actions & A_HA_DISCONNECT) { + do_fsa_action(fsa_data, A_HA_DISCONNECT, do_ha_control); + } else if (fsa_actions & A_CIB_STOP) { + do_fsa_action(fsa_data, A_CIB_STOP, do_cib_control); + } else if (fsa_actions & A_STOP) { + do_fsa_action(fsa_data, A_STOP, do_stop); + + /* exit gracefully */ + } else if (fsa_actions & A_EXIT_0) { + do_fsa_action(fsa_data, A_EXIT_0, do_exit); + + /* Error checking and reporting */ + } else { + crm_err("Action %s (0x%llx) not supported ", + fsa_action2string(fsa_actions), fsa_actions); + register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, fsa_data, NULL, __FUNCTION__); + } + } } - -void log_fsa_input(fsa_data_t *stored_msg) +void +log_fsa_input(fsa_data_t * stored_msg) { - crm_debug_2("Processing queued input %d", stored_msg->id); - if(stored_msg->fsa_cause == C_CCM_CALLBACK) { - crm_debug_3("FSA processing CCM callback from %s", - stored_msg->origin); - - } else if(stored_msg->fsa_cause == C_LRM_OP_CALLBACK) { - crm_debug_3("FSA processing LRM callback from %s", - stored_msg->origin); - - } else if(stored_msg->data == NULL) { - crm_debug_3("FSA processing input from %s", - stored_msg->origin); - - } else { - ha_msg_input_t *ha_input = fsa_typed_data_adv( - stored_msg, fsa_dt_ha_msg, __FUNCTION__); - - crm_debug_3("FSA processing XML message from %s", - stored_msg->origin); - crm_log_xml(LOG_MSG, "FSA message data", ha_input->xml); - } + crm_debug_2("Processing queued input %d", stored_msg->id); + if (stored_msg->fsa_cause == C_CCM_CALLBACK) { + crm_debug_3("FSA processing CCM callback from %s", stored_msg->origin); + + } else if (stored_msg->fsa_cause == C_LRM_OP_CALLBACK) { + crm_debug_3("FSA processing LRM callback from %s", stored_msg->origin); + + } else if (stored_msg->data == NULL) { + crm_debug_3("FSA processing input from %s", stored_msg->origin); + + } else { + ha_msg_input_t *ha_input = fsa_typed_data_adv(stored_msg, fsa_dt_ha_msg, __FUNCTION__); + + crm_debug_3("FSA processing XML message from %s", stored_msg->origin); + crm_log_xml(LOG_MSG, "FSA message data", ha_input->xml); + } } -long long +long long do_state_transition(long long actions, - enum crmd_fsa_state cur_state, - enum crmd_fsa_state next_state, - fsa_data_t *msg_data) + enum crmd_fsa_state cur_state, + enum crmd_fsa_state next_state, fsa_data_t * msg_data) { - long long tmp = actions; - gboolean clear_recovery_bit = TRUE; - - enum crmd_fsa_cause cause = msg_data->fsa_cause; - enum crmd_fsa_input current_input = msg_data->fsa_input; - - const char *state_from = fsa_state2string(cur_state); - const char *state_to = fsa_state2string(next_state); - const char *input = fsa_input2string(current_input); - - CRM_LOG_ASSERT(cur_state != next_state); - - do_dot_log(DOT_PREFIX"\t%s -> %s [ label=%s cause=%s origin=%s ]", - state_from, state_to, input, fsa_cause2string(cause), - msg_data->origin); - - crm_info("State transition %s -> %s [ input=%s cause=%s origin=%s ]", - state_from, state_to, input, fsa_cause2string(cause), - msg_data->origin); - - /* the last two clauses might cause trouble later */ - if(election_timeout != NULL - && next_state != S_ELECTION - && cur_state != S_RELEASE_DC) { - crm_timer_stop(election_timeout); + long long tmp = actions; + gboolean clear_recovery_bit = TRUE; + + enum crmd_fsa_cause cause = msg_data->fsa_cause; + enum crmd_fsa_input current_input = msg_data->fsa_input; + + const char *state_from = fsa_state2string(cur_state); + const char *state_to = fsa_state2string(next_state); + const char *input = fsa_input2string(current_input); + + CRM_LOG_ASSERT(cur_state != next_state); + + do_dot_log(DOT_PREFIX "\t%s -> %s [ label=%s cause=%s origin=%s ]", + state_from, state_to, input, fsa_cause2string(cause), msg_data->origin); + + crm_info("State transition %s -> %s [ input=%s cause=%s origin=%s ]", + state_from, state_to, input, fsa_cause2string(cause), msg_data->origin); + + /* the last two clauses might cause trouble later */ + if (election_timeout != NULL && next_state != S_ELECTION && cur_state != S_RELEASE_DC) { + crm_timer_stop(election_timeout); /* } else { */ /* crm_timer_start(election_timeout); */ - } + } #if 0 - if((fsa_input_register & R_SHUTDOWN)){ - set_bit_inplace(tmp, A_DC_TIMER_STOP); - } + if ((fsa_input_register & R_SHUTDOWN)) { + set_bit_inplace(tmp, A_DC_TIMER_STOP); + } #endif - if(next_state == S_INTEGRATION) { - set_bit_inplace(tmp, A_INTEGRATE_TIMER_START); - } else { - set_bit_inplace(tmp, A_INTEGRATE_TIMER_STOP); - } - - if(next_state == S_FINALIZE_JOIN) { - set_bit_inplace(tmp, A_FINALIZE_TIMER_START); - } else { - set_bit_inplace(tmp, A_FINALIZE_TIMER_STOP); - } - - if(next_state != S_PENDING) { - set_bit_inplace(tmp, A_DC_TIMER_STOP); - } - if(next_state != S_ELECTION) { - highest_born_on = 0; - } - if(next_state != S_IDLE) { - crm_timer_stop(recheck_timer); - } - - if(cur_state == S_FINALIZE_JOIN && next_state == S_POLICY_ENGINE) { - populate_cib_nodes(FALSE); - do_update_cib_nodes(TRUE, __FUNCTION__); - } - - switch(next_state) { - case S_PENDING: - fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local); - /* fall through */ - case S_ELECTION: - crm_debug_2("Resetting our DC to NULL on transition to %s", - fsa_state2string(next_state)); - update_dc(NULL); - break; - case S_NOT_DC: - if(is_set(fsa_input_register, R_SHUTDOWN)){ - crm_info("(Re)Issuing shutdown request now" - " that we have a new DC"); - set_bit_inplace(tmp, A_SHUTDOWN_REQ); - } - CRM_LOG_ASSERT(fsa_our_dc != NULL); - if(fsa_our_dc == NULL) { - crm_err("Reached S_NOT_DC without a DC" - " being recorded"); - } - break; - case S_RECOVERY: - clear_recovery_bit = FALSE; - break; - - case S_FINALIZE_JOIN: - CRM_LOG_ASSERT(AM_I_DC); - if(cause == C_TIMER_POPPED) { - crm_warn("Progressed to state %s after %s", - fsa_state2string(next_state), - fsa_cause2string(cause)); - } - if(g_hash_table_size(welcomed_nodes) > 0) { - char *msg = crm_strdup( - " Welcome reply not received from"); - - crm_warn("%u cluster nodes failed to respond" - " to the join offer.", - g_hash_table_size(welcomed_nodes)); - g_hash_table_foreach( - welcomed_nodes, ghash_print_node, msg); - crm_free(msg); - - } else { - crm_info("All %d cluster nodes " - "responded to the join offer.", - g_hash_table_size(integrated_nodes)); - } - break; - - case S_POLICY_ENGINE: - CRM_LOG_ASSERT(AM_I_DC); - if(cause == C_TIMER_POPPED) { - crm_info("Progressed to state %s after %s", - fsa_state2string(next_state), - fsa_cause2string(cause)); - } - - if(g_hash_table_size(finalized_nodes) > 0) { - char *msg = crm_strdup(" Confirm not received from"); - - crm_err("%u cluster nodes failed to confirm" - " their join.", - g_hash_table_size(finalized_nodes)); - g_hash_table_foreach( - finalized_nodes, ghash_print_node, msg); - crm_free(msg); - - } else if(g_hash_table_size(confirmed_nodes) - == crm_active_members()) { - crm_info("All %u cluster nodes are" - " eligible to run resources.", - crm_active_members()); - - } else if(g_hash_table_size(confirmed_nodes) > crm_active_members()) { - crm_err("We have more confirmed nodes than our membership does: %d vs. %d", - g_hash_table_size(confirmed_nodes), crm_active_members()); - register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL); - - } else if(saved_ccm_membership_id != crm_peer_seq) { - crm_info("Membership changed: %llu -> %llu - join restart", - saved_ccm_membership_id, crm_peer_seq); - register_fsa_input_before(C_FSA_INTERNAL, I_NODE_JOIN, NULL); - - } else { - crm_warn("Only %u of %u cluster " - "nodes are eligible to run resources - continue %d", - g_hash_table_size(confirmed_nodes), - crm_active_members(), - g_hash_table_size(welcomed_nodes)); - } + if (next_state == S_INTEGRATION) { + set_bit_inplace(tmp, A_INTEGRATE_TIMER_START); + } else { + set_bit_inplace(tmp, A_INTEGRATE_TIMER_STOP); + } + + if (next_state == S_FINALIZE_JOIN) { + set_bit_inplace(tmp, A_FINALIZE_TIMER_START); + } else { + set_bit_inplace(tmp, A_FINALIZE_TIMER_STOP); + } + + if (next_state != S_PENDING) { + set_bit_inplace(tmp, A_DC_TIMER_STOP); + } + if (next_state != S_ELECTION) { + highest_born_on = 0; + } + if (next_state != S_IDLE) { + crm_timer_stop(recheck_timer); + } + + if (cur_state == S_FINALIZE_JOIN && next_state == S_POLICY_ENGINE) { + populate_cib_nodes(FALSE); + do_update_cib_nodes(TRUE, __FUNCTION__); + } + + switch (next_state) { + case S_PENDING: + fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local); + /* fall through */ + case S_ELECTION: + crm_debug_2("Resetting our DC to NULL on transition to %s", + fsa_state2string(next_state)); + update_dc(NULL); + break; + case S_NOT_DC: + if (is_set(fsa_input_register, R_SHUTDOWN)) { + crm_info("(Re)Issuing shutdown request now" " that we have a new DC"); + set_bit_inplace(tmp, A_SHUTDOWN_REQ); + } + CRM_LOG_ASSERT(fsa_our_dc != NULL); + if (fsa_our_dc == NULL) { + crm_err("Reached S_NOT_DC without a DC" " being recorded"); + } + break; + case S_RECOVERY: + clear_recovery_bit = FALSE; + break; + + case S_FINALIZE_JOIN: + CRM_LOG_ASSERT(AM_I_DC); + if (cause == C_TIMER_POPPED) { + crm_warn("Progressed to state %s after %s", + fsa_state2string(next_state), fsa_cause2string(cause)); + } + if (g_hash_table_size(welcomed_nodes) > 0) { + char *msg = crm_strdup(" Welcome reply not received from"); + + crm_warn("%u cluster nodes failed to respond" + " to the join offer.", g_hash_table_size(welcomed_nodes)); + g_hash_table_foreach(welcomed_nodes, ghash_print_node, msg); + crm_free(msg); + + } else { + crm_info("All %d cluster nodes " + "responded to the join offer.", g_hash_table_size(integrated_nodes)); + } + break; + + case S_POLICY_ENGINE: + CRM_LOG_ASSERT(AM_I_DC); + if (cause == C_TIMER_POPPED) { + crm_info("Progressed to state %s after %s", + fsa_state2string(next_state), fsa_cause2string(cause)); + } + + if (g_hash_table_size(finalized_nodes) > 0) { + char *msg = crm_strdup(" Confirm not received from"); + + crm_err("%u cluster nodes failed to confirm" + " their join.", g_hash_table_size(finalized_nodes)); + g_hash_table_foreach(finalized_nodes, ghash_print_node, msg); + crm_free(msg); + + } else if (g_hash_table_size(confirmed_nodes) + == crm_active_members()) { + crm_info("All %u cluster nodes are" + " eligible to run resources.", crm_active_members()); + + } else if (g_hash_table_size(confirmed_nodes) > crm_active_members()) { + crm_err("We have more confirmed nodes than our membership does: %d vs. %d", + g_hash_table_size(confirmed_nodes), crm_active_members()); + register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL); + + } else if (saved_ccm_membership_id != crm_peer_seq) { + crm_info("Membership changed: %llu -> %llu - join restart", + saved_ccm_membership_id, crm_peer_seq); + register_fsa_input_before(C_FSA_INTERNAL, I_NODE_JOIN, NULL); + + } else { + crm_warn("Only %u of %u cluster " + "nodes are eligible to run resources - continue %d", + g_hash_table_size(confirmed_nodes), + crm_active_members(), g_hash_table_size(welcomed_nodes)); + } /* initialize_join(FALSE); */ - break; - - case S_STOPPING: - case S_TERMINATE: - /* possibly redundant */ - set_bit_inplace(fsa_input_register, R_SHUTDOWN); - break; - - case S_IDLE: - CRM_LOG_ASSERT(AM_I_DC); - dump_rsc_info(); - if(is_set(fsa_input_register, R_SHUTDOWN)){ - crm_info("(Re)Issuing shutdown request now" - " that we are the DC"); - set_bit_inplace(tmp, A_SHUTDOWN_REQ); - } - if(recheck_timer->period_ms > 0) { - crm_info("Starting %s", get_timer_desc(recheck_timer)); - crm_timer_start(recheck_timer); - } - break; - - default: - break; - } - - if(clear_recovery_bit && next_state != S_PENDING) { - tmp &= ~A_RECOVER; - } else if(clear_recovery_bit == FALSE) { - tmp |= A_RECOVER; - } - - if(tmp != actions) { - /* fsa_dump_actions(actions ^ tmp, "New actions"); */ - actions = tmp; - } - - return actions; + break; + + case S_STOPPING: + case S_TERMINATE: + /* possibly redundant */ + set_bit_inplace(fsa_input_register, R_SHUTDOWN); + break; + + case S_IDLE: + CRM_LOG_ASSERT(AM_I_DC); + dump_rsc_info(); + if (is_set(fsa_input_register, R_SHUTDOWN)) { + crm_info("(Re)Issuing shutdown request now" " that we are the DC"); + set_bit_inplace(tmp, A_SHUTDOWN_REQ); + } + if (recheck_timer->period_ms > 0) { + crm_info("Starting %s", get_timer_desc(recheck_timer)); + crm_timer_start(recheck_timer); + } + break; + + default: + break; + } + + if (clear_recovery_bit && next_state != S_PENDING) { + tmp &= ~A_RECOVER; + } else if (clear_recovery_bit == FALSE) { + tmp |= A_RECOVER; + } + + if (tmp != actions) { + /* fsa_dump_actions(actions ^ tmp, "New actions"); */ + actions = tmp; + } + + return actions; } void dump_rsc_info(void) { } - void -ghash_print_node(gpointer key, gpointer value, gpointer user_data) +ghash_print_node(gpointer key, gpointer value, gpointer user_data) { - const char *text = user_data; - const char *uname = key; - const char *value_s = value; - crm_info("%s: %s %s", text, uname, value_s); + const char *text = user_data; + const char *uname = key; + const char *value_s = value; + + crm_info("%s: %s %s", text, uname, value_s); } diff --git a/crmd/join_client.c b/crmd/join_client.c index 1bba44fb5e..41d5c750a5 100644 --- a/crmd/join_client.c +++ b/crmd/join_client.c @@ -1,297 +1,279 @@ /* * 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 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 #include #include #include #include #include #include - int reannounce_count = 0; -void join_query_callback(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data); +void join_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data); -extern ha_msg_input_t *copy_ha_msg_input(ha_msg_input_t *orig); +extern ha_msg_input_t *copy_ha_msg_input(ha_msg_input_t * orig); /* A_CL_JOIN_QUERY */ /* is there a DC out there? */ void do_cl_join_query(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - xmlNode *req = create_request(CRM_OP_JOIN_ANNOUNCE, NULL, NULL, - CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); - - sleep(1); /* give the CCM time to propogate to the DC */ - update_dc(NULL); /* Unset any existing value so that the result is not discarded */ - crm_debug("Querying for a DC"); - send_cluster_message(NULL, crm_msg_crmd, req, FALSE); - free_xml(req); + xmlNode *req = create_request(CRM_OP_JOIN_ANNOUNCE, NULL, NULL, + CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); + + sleep(1); /* give the CCM time to propogate to the DC */ + update_dc(NULL); /* Unset any existing value so that the result is not discarded */ + crm_debug("Querying for a DC"); + send_cluster_message(NULL, crm_msg_crmd, req, FALSE); + free_xml(req); } - /* A_CL_JOIN_ANNOUNCE */ /* this is kind of a workaround for the fact that we may not be around * or are otherwise unable to reply when the DC sends out A_WELCOME_ALL */ void do_cl_join_announce(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_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 */ - if(cur_state != S_PENDING) { - crm_warn("Do not announce ourselves in state %s", - fsa_state2string(cur_state)); - return; - } - - if(AM_I_OPERATIONAL) { - /* send as a broadcast */ - xmlNode *req = create_request( - CRM_OP_JOIN_ANNOUNCE, NULL, NULL, - CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); - - crm_debug("Announcing availability"); - update_dc(NULL); - send_cluster_message(NULL, crm_msg_crmd, req, FALSE); - free_xml(req); - - } else { - /* Delay announce until we have finished local startup */ - crm_warn("Delaying announce until local startup is complete"); - return; - } + /* 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 */ + if (cur_state != S_PENDING) { + crm_warn("Do not announce ourselves in state %s", fsa_state2string(cur_state)); + return; + } + + if (AM_I_OPERATIONAL) { + /* send as a broadcast */ + xmlNode *req = create_request(CRM_OP_JOIN_ANNOUNCE, NULL, NULL, + CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); + + crm_debug("Announcing availability"); + update_dc(NULL); + send_cluster_message(NULL, crm_msg_crmd, req, FALSE); + free_xml(req); + + } else { + /* Delay announce until we have finished local startup */ + crm_warn("Delaying announce until local startup is complete"); + return; + } } - static int query_call_id = 0; /* A_CL_JOIN_REQUEST */ /* aka. accept the welcome offer */ void do_cl_join_offer_respond(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg); - const char *welcome_from = crm_element_value(input->msg, F_CRM_HOST_FROM); - const char *join_id = crm_element_value(input->msg, F_CRM_JOIN_ID); - + ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg); + const char *welcome_from = crm_element_value(input->msg, F_CRM_HOST_FROM); + const char *join_id = crm_element_value(input->msg, F_CRM_JOIN_ID); + #if 0 - if(we are sick) { - log error ; + if (we are sick) { + log error; - /* save the request for later? */ - return; - } + /* save the request for later? */ + return; + } #endif - crm_debug_2("Accepting join offer: join-%s", - crm_element_value(input->msg, F_CRM_JOIN_ID)); - - /* we only ever want the last one */ - if(query_call_id > 0) { - crm_debug_3("Cancelling previous join query: %d", query_call_id); - remove_cib_op_callback(query_call_id, FALSE); - query_call_id = 0; - } - - if(update_dc(input->msg) == FALSE) { - crm_warn("Discarding offer from %s (expected %s)", welcome_from, fsa_our_dc); - return; - } - - CRM_LOG_ASSERT(input != NULL); - query_call_id = fsa_cib_conn->cmds->query( - fsa_cib_conn, NULL, NULL, cib_scope_local); - add_cib_op_callback( - fsa_cib_conn, query_call_id, FALSE, crm_strdup(join_id), join_query_callback); - crm_debug_2("Registered join query callback: %d", query_call_id); - - register_fsa_action(A_DC_TIMER_STOP); + crm_debug_2("Accepting join offer: join-%s", crm_element_value(input->msg, F_CRM_JOIN_ID)); + + /* we only ever want the last one */ + if (query_call_id > 0) { + crm_debug_3("Cancelling previous join query: %d", query_call_id); + remove_cib_op_callback(query_call_id, FALSE); + query_call_id = 0; + } + + if (update_dc(input->msg) == FALSE) { + crm_warn("Discarding offer from %s (expected %s)", welcome_from, fsa_our_dc); + return; + } + + CRM_LOG_ASSERT(input != NULL); + query_call_id = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local); + add_cib_op_callback(fsa_cib_conn, query_call_id, FALSE, crm_strdup(join_id), + join_query_callback); + crm_debug_2("Registered join query callback: %d", query_call_id); + + register_fsa_action(A_DC_TIMER_STOP); } void -join_query_callback(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +join_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - xmlNode *local_cib = NULL; - char *join_id = user_data; - xmlNode *generation = create_xml_node( - NULL, XML_CIB_TAG_GENERATION_TUPPLE); - - CRM_LOG_ASSERT(join_id != NULL); - - query_call_id = 0; - - if(rc == cib_ok) { - local_cib = output; - CRM_LOG_ASSERT(safe_str_eq(crm_element_name(local_cib), XML_TAG_CIB)); - } - - if(local_cib != NULL) { - xmlNode *reply = NULL; - crm_debug("Respond to join offer join-%s", join_id); - crm_debug("Acknowledging %s as our DC", fsa_our_dc); - copy_in_properties(generation, local_cib); - - reply = create_request( - CRM_OP_JOIN_REQUEST, generation, fsa_our_dc, - CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); - - crm_xml_add(reply, F_CRM_JOIN_ID, join_id); - send_cluster_message(fsa_our_dc, crm_msg_crmd, reply, TRUE); - free_xml(reply); - - } else { - crm_err("Could not retrieve Generation to attach to our" - " join acknowledgement: %s", cib_error2string(rc)); - register_fsa_error_adv( - C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__); - } - - crm_free(join_id); - free_xml(generation); + xmlNode *local_cib = NULL; + char *join_id = user_data; + xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE); + + CRM_LOG_ASSERT(join_id != NULL); + + query_call_id = 0; + + if (rc == cib_ok) { + local_cib = output; + CRM_LOG_ASSERT(safe_str_eq(crm_element_name(local_cib), XML_TAG_CIB)); + } + + if (local_cib != NULL) { + xmlNode *reply = NULL; + + crm_debug("Respond to join offer join-%s", join_id); + crm_debug("Acknowledging %s as our DC", fsa_our_dc); + copy_in_properties(generation, local_cib); + + reply = create_request(CRM_OP_JOIN_REQUEST, generation, fsa_our_dc, + CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); + + crm_xml_add(reply, F_CRM_JOIN_ID, join_id); + send_cluster_message(fsa_our_dc, crm_msg_crmd, reply, TRUE); + free_xml(reply); + + } else { + crm_err("Could not retrieve Generation to attach to our" + " join acknowledgement: %s", cib_error2string(rc)); + register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__); + } + + crm_free(join_id); + free_xml(generation); } /* A_CL_JOIN_RESULT */ /* aka. this is notification that we have (or have not) been accepted */ void do_cl_join_finalize_respond(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - xmlNode *tmp1 = NULL; - gboolean was_nack = TRUE; - static gboolean first_join = TRUE; - ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg); - - int join_id = -1; - const char *op = crm_element_value(input->msg,F_CRM_TASK); - const char *ack_nack = crm_element_value(input->msg,CRM_OP_JOIN_ACKNAK); - const char *welcome_from = crm_element_value(input->msg,F_CRM_HOST_FROM); - - if(safe_str_neq(op, CRM_OP_JOIN_ACKNAK)) { - crm_debug_2("Ignoring op=%s message", op); - return; - } - - /* calculate if it was an ack or a nack */ - if(crm_is_true(ack_nack)) { - was_nack = FALSE; - } - - crm_element_value_int(input->msg, F_CRM_JOIN_ID, &join_id); - - if(was_nack) { - crm_err("Join (join-%d) with leader %s failed (NACK'd): Shutting down", - join_id, welcome_from); - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - return; - } - - if(AM_I_DC == FALSE && safe_str_eq(welcome_from, fsa_our_uname)) { - crm_warn("Discarding our own welcome - we're no longer the DC"); - return; - } - - if(update_dc(input->msg) == FALSE) { - crm_warn("Discarding %s from %s (expected %s)", op, welcome_from, fsa_our_dc); - return; - } - - /* send our status section to the DC */ - crm_debug("Confirming join join-%d: %s", - join_id, crm_element_value(input->msg, F_CRM_TASK)); - tmp1 = do_lrm_query(TRUE); - if(tmp1 != NULL) { - xmlNode *reply = create_request( - CRM_OP_JOIN_CONFIRM, tmp1, fsa_our_dc, - CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); - crm_xml_add_int(reply, F_CRM_JOIN_ID, join_id); - - crm_debug("join-%d: Join complete." - " Sending local LRM status to %s", - join_id, fsa_our_dc); - - if(first_join) { - first_join = FALSE; - - /* - * Clear any previous transient node attribute and lrm operations - * - * OpenAIS has a nasty habit of not being able to tell if a - * node is returning or didn't leave in the first place. - * This confuses Pacemaker because it never gets a "node up" - * event which is normally used to clean up the status section. - * - * Do not remove the resources though, they'll be cleaned up in - * do_dc_join_ack(). Removing them here creates a race - * condition if the crmd is being recovered. - * Instead of a list of active resources from the lrmd - * we may end up with a blank status section. - * If we are _NOT_ lucky, we will probe for the "wrong" instance - * of anonymous clones and end up with multiple active - * instances on the machine. - */ - erase_status_tag(fsa_our_uname, XML_TAG_TRANSIENT_NODEATTRS, 0); - - /* Just in case attrd was still around too */ - if(is_not_set(fsa_input_register, R_SHUTDOWN)) { - update_attrd(fsa_our_uname, "terminate", NULL, NULL); - update_attrd(fsa_our_uname, XML_CIB_ATTR_SHUTDOWN, NULL, NULL); - } - } - - send_cluster_message(fsa_our_dc, crm_msg_crmd, reply, TRUE); - free_xml(reply); - - if(AM_I_DC == FALSE) { - register_fsa_input_adv( - cause, I_NOT_DC, NULL, A_NOTHING, TRUE, __FUNCTION__); - update_attrd(NULL, NULL, NULL, NULL); - } - - free_xml(tmp1); - - } else { - crm_err("Could not send our LRM state to the DC"); - register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); - } + xmlNode *tmp1 = NULL; + gboolean was_nack = TRUE; + static gboolean first_join = TRUE; + ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg); + + int join_id = -1; + const char *op = crm_element_value(input->msg, F_CRM_TASK); + const char *ack_nack = crm_element_value(input->msg, CRM_OP_JOIN_ACKNAK); + const char *welcome_from = crm_element_value(input->msg, F_CRM_HOST_FROM); + + if (safe_str_neq(op, CRM_OP_JOIN_ACKNAK)) { + crm_debug_2("Ignoring op=%s message", op); + return; + } + + /* calculate if it was an ack or a nack */ + if (crm_is_true(ack_nack)) { + was_nack = FALSE; + } + + crm_element_value_int(input->msg, F_CRM_JOIN_ID, &join_id); + + if (was_nack) { + crm_err("Join (join-%d) with leader %s failed (NACK'd): Shutting down", + join_id, welcome_from); + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + return; + } + + if (AM_I_DC == FALSE && safe_str_eq(welcome_from, fsa_our_uname)) { + crm_warn("Discarding our own welcome - we're no longer the DC"); + return; + } + + if (update_dc(input->msg) == FALSE) { + crm_warn("Discarding %s from %s (expected %s)", op, welcome_from, fsa_our_dc); + return; + } + + /* send our status section to the DC */ + crm_debug("Confirming join join-%d: %s", join_id, crm_element_value(input->msg, F_CRM_TASK)); + tmp1 = do_lrm_query(TRUE); + if (tmp1 != NULL) { + xmlNode *reply = create_request(CRM_OP_JOIN_CONFIRM, tmp1, fsa_our_dc, + CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL); + + crm_xml_add_int(reply, F_CRM_JOIN_ID, join_id); + + crm_debug("join-%d: Join complete." + " Sending local LRM status to %s", join_id, fsa_our_dc); + + if (first_join) { + first_join = FALSE; + + /* + * Clear any previous transient node attribute and lrm operations + * + * OpenAIS has a nasty habit of not being able to tell if a + * node is returning or didn't leave in the first place. + * This confuses Pacemaker because it never gets a "node up" + * event which is normally used to clean up the status section. + * + * Do not remove the resources though, they'll be cleaned up in + * do_dc_join_ack(). Removing them here creates a race + * condition if the crmd is being recovered. + * Instead of a list of active resources from the lrmd + * we may end up with a blank status section. + * If we are _NOT_ lucky, we will probe for the "wrong" instance + * of anonymous clones and end up with multiple active + * instances on the machine. + */ + erase_status_tag(fsa_our_uname, XML_TAG_TRANSIENT_NODEATTRS, 0); + + /* Just in case attrd was still around too */ + if (is_not_set(fsa_input_register, R_SHUTDOWN)) { + update_attrd(fsa_our_uname, "terminate", NULL, NULL); + update_attrd(fsa_our_uname, XML_CIB_ATTR_SHUTDOWN, NULL, NULL); + } + } + + send_cluster_message(fsa_our_dc, crm_msg_crmd, reply, TRUE); + free_xml(reply); + + if (AM_I_DC == FALSE) { + register_fsa_input_adv(cause, I_NOT_DC, NULL, A_NOTHING, TRUE, __FUNCTION__); + update_attrd(NULL, NULL, NULL, NULL); + } + + free_xml(tmp1); + + } else { + crm_err("Could not send our LRM state to the DC"); + register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); + } } diff --git a/crmd/join_dc.c b/crmd/join_dc.c index 7e58d07bc3..77adbb89fd 100644 --- a/crmd/join_dc.c +++ b/crmd/join_dc.c @@ -1,706 +1,656 @@ /* * 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 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 #include #include #include #include #include #include #include - -GHashTable *welcomed_nodes = NULL; +GHashTable *welcomed_nodes = NULL; GHashTable *integrated_nodes = NULL; -GHashTable *finalized_nodes = NULL; -GHashTable *confirmed_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); +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) { - crm_free(max_generation_from); - max_generation_from = NULL; - } - if(max_generation_xml != NULL) { - free_xml(max_generation_xml); - max_generation_xml = NULL; - } - clear_bit_inplace(fsa_input_register, R_HAVE_CIB); - clear_bit_inplace(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); + /* 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) { + crm_free(max_generation_from); + max_generation_from = NULL; + } + if (max_generation_xml != NULL) { + free_xml(max_generation_xml); + max_generation_xml = NULL; + } + clear_bit_inplace(fsa_input_register, R_HAVE_CIB); + clear_bit_inplace(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) +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_info("Removed node %s from join calculations:" - " welcomed=%d itegrated=%d finalized=%d confirmed=%d", - uname, w, i, f, c); - } + 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_info("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_member_active(member) == FALSE) { - 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(member->processes & crm_proc_crmd) { - 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, crm_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)); - } - + const char *join_to = NULL; + const crm_node_t *member = value; + + CRM_ASSERT(member != NULL); + if (crm_is_member_active(member) == FALSE) { + 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 (member->processes & crm_proc_crmd) { + 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, crm_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) + 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); + /* 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)); + 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) + 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(member == NULL || crm_is_member_active(member) == FALSE) { - crm_err("Attempt to send welcome message " - "to a node not part of our partition!"); - 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_debug("(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); + 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 (member == NULL || crm_is_member_active(member) == FALSE) { + crm_err("Attempt to send welcome message " "to a node not part of our partition!"); + 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_debug("(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) +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; + 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) + 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_member_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 = crm_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"); - - crm_free(max_generation_from); - free_xml(max_generation_xml); - - max_generation_from = crm_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, crm_strdup(join_from), crm_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)); - } -} + 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_member_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 = crm_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"); + + crm_free(max_generation_from); + free_xml(max_generation_xml); + + max_generation_from = crm_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, crm_strdup(join_from), crm_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) + 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; - enum cib_errors rc = cib_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_inplace(fsa_input_register, R_HAVE_CIB); - if(max_generation_from == NULL - || safe_str_eq(max_generation_from, fsa_our_uname)){ - set_bit_inplace(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 = crm_strdup(max_generation_from); - crm_log_xml_debug(max_generation_xml, "Requesting version"); - set_bit_inplace(fsa_input_register, R_CIB_ASKED); - - } else { - /* Send _our_ CIB out to everyone */ - sync_from = crm_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); + char *sync_from = NULL; + enum cib_errors rc = cib_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_inplace(fsa_input_register, R_HAVE_CIB); + if (max_generation_from == NULL || safe_str_eq(max_generation_from, fsa_our_uname)) { + set_bit_inplace(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 = crm_strdup(max_generation_from); + crm_log_xml_debug(max_generation_xml, "Requesting version"); + set_bit_inplace(fsa_input_register, R_CIB_ASKED); + + } else { + /* Send _our_ CIB out to everyone */ + sync_from = crm_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) +finalize_sync_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - CRM_LOG_ASSERT(cib_not_master != rc); - clear_bit_inplace(fsa_input_register, R_CIB_ASKED); - if(rc != cib_ok) { - do_crm_log((rc==cib_old_data?LOG_WARNING:LOG_ERR), - "Sync from %s resulted in an error: %s", - (char*)user_data, cib_error2string(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_inplace(fsa_input_register, R_HAVE_CIB); - clear_bit_inplace(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)); - } - - crm_free(user_data); + CRM_LOG_ASSERT(cib_not_master != rc); + clear_bit_inplace(fsa_input_register, R_CIB_ASKED); + if (rc != cib_ok) { + do_crm_log((rc == cib_old_data ? LOG_WARNING : LOG_ERR), + "Sync from %s resulted in an error: %s", + (char *)user_data, cib_error2string(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_inplace(fsa_input_register, R_HAVE_CIB); + clear_bit_inplace(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)); + } + + crm_free(user_data); } static void -join_update_complete_callback(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +join_update_complete_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - fsa_data_t *msg_data = NULL; - - if(rc == cib_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(LOG_DEBUG, "failed", msg); - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - } + fsa_data_t *msg_data = NULL; + + if (rc == cib_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(LOG_DEBUG, "failed", msg); + 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) + 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_debug_2("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, crm_strdup(join_from), crm_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); + 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_debug_2("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, crm_strdup(join_from), crm_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; - 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); - - join_node = crm_get_peer(0, join_to); - if(crm_is_member_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, - crm_strdup(join_to), crm_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; + const char *join_to = NULL; + const char *join_state = NULL; + xmlNode *acknak = 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); + + join_node = crm_get_peer(0, join_to); + if (crm_is_member_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, + crm_strdup(join_to), crm_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_info("%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 = crm_strdup("Integrated node"); - g_hash_table_foreach(integrated_nodes, ghash_print_node, msg); - crm_free(msg); - - msg = crm_strdup("Finalized node"); - g_hash_table_foreach(finalized_nodes, ghash_print_node, msg); - crm_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; + crm_debug("Invoked by %s in state: %s", source, fsa_state2string(cur_state)); + + if (saved_ccm_membership_id != crm_peer_seq) { + crm_info("%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 = crm_strdup("Integrated node"); + g_hash_table_foreach(integrated_nodes, ghash_print_node, msg); + crm_free(msg); + + msg = crm_strdup("Finalized node"); + g_hash_table_foreach(finalized_nodes, ghash_print_node, msg); + crm_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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { crm_info("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/lrm.c b/crmd/lrm.c index de9e7ebf3c..187db76785 100644 --- a/crmd/lrm.c +++ b/crmd/lrm.c @@ -1,2079 +1,2046 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define START_DELAY_THRESHOLD 5 * 60 * 1000 typedef struct resource_history_s { char *id; lrm_rsc_t rsc; lrm_op_t *last; lrm_op_t *failed; - GList *recurring_op_list; + GList *recurring_op_list; } rsc_history_t; -struct recurring_op_s -{ - char *rsc_id; - char *op_key; - int call_id; - int interval; - gboolean remove; - gboolean cancelled; +struct recurring_op_s { + char *rsc_id; + char *op_key; + int call_id; + int interval; + gboolean remove; + gboolean cancelled; }; -struct pending_deletion_op_s -{ - char *rsc; - ha_msg_input_t *input; +struct pending_deletion_op_s { + char *rsc; + ha_msg_input_t *input; }; -struct delete_event_s -{ - int rc; - const char *rsc; +struct delete_event_s { + int rc; + const char *rsc; }; GHashTable *resource_history = NULL; GHashTable *pending_ops = NULL; GHashTable *deletion_ops = NULL; GCHSource *lrm_source = NULL; int num_lrm_register_fails = 0; int max_lrm_register_fails = 30; gboolean populate_history_cache(void); -gboolean process_lrm_event(lrm_op_t *op); +gboolean process_lrm_event(lrm_op_t * op); gboolean is_rsc_active(const char *rsc_id); -gboolean build_active_RAs(xmlNode *rsc_list); +gboolean build_active_RAs(xmlNode * rsc_list); static gboolean stop_recurring_actions(gpointer key, gpointer value, gpointer user_data); static int delete_rsc_status(const char *rsc_id, int call_options, const char *user_name); -lrm_op_t *construct_op(xmlNode *rsc_op, const char *rsc_id, const char *operation); -void do_lrm_rsc_op(lrm_rsc_t *rsc, const char *operation, xmlNode *msg, xmlNode *request); +lrm_op_t *construct_op(xmlNode * rsc_op, const char *rsc_id, const char *operation); +void do_lrm_rsc_op(lrm_rsc_t * rsc, const char *operation, xmlNode * msg, xmlNode * request); void send_direct_ack(const char *to_host, const char *to_sys, - lrm_rsc_t *rsc, lrm_op_t* op, const char *rsc_id); + lrm_rsc_t * rsc, lrm_op_t * op, const char *rsc_id); -void lrm_connection_destroy(gpointer user_data) +void +lrm_connection_destroy(gpointer user_data) { - if(is_set(fsa_input_register, R_LRM_CONNECTED)) { - crm_crit("LRM Connection failed"); - register_fsa_input(C_FSA_INTERNAL, I_ERROR, NULL); - clear_bit_inplace(fsa_input_register, R_LRM_CONNECTED); - + if (is_set(fsa_input_register, R_LRM_CONNECTED)) { + crm_crit("LRM Connection failed"); + register_fsa_input(C_FSA_INTERNAL, I_ERROR, NULL); + clear_bit_inplace(fsa_input_register, R_LRM_CONNECTED); + } else { - crm_info("LRM Connection disconnected"); + crm_info("LRM Connection disconnected"); } - + lrm_source = NULL; } -static void free_deletion_op(gpointer value) +static void +free_deletion_op(gpointer value) { struct pending_deletion_op_s *op = value; + crm_free(op->rsc); delete_ha_msg_input(op->input); crm_free(op); } -static void free_recurring_op(gpointer value) +static void +free_recurring_op(gpointer value) { - struct recurring_op_s *op = (struct recurring_op_s*)value; + struct recurring_op_s *op = (struct recurring_op_s *)value; + crm_free(op->rsc_id); crm_free(op->op_key); crm_free(op); } -static char *make_stop_id(const char *rsc, int call_id) +static char * +make_stop_id(const char *rsc, int call_id) { char *op_id = NULL; + crm_malloc0(op_id, strlen(rsc) + 34); - if(op_id != NULL) { - snprintf(op_id, strlen(rsc) + 34, "%s:%d", rsc, call_id); + if (op_id != NULL) { + snprintf(op_id, strlen(rsc) + 34, "%s:%d", rsc, call_id); } return op_id; } -static void dup_attr(gpointer key, gpointer value, gpointer user_data) +static void +dup_attr(gpointer key, gpointer value, gpointer user_data) { g_hash_table_replace(user_data, crm_strdup(key), crm_strdup(value)); } -static void history_cache_destroy(gpointer data) +static void +history_cache_destroy(gpointer data) { rsc_history_t *entry = data; crm_free(entry->rsc.type); crm_free(entry->rsc.class); crm_free(entry->rsc.provider); - + free_lrm_op(entry->failed); free_lrm_op(entry->last); crm_free(entry->id); crm_free(entry); } -static void update_history_cache(lrm_rsc_t *rsc, lrm_op_t *op) +static void +update_history_cache(lrm_rsc_t * rsc, lrm_op_t * op) { int target_rc = 0; rsc_history_t *entry = NULL; #ifdef HAVE_LRM_OP_T_RSC_DELETED - if(op->rsc_deleted) { - crm_debug("Purged history for '%s' after %s", op->rsc_id, op->op_type); - delete_rsc_status(op->rsc_id, cib_quorum_override, NULL); - return; + if (op->rsc_deleted) { + crm_debug("Purged history for '%s' after %s", op->rsc_id, op->op_type); + delete_rsc_status(op->rsc_id, cib_quorum_override, NULL); + return; } #endif - if(safe_str_eq(op->op_type, RSC_NOTIFY)) { - return; + if (safe_str_eq(op->op_type, RSC_NOTIFY)) { + return; } - + crm_debug("Appending %s op to history for '%s'", op->op_type, op->rsc_id); entry = g_hash_table_lookup(resource_history, op->rsc_id); - if(entry == NULL && rsc) { - crm_malloc0(entry, sizeof(rsc_history_t)); - entry->id = crm_strdup(op->rsc_id); - g_hash_table_insert(resource_history, entry->id, entry); - - entry->rsc.id = entry->id; - entry->rsc.type = crm_strdup(rsc->type); - entry->rsc.class = crm_strdup(rsc->class); - if(rsc->provider) { - entry->rsc.provider = crm_strdup(rsc->provider); - } else { - entry->rsc.provider = NULL; - } - - } else if(entry == NULL) { - crm_info("Resource %s no longer exists, not updating cache", op->rsc_id); - return; + if (entry == NULL && rsc) { + crm_malloc0(entry, sizeof(rsc_history_t)); + entry->id = crm_strdup(op->rsc_id); + g_hash_table_insert(resource_history, entry->id, entry); + + entry->rsc.id = entry->id; + entry->rsc.type = crm_strdup(rsc->type); + entry->rsc.class = crm_strdup(rsc->class); + if (rsc->provider) { + entry->rsc.provider = crm_strdup(rsc->provider); + } else { + entry->rsc.provider = NULL; + } + + } else if (entry == NULL) { + crm_info("Resource %s no longer exists, not updating cache", op->rsc_id); + return; } target_rc = rsc_op_expected_rc(op); - if(op->op_status == LRM_OP_CANCELLED) { - crm_trace("Skipping %s_%s_%d rc=%d, status=%d", op->rsc_id, op->op_type, op->interval, op->rc, op->op_status); - - } else if(did_rsc_op_fail(op, target_rc)) { - /* We must store failed monitors here - * - otherwise the block below will cause them to be forgetten them when a stop happens - */ - if(entry->failed) { - free_lrm_op(entry->failed); - } - entry->failed = copy_lrm_op(op); - - } else if(op->interval == 0) { - if(entry->last) { - free_lrm_op(entry->last); - } - entry->last = copy_lrm_op(op); - } - - if(op->interval > 0) { - crm_trace("Adding recurring op: %s_%s_%d", op->rsc_id, op->op_type, op->interval); - entry->recurring_op_list = g_list_prepend(entry->recurring_op_list, copy_lrm_op(op)); - - } else if(entry->recurring_op_list && safe_str_eq(op->op_type, RSC_STATUS) == FALSE) { - GList *gIter = entry->recurring_op_list; - crm_trace("Dropping %d recurring ops because of: %s_%s_%d", - g_list_length(gIter), op->rsc_id, op->op_type, op->interval); - for(; gIter != NULL; gIter = gIter->next) { - free_lrm_op(gIter->data); - } - g_list_free(entry->recurring_op_list); - entry->recurring_op_list = NULL; + if (op->op_status == LRM_OP_CANCELLED) { + crm_trace("Skipping %s_%s_%d rc=%d, status=%d", op->rsc_id, op->op_type, op->interval, + op->rc, op->op_status); + + } else if (did_rsc_op_fail(op, target_rc)) { + /* We must store failed monitors here + * - otherwise the block below will cause them to be forgetten them when a stop happens + */ + if (entry->failed) { + free_lrm_op(entry->failed); + } + entry->failed = copy_lrm_op(op); + + } else if (op->interval == 0) { + if (entry->last) { + free_lrm_op(entry->last); + } + entry->last = copy_lrm_op(op); + } + + if (op->interval > 0) { + crm_trace("Adding recurring op: %s_%s_%d", op->rsc_id, op->op_type, op->interval); + entry->recurring_op_list = g_list_prepend(entry->recurring_op_list, copy_lrm_op(op)); + + } else if (entry->recurring_op_list && safe_str_eq(op->op_type, RSC_STATUS) == FALSE) { + GList *gIter = entry->recurring_op_list; + + crm_trace("Dropping %d recurring ops because of: %s_%s_%d", + g_list_length(gIter), op->rsc_id, op->op_type, op->interval); + for (; gIter != NULL; gIter = gIter->next) { + free_lrm_op(gIter->data); + } + g_list_free(entry->recurring_op_list); + entry->recurring_op_list = NULL; } } /* A_LRM_CONNECT */ void do_lrm_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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - if(fsa_lrm_conn == NULL) { - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - return; - } - - if(action & A_LRM_DISCONNECT) { - if(verify_stopped(cur_state, LOG_INFO) == FALSE) { - crmd_fsa_stall(NULL); - return; - } - - if(is_set(fsa_input_register, R_LRM_CONNECTED)) { - clear_bit_inplace(fsa_input_register, R_LRM_CONNECTED); - fsa_lrm_conn->lrm_ops->signoff(fsa_lrm_conn); - crm_info("Disconnected from the LRM"); - } - - /* TODO: Clean up the hashtable */ - } - - if(action & A_LRM_CONNECT) { - int ret = HA_OK; - - deletion_ops = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, free_deletion_op); - - pending_ops = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, free_recurring_op); - - resource_history = g_hash_table_new_full( - crm_str_hash, g_str_equal, - NULL, history_cache_destroy); - - if(ret == HA_OK) { - crm_debug("Connecting to the LRM"); - ret = fsa_lrm_conn->lrm_ops->signon(fsa_lrm_conn, CRM_SYSTEM_CRMD); - } - - if(ret != HA_OK) { - if(++num_lrm_register_fails < max_lrm_register_fails) { - crm_warn("Failed to sign on to the LRM %d" - " (%d max) times", - num_lrm_register_fails, - max_lrm_register_fails); - - crm_timer_start(wait_timer); - crmd_fsa_stall(NULL); - return; - } - } - - if(ret == HA_OK) { - crm_debug_4("LRM: set_lrm_callback..."); - ret = fsa_lrm_conn->lrm_ops->set_lrm_callback(fsa_lrm_conn, lrm_op_callback); - if(ret != HA_OK) { - crm_err("Failed to set LRM callbacks"); - } - } - - if(ret != HA_OK) { - crm_err("Failed to sign on to the LRM %d" - " (max) times", num_lrm_register_fails); - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); - return; - } - - populate_history_cache(); - - /* TODO: create a destroy handler that causes - * some recovery to happen - */ - lrm_source = G_main_add_IPC_Channel( - G_PRIORITY_LOW, - fsa_lrm_conn->lrm_ops->ipcchan(fsa_lrm_conn), - FALSE, lrm_dispatch, fsa_lrm_conn, - lrm_connection_destroy); - - set_bit_inplace(fsa_input_register, R_LRM_CONNECTED); - crm_debug("LRM connection established"); - } - - if(action & ~(A_LRM_CONNECT|A_LRM_DISCONNECT)) { - crm_err("Unexpected action %s in %s", - fsa_action2string(action), __FUNCTION__); + if (fsa_lrm_conn == NULL) { + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + return; + } + + if (action & A_LRM_DISCONNECT) { + if (verify_stopped(cur_state, LOG_INFO) == FALSE) { + crmd_fsa_stall(NULL); + return; + } + + if (is_set(fsa_input_register, R_LRM_CONNECTED)) { + clear_bit_inplace(fsa_input_register, R_LRM_CONNECTED); + fsa_lrm_conn->lrm_ops->signoff(fsa_lrm_conn); + crm_info("Disconnected from the LRM"); + } + + /* TODO: Clean up the hashtable */ + } + + if (action & A_LRM_CONNECT) { + int ret = HA_OK; + + deletion_ops = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, free_deletion_op); + + pending_ops = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, free_recurring_op); + + resource_history = g_hash_table_new_full(crm_str_hash, g_str_equal, + NULL, history_cache_destroy); + + if (ret == HA_OK) { + crm_debug("Connecting to the LRM"); + ret = fsa_lrm_conn->lrm_ops->signon(fsa_lrm_conn, CRM_SYSTEM_CRMD); + } + + if (ret != HA_OK) { + if (++num_lrm_register_fails < max_lrm_register_fails) { + crm_warn("Failed to sign on to the LRM %d" + " (%d max) times", num_lrm_register_fails, max_lrm_register_fails); + + crm_timer_start(wait_timer); + crmd_fsa_stall(NULL); + return; + } + } + + if (ret == HA_OK) { + crm_debug_4("LRM: set_lrm_callback..."); + ret = fsa_lrm_conn->lrm_ops->set_lrm_callback(fsa_lrm_conn, lrm_op_callback); + if (ret != HA_OK) { + crm_err("Failed to set LRM callbacks"); + } + } + + if (ret != HA_OK) { + crm_err("Failed to sign on to the LRM %d" " (max) times", num_lrm_register_fails); + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + return; + } + + populate_history_cache(); + + /* TODO: create a destroy handler that causes + * some recovery to happen + */ + lrm_source = G_main_add_IPC_Channel(G_PRIORITY_LOW, + fsa_lrm_conn->lrm_ops->ipcchan(fsa_lrm_conn), + FALSE, lrm_dispatch, fsa_lrm_conn, + lrm_connection_destroy); + + set_bit_inplace(fsa_input_register, R_LRM_CONNECTED); + crm_debug("LRM connection established"); + } + + if (action & ~(A_LRM_CONNECT | A_LRM_DISCONNECT)) { + crm_err("Unexpected action %s in %s", fsa_action2string(action), __FUNCTION__); } } static void -ghash_print_pending(gpointer key, gpointer value, gpointer user_data) +ghash_print_pending(gpointer key, gpointer value, gpointer user_data) { const char *stop_id = key; int *log_level = user_data; struct recurring_op_s *pending = value; + do_crm_log(*log_level, "Pending action: %s (%s)", stop_id, pending->op_key); } static void -ghash_print_pending_for_rsc(gpointer key, gpointer value, gpointer user_data) +ghash_print_pending_for_rsc(gpointer key, gpointer value, gpointer user_data) { const char *stop_id = key; char *rsc = user_data; struct recurring_op_s *pending = value; - if(safe_str_eq(rsc, pending->rsc_id)) { - do_crm_log(LOG_NOTICE, "%sction %s (%s) incomplete at shutdown", - pending->interval==0?"A":"Recurring a", stop_id, pending->op_key); + + if (safe_str_eq(rsc, pending->rsc_id)) { + do_crm_log(LOG_NOTICE, "%sction %s (%s) incomplete at shutdown", + pending->interval == 0 ? "A" : "Recurring a", stop_id, pending->op_key); } } static void -ghash_count_pending(gpointer key, gpointer value, gpointer user_data) +ghash_count_pending(gpointer key, gpointer value, gpointer user_data) { int *counter = user_data; struct recurring_op_s *pending = value; - if(pending->interval > 0) { - /* Ignore recurring actions in the shutdown calculations */ - return; + if (pending->interval > 0) { + /* Ignore recurring actions in the shutdown calculations */ + return; } (*counter)++; } gboolean verify_stopped(enum crmd_fsa_state cur_state, int log_level) { int counter = 0; gboolean rc = TRUE; GHashTableIter gIter; rsc_history_t *entry = NULL; - + crm_debug("Checking for active resources before exit"); - if(cur_state == S_TERMINATE) { - log_level = LOG_ERR; - } - - if(pending_ops) { - if(is_set(fsa_input_register, R_LRM_CONNECTED)) { - /* Only log/complain about non-recurring actions */ - g_hash_table_foreach_remove(pending_ops, stop_recurring_actions, NULL); - } - g_hash_table_foreach(pending_ops, ghash_count_pending, &counter); - } - - if(counter > 0) { - rc = FALSE; - do_crm_log(log_level, - "%d pending LRM operations at shutdown%s", - counter, cur_state == S_TERMINATE?"":"... waiting"); - - if(cur_state == S_TERMINATE || !is_set(fsa_input_register, R_SENT_RSC_STOP)) { - g_hash_table_foreach( - pending_ops, ghash_print_pending, &log_level); - } - goto bail; - } - - if(resource_history == NULL) { - goto bail; - } - + if (cur_state == S_TERMINATE) { + log_level = LOG_ERR; + } + + if (pending_ops) { + if (is_set(fsa_input_register, R_LRM_CONNECTED)) { + /* Only log/complain about non-recurring actions */ + g_hash_table_foreach_remove(pending_ops, stop_recurring_actions, NULL); + } + g_hash_table_foreach(pending_ops, ghash_count_pending, &counter); + } + + if (counter > 0) { + rc = FALSE; + do_crm_log(log_level, + "%d pending LRM operations at shutdown%s", + counter, cur_state == S_TERMINATE ? "" : "... waiting"); + + if (cur_state == S_TERMINATE || !is_set(fsa_input_register, R_SENT_RSC_STOP)) { + g_hash_table_foreach(pending_ops, ghash_print_pending, &log_level); + } + goto bail; + } + + if (resource_history == NULL) { + goto bail; + } + g_hash_table_iter_init(&gIter, resource_history); - while (g_hash_table_iter_next (&gIter, NULL, (void**)&entry)) { - if(is_rsc_active(entry->id) == FALSE) { - continue; - } - - crm_err("Resource %s was active at shutdown." - " You may ignore this error if it is unmanaged.", - entry->id); + while (g_hash_table_iter_next(&gIter, NULL, (void **)&entry)) { + if (is_rsc_active(entry->id) == FALSE) { + continue; + } + + crm_err("Resource %s was active at shutdown." + " You may ignore this error if it is unmanaged.", entry->id); - g_hash_table_foreach( - pending_ops, ghash_print_pending_for_rsc, entry->id); + g_hash_table_foreach(pending_ops, ghash_print_pending_for_rsc, entry->id); } bail: set_bit_inplace(fsa_input_register, R_SENT_RSC_STOP); - if(cur_state == S_TERMINATE) { - rc = TRUE; + if (cur_state == S_TERMINATE) { + rc = TRUE; } return rc; } static char * get_rsc_metadata(const char *type, const char *class, const char *provider) { char *metadata = NULL; + CRM_CHECK(type != NULL, return NULL); CRM_CHECK(class != NULL, return NULL); - if(provider == NULL) { - provider = "heartbeat"; + if (provider == NULL) { + provider = "heartbeat"; } crm_debug_2("Retreiving metadata for %s::%s:%s", type, class, provider); - metadata = fsa_lrm_conn->lrm_ops->get_rsc_type_metadata( - fsa_lrm_conn, class, type, provider); - - if(metadata) { - /* copy the metadata because the LRM likes using - * g_alloc instead of cl_malloc - */ - char *m_copy = crm_strdup(metadata); - g_free(metadata); - metadata = m_copy; - + metadata = fsa_lrm_conn->lrm_ops->get_rsc_type_metadata(fsa_lrm_conn, class, type, provider); + + if (metadata) { + /* copy the metadata because the LRM likes using + * g_alloc instead of cl_malloc + */ + char *m_copy = crm_strdup(metadata); + + g_free(metadata); + metadata = m_copy; + } else { - crm_warn("No metadata found for %s::%s:%s", type, class, provider); - } + crm_warn("No metadata found for %s::%s:%s", type, class, provider); + } return metadata; } -typedef struct reload_data_s -{ - char *key; - char *metadata; - time_t last_query; - gboolean can_reload; - GListPtr restart_list; +typedef struct reload_data_s { + char *key; + char *metadata; + time_t last_query; + gboolean can_reload; + GListPtr restart_list; } reload_data_t; - -static void g_hash_destroy_reload(gpointer data) +static void +g_hash_destroy_reload(gpointer data) { reload_data_t *reload = data; + crm_free(reload->key); crm_free(reload->metadata); slist_basic_destroy(reload->restart_list); crm_free(reload); } - GHashTable *reload_hash = NULL; static GListPtr -get_rsc_restart_list(lrm_rsc_t *rsc, lrm_op_t *op) +get_rsc_restart_list(lrm_rsc_t * rsc, lrm_op_t * op) { int len = 0; char *key = NULL; char *copy = NULL; const char *value = NULL; const char *provider = NULL; xmlNode *param = NULL; xmlNode *params = NULL; xmlNode *actions = NULL; xmlNode *metadata = NULL; time_t now = time(NULL); reload_data_t *reload = NULL; - - if(reload_hash == NULL) { - reload_hash = g_hash_table_new_full( - crm_str_hash, g_str_equal, NULL, g_hash_destroy_reload); + + if (reload_hash == NULL) { + reload_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_reload); } provider = rsc->provider; - if(provider == NULL) { - provider = "heartbeat"; + if (provider == NULL) { + provider = "heartbeat"; } - + len = strlen(rsc->type) + strlen(rsc->class) + strlen(provider) + 4; crm_malloc(key, len); snprintf(key, len, "%s::%s:%s", rsc->type, rsc->class, provider); - + reload = g_hash_table_lookup(reload_hash, key); - if(reload - && ((now - 9) > reload->last_query) - && safe_str_eq(op->op_type, RSC_START)) { - reload = NULL; /* re-query */ - } - - if(reload == NULL) { - xmlNode *action = NULL; - crm_malloc0(reload, sizeof(reload_data_t)); - g_hash_table_replace(reload_hash, key, reload); - - reload->last_query = now; - reload->key = key; key = NULL; - reload->metadata = get_rsc_metadata(rsc->type, rsc->class, provider); - - metadata = string2xml(reload->metadata); - if(metadata == NULL) { - crm_err("Metadata for %s::%s:%s is not valid XML", - rsc->provider, rsc->class, rsc->type); - goto cleanup; - } - - actions = find_xml_node(metadata, "actions", TRUE); - - for(action = __xml_first_child(actions); action != NULL; action = __xml_next(action)) { - if(crm_str_eq((const char *)action->name, "action", TRUE)) { - value = crm_element_value(action, "name"); - if(safe_str_eq("reload", value)) { - reload->can_reload = TRUE; - break; - } - } - } - - if(reload->can_reload == FALSE) { - goto cleanup; - } - - params = find_xml_node(metadata, "parameters", TRUE); - for(param = __xml_first_child(params); param != NULL; param = __xml_next(param)) { - if(crm_str_eq((const char *)param->name, "parameter", TRUE)) { - value = crm_element_value(param, "unique"); - if(crm_is_true(value)) { - value = crm_element_value(param, "name"); - if(value == NULL) { - crm_err("%s: NULL param", key); - continue; - } - crm_debug("Attr %s is not reloadable", value); - copy = crm_strdup(value); - CRM_CHECK(copy != NULL, continue); - reload->restart_list = g_list_append(reload->restart_list, copy); - } - } - } - } - + if (reload && ((now - 9) > reload->last_query) + && safe_str_eq(op->op_type, RSC_START)) { + reload = NULL; /* re-query */ + } + + if (reload == NULL) { + xmlNode *action = NULL; + + crm_malloc0(reload, sizeof(reload_data_t)); + g_hash_table_replace(reload_hash, key, reload); + + reload->last_query = now; + reload->key = key; + key = NULL; + reload->metadata = get_rsc_metadata(rsc->type, rsc->class, provider); + + metadata = string2xml(reload->metadata); + if (metadata == NULL) { + crm_err("Metadata for %s::%s:%s is not valid XML", + rsc->provider, rsc->class, rsc->type); + goto cleanup; + } + + actions = find_xml_node(metadata, "actions", TRUE); + + for (action = __xml_first_child(actions); action != NULL; action = __xml_next(action)) { + if (crm_str_eq((const char *)action->name, "action", TRUE)) { + value = crm_element_value(action, "name"); + if (safe_str_eq("reload", value)) { + reload->can_reload = TRUE; + break; + } + } + } + + if (reload->can_reload == FALSE) { + goto cleanup; + } + + params = find_xml_node(metadata, "parameters", TRUE); + for (param = __xml_first_child(params); param != NULL; param = __xml_next(param)) { + if (crm_str_eq((const char *)param->name, "parameter", TRUE)) { + value = crm_element_value(param, "unique"); + if (crm_is_true(value)) { + value = crm_element_value(param, "name"); + if (value == NULL) { + crm_err("%s: NULL param", key); + continue; + } + crm_debug("Attr %s is not reloadable", value); + copy = crm_strdup(value); + CRM_CHECK(copy != NULL, continue); + reload->restart_list = g_list_append(reload->restart_list, copy); + } + } + } + } + cleanup: crm_free(key); free_xml(metadata); - return reload?reload->restart_list:NULL; + return reload ? reload->restart_list : NULL; } static void -append_restart_list(lrm_rsc_t *rsc, lrm_op_t *op, xmlNode *update, const char *version) +append_restart_list(lrm_rsc_t * rsc, lrm_op_t * op, xmlNode * update, const char *version) { int len = 0; char *list = NULL; char *digest = NULL; const char *value = NULL; gboolean non_empty = FALSE; xmlNode *restart = NULL; GListPtr restart_list = NULL; GListPtr lpc = NULL; - if(op->interval > 0) { - /* monitors are not reloadable */ - return; + if (op->interval > 0) { + /* monitors are not reloadable */ + return; - } else if(op->params == NULL) { - crm_debug("%s has no parameters", ID(update)); - return; + } else if (op->params == NULL) { + crm_debug("%s has no parameters", ID(update)); + return; - } else if(rsc == NULL) { - return; + } else if (rsc == NULL) { + return; - } else if(crm_str_eq(CRMD_ACTION_START, op->op_type, TRUE) == FALSE) { - /* only starts are potentially reloadable */ - return; - - } else if(compare_version("1.0.8", version) > 0) { - /* Caller version does not support reloads */ - return; + } else if (crm_str_eq(CRMD_ACTION_START, op->op_type, TRUE) == FALSE) { + /* only starts are potentially reloadable */ + return; + + } else if (compare_version("1.0.8", version) > 0) { + /* Caller version does not support reloads */ + return; } restart_list = get_rsc_restart_list(rsc, op); - if(restart_list == NULL) { - /* Resource does not support reloads */ - return; + if (restart_list == NULL) { + /* Resource does not support reloads */ + return; } restart = create_xml_node(NULL, XML_TAG_PARAMS); - for(lpc = restart_list; lpc != NULL; lpc = lpc->next) { - const char *param = (const char*)lpc->data; - - int start = len; - CRM_CHECK(param != NULL, continue); - value = g_hash_table_lookup(op->params, param); - if(value != NULL) { - non_empty = TRUE; - crm_xml_add(restart, param, value); - } - len += strlen(param) + 2; - crm_realloc(list, len+1); - sprintf(list+start, " %s ", param); - } - + for (lpc = restart_list; lpc != NULL; lpc = lpc->next) { + const char *param = (const char *)lpc->data; + + int start = len; + + CRM_CHECK(param != NULL, continue); + value = g_hash_table_lookup(op->params, param); + if (value != NULL) { + non_empty = TRUE; + crm_xml_add(restart, param, value); + } + len += strlen(param) + 2; + crm_realloc(list, len + 1); + sprintf(list + start, " %s ", param); + } + digest = calculate_operation_digest(restart, version); crm_xml_add(update, XML_LRM_ATTR_OP_RESTART, list); crm_xml_add(update, XML_LRM_ATTR_RESTART_DIGEST, digest); #if 0 crm_debug("%s: %s, %s", rsc->id, digest, list); - if(non_empty) { - crm_log_xml_debug(restart, "restart digest source"); + if (non_empty) { + crm_log_xml_debug(restart, "restart digest source"); } #endif - + free_xml(restart); crm_free(digest); crm_free(list); } -static gboolean build_operation_update( - xmlNode *parent, lrm_rsc_t *rsc, lrm_op_t *op, const char *src) +static gboolean +build_operation_update(xmlNode * parent, lrm_rsc_t * rsc, lrm_op_t * op, const char *src) { int target_rc = 0; xmlNode *xml_op = NULL; const char *caller_version = CRM_FEATURE_SET; - - if(op == NULL) { - return FALSE; - - } else if(AM_I_DC) { - - } else if(fsa_our_dc_version != NULL) { - caller_version = fsa_our_dc_version; - } else if(op->params == NULL) { - caller_version = fsa_our_dc_version; + + if (op == NULL) { + return FALSE; + + } else if (AM_I_DC) { + + } else if (fsa_our_dc_version != NULL) { + caller_version = fsa_our_dc_version; + } else if (op->params == NULL) { + caller_version = fsa_our_dc_version; } else { - /* there is a small risk in formerly mixed clusters that - * it will be sub-optimal. - * however with our upgrade policy, the update we send - * should still be completely supported anyway - */ - caller_version = g_hash_table_lookup( - op->params, XML_ATTR_CRM_VERSION); - crm_warn("Falling back to operation originator version: %s", - caller_version); + /* there is a small risk in formerly mixed clusters that + * it will be sub-optimal. + * however with our upgrade policy, the update we send + * should still be completely supported anyway + */ + caller_version = g_hash_table_lookup(op->params, XML_ATTR_CRM_VERSION); + crm_warn("Falling back to operation originator version: %s", caller_version); } target_rc = rsc_op_expected_rc(op); xml_op = create_operation_update(parent, op, caller_version, target_rc, src, LOG_DEBUG); - if(xml_op) { - append_restart_list(rsc, op, xml_op, caller_version); + if (xml_op) { + append_restart_list(rsc, op, xml_op, caller_version); } return TRUE; } gboolean -is_rsc_active(const char *rsc_id) +is_rsc_active(const char *rsc_id) { rsc_history_t *entry = NULL; - + crm_debug_3("Processing lrm_rsc_t entry %s", rsc_id); - + entry = g_hash_table_lookup(resource_history, rsc_id); - if(entry == NULL || entry->last == NULL) { - return FALSE; - } - - if(entry->last->rc == EXECRA_OK - && safe_str_eq(entry->last->op_type, CRMD_ACTION_STOP)) { - return FALSE; - - } else if(entry->last->rc == EXECRA_OK - && safe_str_eq(entry->last->op_type, CRMD_ACTION_MIGRATE)) { - /* a stricter check is too complex... - * leave that to the PE - */ - return FALSE; - - } else if(entry->last->rc == EXECRA_NOT_RUNNING) { - return FALSE; + if (entry == NULL || entry->last == NULL) { + return FALSE; + } + + if (entry->last->rc == EXECRA_OK && safe_str_eq(entry->last->op_type, CRMD_ACTION_STOP)) { + return FALSE; + + } else if (entry->last->rc == EXECRA_OK + && safe_str_eq(entry->last->op_type, CRMD_ACTION_MIGRATE)) { + /* a stricter check is too complex... + * leave that to the PE + */ + return FALSE; + + } else if (entry->last->rc == EXECRA_NOT_RUNNING) { + return FALSE; } return TRUE; } gboolean -build_active_RAs(xmlNode *rsc_list) +build_active_RAs(xmlNode * rsc_list) { GHashTableIter iter; rsc_history_t *entry = NULL; g_hash_table_iter_init(&iter, resource_history); - while (g_hash_table_iter_next (&iter, NULL, (void**)&entry)) { + while (g_hash_table_iter_next(&iter, NULL, (void **)&entry)) { - GList *gIter = NULL; - xmlNode *xml_rsc = create_xml_node(rsc_list, XML_LRM_TAG_RESOURCE); + GList *gIter = NULL; + xmlNode *xml_rsc = create_xml_node(rsc_list, XML_LRM_TAG_RESOURCE); - crm_xml_add(xml_rsc, XML_ATTR_ID, entry->id); - crm_xml_add(xml_rsc, XML_ATTR_TYPE, entry->rsc.type); - crm_xml_add(xml_rsc, XML_AGENT_ATTR_CLASS, entry->rsc.class); - crm_xml_add(xml_rsc, XML_AGENT_ATTR_PROVIDER, entry->rsc.provider); + crm_xml_add(xml_rsc, XML_ATTR_ID, entry->id); + crm_xml_add(xml_rsc, XML_ATTR_TYPE, entry->rsc.type); + crm_xml_add(xml_rsc, XML_AGENT_ATTR_CLASS, entry->rsc.class); + crm_xml_add(xml_rsc, XML_AGENT_ATTR_PROVIDER, entry->rsc.provider); - build_operation_update(xml_rsc, &(entry->rsc), entry->last, __FUNCTION__); - build_operation_update(xml_rsc, &(entry->rsc), entry->failed, __FUNCTION__); - for(gIter = entry->recurring_op_list; gIter != NULL; gIter = gIter->next) { - build_operation_update(xml_rsc, &(entry->rsc), gIter->data, __FUNCTION__); - } + build_operation_update(xml_rsc, &(entry->rsc), entry->last, __FUNCTION__); + build_operation_update(xml_rsc, &(entry->rsc), entry->failed, __FUNCTION__); + for (gIter = entry->recurring_op_list; gIter != NULL; gIter = gIter->next) { + build_operation_update(xml_rsc, &(entry->rsc), gIter->data, __FUNCTION__); + } } - return FALSE; + return FALSE; } -gboolean populate_history_cache(void) +gboolean +populate_history_cache(void) { - GListPtr gIter = NULL; + GListPtr gIter = NULL; GListPtr gIter2 = NULL; - GList *op_list = NULL; + GList *op_list = NULL; GList *rsc_list = NULL; state_flag_t cur_state = 0; - + rsc_list = fsa_lrm_conn->lrm_ops->get_all_rscs(fsa_lrm_conn); - for(gIter = rsc_list; gIter != NULL; gIter = gIter->next) { - char *rid = (char*)gIter->data; - - int max_call_id = -1; - lrm_rsc_t *rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); - - if(rsc == NULL) { - crm_err("NULL resource returned from the LRM: %s", rid); - continue; - } - - op_list = rsc->ops->get_cur_state(rsc, &cur_state); - for(gIter2 = op_list; gIter2 != NULL; gIter2 = gIter2->next) { - lrm_op_t *op = (lrm_op_t*)gIter2->data; - - if(max_call_id < op->call_id) { - update_history_cache(rsc, op); - - } else if(max_call_id > op->call_id) { - crm_err("Bad call_id in list=%d. Previous call_id=%d", - op->call_id, max_call_id); - - } else { - crm_warn("lrm->get_cur_state() returned" - " duplicate entries for call_id=%d", - op->call_id); - } - - max_call_id = op->call_id; - lrm_free_op(op); - } - - g_list_free(op_list); - lrm_free_rsc(rsc); - free(rid); + for (gIter = rsc_list; gIter != NULL; gIter = gIter->next) { + char *rid = (char *)gIter->data; + + int max_call_id = -1; + lrm_rsc_t *rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); + + if (rsc == NULL) { + crm_err("NULL resource returned from the LRM: %s", rid); + continue; + } + + op_list = rsc->ops->get_cur_state(rsc, &cur_state); + for (gIter2 = op_list; gIter2 != NULL; gIter2 = gIter2->next) { + lrm_op_t *op = (lrm_op_t *) gIter2->data; + + if (max_call_id < op->call_id) { + update_history_cache(rsc, op); + + } else if (max_call_id > op->call_id) { + crm_err("Bad call_id in list=%d. Previous call_id=%d", op->call_id, max_call_id); + + } else { + crm_warn("lrm->get_cur_state() returned" + " duplicate entries for call_id=%d", op->call_id); + } + + max_call_id = op->call_id; + lrm_free_op(op); + } + + g_list_free(op_list); + lrm_free_rsc(rsc); + free(rid); } g_list_free(rsc_list); return TRUE; } -xmlNode* +xmlNode * do_lrm_query(gboolean is_replace) { gboolean shut_down = FALSE; - xmlNode *xml_result= NULL; + xmlNode *xml_result = NULL; xmlNode *xml_state = NULL; - xmlNode *xml_data = NULL; - xmlNode *rsc_list = NULL; + xmlNode *xml_data = NULL; + xmlNode *rsc_list = NULL; const char *exp_state = CRMD_STATE_ACTIVE; - if(is_set(fsa_input_register, R_SHUTDOWN)) { - exp_state = CRMD_STATE_INACTIVE; - shut_down = TRUE; + if (is_set(fsa_input_register, R_SHUTDOWN)) { + exp_state = CRMD_STATE_INACTIVE; + shut_down = TRUE; } - - xml_state = create_node_state( - fsa_our_uname, ACTIVESTATUS, XML_BOOLEAN_TRUE, - ONLINESTATUS, CRMD_JOINSTATE_MEMBER, exp_state, - !shut_down, __FUNCTION__); - xml_data = create_xml_node(xml_state, XML_CIB_TAG_LRM); + xml_state = create_node_state(fsa_our_uname, ACTIVESTATUS, XML_BOOLEAN_TRUE, + ONLINESTATUS, CRMD_JOINSTATE_MEMBER, exp_state, + !shut_down, __FUNCTION__); + + xml_data = create_xml_node(xml_state, XML_CIB_TAG_LRM); crm_xml_add(xml_data, XML_ATTR_ID, fsa_our_uuid); - rsc_list = create_xml_node(xml_data, XML_LRM_TAG_RESOURCES); + rsc_list = create_xml_node(xml_data, XML_LRM_TAG_RESOURCES); /* Build a list of active (not always running) resources */ build_active_RAs(rsc_list); xml_result = create_cib_fragment(xml_state, XML_CIB_TAG_STATUS); crm_log_xml_debug_3(xml_state, "Current state of the LRM"); - free_xml(xml_state); - + free_xml(xml_state); + return xml_result; } - -static void notify_deleted(ha_msg_input_t *input, const char *rsc_id, int rc) +static void +notify_deleted(ha_msg_input_t * input, const char *rsc_id, int rc) { - lrm_op_t* op = NULL; - const char *from_sys = crm_element_value(input->msg, F_CRM_SYS_FROM); + lrm_op_t *op = NULL; + const char *from_sys = crm_element_value(input->msg, F_CRM_SYS_FROM); const char *from_host = crm_element_value(input->msg, F_CRM_HOST_FROM); crm_info("Notifying %s on %s that %s was%s deleted", - from_sys, from_host, rsc_id, rc==HA_OK?"":" not"); + from_sys, from_host, rsc_id, rc == HA_OK ? "" : " not"); op = construct_op(input->xml, rsc_id, CRMD_ACTION_DELETE); CRM_ASSERT(op != NULL); - if(rc == HA_OK) { - op->op_status = LRM_OP_DONE; - op->rc = EXECRA_OK; + if (rc == HA_OK) { + op->op_status = LRM_OP_DONE; + op->rc = EXECRA_OK; } else { - op->op_status = LRM_OP_ERROR; - op->rc = EXECRA_UNKNOWN_ERROR; + op->op_status = LRM_OP_ERROR; + op->rc = EXECRA_UNKNOWN_ERROR; } - + send_direct_ack(from_host, from_sys, NULL, op, rsc_id); free_lrm_op(op); - - if(safe_str_neq(from_sys, CRM_SYSTEM_TENGINE)) { - /* this isn't expected - trigger a new transition */ - time_t now = time(NULL); - char *now_s = crm_itoa(now); - - crm_debug("Triggering a refresh after %s deleted %s from the LRM", - from_sys, rsc_id); - - update_attr(fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG, - NULL, NULL, NULL, NULL, "last-lrm-refresh", now_s, FALSE); - crm_free(now_s); + + if (safe_str_neq(from_sys, CRM_SYSTEM_TENGINE)) { + /* this isn't expected - trigger a new transition */ + time_t now = time(NULL); + char *now_s = crm_itoa(now); + + crm_debug("Triggering a refresh after %s deleted %s from the LRM", from_sys, rsc_id); + + update_attr(fsa_cib_conn, cib_none, XML_CIB_TAG_CRMCONFIG, + NULL, NULL, NULL, NULL, "last-lrm-refresh", now_s, FALSE); + crm_free(now_s); } } -static gboolean lrm_remove_deleted_rsc( - gpointer key, gpointer value, gpointer user_data) +static gboolean +lrm_remove_deleted_rsc(gpointer key, gpointer value, gpointer user_data) { struct delete_event_s *event = user_data; struct pending_deletion_op_s *op = value; - if(safe_str_eq(event->rsc, op->rsc)) { - notify_deleted(op->input, event->rsc, event->rc); - return TRUE; + if (safe_str_eq(event->rsc, op->rsc)) { + notify_deleted(op->input, event->rsc, event->rc); + return TRUE; } return FALSE; } -static gboolean lrm_remove_deleted_op( - gpointer key, gpointer value, gpointer user_data) +static gboolean +lrm_remove_deleted_op(gpointer key, gpointer value, gpointer user_data) { const char *rsc = user_data; struct recurring_op_s *pending = value; - if(safe_str_eq(rsc, pending->rsc_id)) { - crm_info("Removing op %s:%d for deleted resource %s", - pending->op_key, pending->call_id, rsc); - return TRUE; + + if (safe_str_eq(rsc, pending->rsc_id)) { + crm_info("Removing op %s:%d for deleted resource %s", + pending->op_key, pending->call_id, rsc); + return TRUE; } return FALSE; } /* * Remove the rsc from the CIB * * Avoids refreshing the entire LRM section of this host */ #define rsc_template "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']" static int -delete_rsc_status(const char *rsc_id, int call_options, const char *user_name) +delete_rsc_status(const char *rsc_id, int call_options, const char *user_name) { char *rsc_xpath = NULL; int max = 0; int rc = cib_ok; CRM_CHECK(rsc_id != NULL, return cib_id_check); max = strlen(rsc_template) + strlen(rsc_id) + strlen(fsa_our_uname) + 1; crm_malloc0(rsc_xpath, max); snprintf(rsc_xpath, max, rsc_template, fsa_our_uname, rsc_id); - - rc = fsa_cib_conn->cmds->delegated_variant_op( - fsa_cib_conn, CIB_OP_DELETE, NULL, rsc_xpath, NULL, NULL, call_options|cib_xpath, user_name); + + rc = fsa_cib_conn->cmds->delegated_variant_op(fsa_cib_conn, CIB_OP_DELETE, NULL, rsc_xpath, + NULL, NULL, call_options | cib_xpath, user_name); crm_free(rsc_xpath); return rc; } static void -delete_rsc_entry(ha_msg_input_t *input, const char *rsc_id, int rc, const char *user_name) +delete_rsc_entry(ha_msg_input_t * input, const char *rsc_id, int rc, const char *user_name) { struct delete_event_s event; - + CRM_CHECK(rsc_id != NULL, return); - - if(rc == HA_OK) { - char *rsc_id_copy = crm_strdup(rsc_id); - - g_hash_table_remove(resource_history, rsc_id); - crm_debug("sync: Sending delete op for %s", rsc_id); - delete_rsc_status(rsc_id, cib_quorum_override, user_name); - g_hash_table_foreach_remove(pending_ops, lrm_remove_deleted_op, rsc_id_copy); - - crm_free(rsc_id_copy); - } + if (rc == HA_OK) { + char *rsc_id_copy = crm_strdup(rsc_id); + + g_hash_table_remove(resource_history, rsc_id); + crm_debug("sync: Sending delete op for %s", rsc_id); + delete_rsc_status(rsc_id, cib_quorum_override, user_name); + + g_hash_table_foreach_remove(pending_ops, lrm_remove_deleted_op, rsc_id_copy); - if(input) { - notify_deleted(input, rsc_id, rc); + crm_free(rsc_id_copy); + } + + if (input) { + notify_deleted(input, rsc_id, rc); } event.rc = rc; event.rsc = rsc_id; - g_hash_table_foreach_remove(deletion_ops, lrm_remove_deleted_rsc, &event); + g_hash_table_foreach_remove(deletion_ops, lrm_remove_deleted_rsc, &event); } /* * Remove the op from the CIB * * Avoids refreshing the entire LRM section of this host */ #define op_template "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']/"XML_LRM_TAG_RSC_OP"[@id='%s']" #define op_call_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']" static void -delete_op_entry(lrm_op_t *op, const char *rsc_id, const char *key, int call_id) +delete_op_entry(lrm_op_t * op, const char *rsc_id, const char *key, int call_id) { xmlNode *xml_top = NULL; - if(op != NULL) { - xml_top = create_xml_node(NULL, XML_LRM_TAG_RSC_OP); - crm_xml_add_int(xml_top, XML_LRM_ATTR_CALLID, op->call_id); - crm_xml_add(xml_top, XML_ATTR_TRANSITION_KEY, op->user_data); - - crm_debug("async: Sending delete op for %s_%s_%d (call=%d)", - op->rsc_id, op->op_type, op->interval, op->call_id); - fsa_cib_conn->cmds->delete( - fsa_cib_conn, XML_CIB_TAG_STATUS, xml_top, cib_quorum_override); + if (op != NULL) { + xml_top = create_xml_node(NULL, XML_LRM_TAG_RSC_OP); + crm_xml_add_int(xml_top, XML_LRM_ATTR_CALLID, op->call_id); + crm_xml_add(xml_top, XML_ATTR_TRANSITION_KEY, op->user_data); + + crm_debug("async: Sending delete op for %s_%s_%d (call=%d)", + op->rsc_id, op->op_type, op->interval, op->call_id); + + fsa_cib_conn->cmds->delete(fsa_cib_conn, XML_CIB_TAG_STATUS, xml_top, cib_quorum_override); } else if (rsc_id != NULL && key != NULL) { - int max = 0; - char *op_xpath = NULL; - if(call_id > 0) { - max = strlen(op_call_template) + strlen(rsc_id) + strlen(fsa_our_uname) + strlen(key) + 10; - crm_malloc0(op_xpath, max); - snprintf(op_xpath, max, op_call_template, fsa_our_uname, rsc_id, key, call_id); - - } else { - max = strlen(op_template) + strlen(rsc_id) + strlen(fsa_our_uname) + strlen(key) + 1; - crm_malloc0(op_xpath, max); - snprintf(op_xpath, max, op_template, fsa_our_uname, rsc_id, key); - } - - crm_debug("sync: Sending delete op for %s (call=%d)", rsc_id, call_id); - fsa_cib_conn->cmds->delete( - fsa_cib_conn, op_xpath, NULL, cib_quorum_override|cib_xpath); - - crm_free(op_xpath); - + int max = 0; + char *op_xpath = NULL; + + if (call_id > 0) { + max = + strlen(op_call_template) + strlen(rsc_id) + strlen(fsa_our_uname) + strlen(key) + + 10; + crm_malloc0(op_xpath, max); + snprintf(op_xpath, max, op_call_template, fsa_our_uname, rsc_id, key, call_id); + + } else { + max = strlen(op_template) + strlen(rsc_id) + strlen(fsa_our_uname) + strlen(key) + 1; + crm_malloc0(op_xpath, max); + snprintf(op_xpath, max, op_template, fsa_our_uname, rsc_id, key); + } + + crm_debug("sync: Sending delete op for %s (call=%d)", rsc_id, call_id); + fsa_cib_conn->cmds->delete(fsa_cib_conn, op_xpath, NULL, cib_quorum_override | cib_xpath); + + crm_free(op_xpath); + } else { - crm_err("Not enough information to delete op entry: rsc=%p key=%p", rsc_id, key); - return; + crm_err("Not enough information to delete op entry: rsc=%p key=%p", rsc_id, key); + return; } crm_log_xml_debug_2(xml_top, "op:cancel"); free_xml(xml_top); } static gboolean -cancel_op(lrm_rsc_t *rsc, const char *key, int op, gboolean remove) +cancel_op(lrm_rsc_t * rsc, const char *key, int op, gboolean remove) { int rc = HA_OK; struct recurring_op_s *pending = NULL; CRM_CHECK(op != 0, return FALSE); CRM_CHECK(rsc != NULL, return FALSE); - if(key == NULL) { - key = make_stop_id(rsc->id, op); + if (key == NULL) { + key = make_stop_id(rsc->id, op); } pending = g_hash_table_lookup(pending_ops, key); - if(pending) { - if(remove && pending->remove == FALSE) { - pending->remove = TRUE; - crm_debug("Scheduling %s for removal", key); - } - - if(pending->cancelled) { - crm_debug("Operation %s already cancelled", key); - return TRUE; - } + if (pending) { + if (remove && pending->remove == FALSE) { + pending->remove = TRUE; + crm_debug("Scheduling %s for removal", key); + } + + if (pending->cancelled) { + crm_debug("Operation %s already cancelled", key); + return TRUE; + } - pending->cancelled = TRUE; + pending->cancelled = TRUE; } else { - crm_info("No pending op found for %s", key); + crm_info("No pending op found for %s", key); } crm_debug("Cancelling op %d for %s (%s)", op, rsc->id, key); rc = rsc->ops->cancel_op(rsc, op); - if(rc == HA_OK) { - crm_debug("Op %d for %s (%s): cancelled", op, rsc->id, key); + if (rc == HA_OK) { + crm_debug("Op %d for %s (%s): cancelled", op, rsc->id, key); #ifdef HAVE_LRM_OP_T_RSC_DELETED - } else if(rc == HA_RSCBUSY) { - crm_debug("Op %d for %s (%s): cancelation pending", op, rsc->id, key); + } else if (rc == HA_RSCBUSY) { + crm_debug("Op %d for %s (%s): cancelation pending", op, rsc->id, key); #endif } else { - crm_debug("Op %d for %s (%s): Nothing to cancel", op, rsc->id, key); - /* The caller needs to make sure the entry is - * removed from the pending_ops list - * - * Usually by returning TRUE inside the worker function - * supplied to g_hash_table_foreach_remove() - * - * Not removing the entry from pending_ops will block - * the node from shutting down - */ - return FALSE; - } - + crm_debug("Op %d for %s (%s): Nothing to cancel", op, rsc->id, key); + /* The caller needs to make sure the entry is + * removed from the pending_ops list + * + * Usually by returning TRUE inside the worker function + * supplied to g_hash_table_foreach_remove() + * + * Not removing the entry from pending_ops will block + * the node from shutting down + */ + return FALSE; + } + return TRUE; } -struct cancel_data -{ - gboolean done; - gboolean remove; - const char *key; - lrm_rsc_t *rsc; +struct cancel_data { + gboolean done; + gboolean remove; + const char *key; + lrm_rsc_t *rsc; }; static gboolean cancel_action_by_key(gpointer key, gpointer value, gpointer user_data) { struct cancel_data *data = user_data; - struct recurring_op_s *op = (struct recurring_op_s*)value; - - if(safe_str_eq(op->op_key, data->key)) { - data->done = TRUE; - if (cancel_op(data->rsc, key, op->call_id, data->remove) == FALSE) { - return TRUE; - } + struct recurring_op_s *op = (struct recurring_op_s *)value; + + if (safe_str_eq(op->op_key, data->key)) { + data->done = TRUE; + if (cancel_op(data->rsc, key, op->call_id, data->remove) == FALSE) { + return TRUE; + } } return FALSE; } static gboolean -cancel_op_key(lrm_rsc_t *rsc, const char *key, gboolean remove) +cancel_op_key(lrm_rsc_t * rsc, const char *key, gboolean remove) { struct cancel_data data; CRM_CHECK(rsc != NULL, return FALSE); CRM_CHECK(key != NULL, return FALSE); data.key = key; data.rsc = rsc; data.done = FALSE; data.remove = remove; - + g_hash_table_foreach_remove(pending_ops, cancel_action_by_key, &data); return data.done; } static lrm_rsc_t * -get_lrm_resource(xmlNode *resource, xmlNode *op_msg, gboolean do_create) +get_lrm_resource(xmlNode * resource, xmlNode * op_msg, gboolean do_create) { char rid[RID_LEN]; lrm_rsc_t *rsc = NULL; const char *short_id = ID(resource); const char *long_id = crm_element_value(resource, XML_ATTR_ID_LONG); - + crm_debug_2("Retrieving %s from the LRM.", short_id); CRM_CHECK(short_id != NULL, return NULL); - - if(rsc == NULL) { - /* check if its already there (short name) */ - strncpy(rid, short_id, RID_LEN); - rid[RID_LEN-1] = 0; - rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); - } - if(rsc == NULL && long_id != NULL) { - /* try the long name instead */ - strncpy(rid, long_id, RID_LEN); - rid[RID_LEN-1] = 0; - rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); - } - - if(rsc == NULL && do_create) { - /* add it to the LRM */ - const char *type = crm_element_value(resource, XML_ATTR_TYPE); - const char *class = crm_element_value(resource, XML_AGENT_ATTR_CLASS); - const char *provider = crm_element_value(resource, XML_AGENT_ATTR_PROVIDER); - GHashTable *params = xml2list(op_msg); - - CRM_CHECK(class != NULL, return NULL); - CRM_CHECK(type != NULL, return NULL); - - crm_debug_2("Adding rsc %s before operation", short_id); - strncpy(rid, short_id, RID_LEN); - rid[RID_LEN-1] = 0; - - if(g_hash_table_size(params) == 0) { - crm_log_xml_warn(op_msg, "EmptyParams"); - } - - if(params != NULL) { - g_hash_table_remove(params, CRM_META"_op_target_rc"); - } - - fsa_lrm_conn->lrm_ops->add_rsc( - fsa_lrm_conn, rid, class, type, provider, params); - - rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); - g_hash_table_destroy(params); - - if(rsc == NULL) { - fsa_data_t *msg_data = NULL; - crm_err("Could not add resource %s to LRM", rid); - register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); - } + + if (rsc == NULL) { + /* check if its already there (short name) */ + strncpy(rid, short_id, RID_LEN); + rid[RID_LEN - 1] = 0; + rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); + } + if (rsc == NULL && long_id != NULL) { + /* try the long name instead */ + strncpy(rid, long_id, RID_LEN); + rid[RID_LEN - 1] = 0; + rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); + } + + if (rsc == NULL && do_create) { + /* add it to the LRM */ + const char *type = crm_element_value(resource, XML_ATTR_TYPE); + const char *class = crm_element_value(resource, XML_AGENT_ATTR_CLASS); + const char *provider = crm_element_value(resource, XML_AGENT_ATTR_PROVIDER); + GHashTable *params = xml2list(op_msg); + + CRM_CHECK(class != NULL, return NULL); + CRM_CHECK(type != NULL, return NULL); + + crm_debug_2("Adding rsc %s before operation", short_id); + strncpy(rid, short_id, RID_LEN); + rid[RID_LEN - 1] = 0; + + if (g_hash_table_size(params) == 0) { + crm_log_xml_warn(op_msg, "EmptyParams"); + } + + if (params != NULL) { + g_hash_table_remove(params, CRM_META "_op_target_rc"); + } + + fsa_lrm_conn->lrm_ops->add_rsc(fsa_lrm_conn, rid, class, type, provider, params); + + rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid); + g_hash_table_destroy(params); + + if (rsc == NULL) { + fsa_data_t *msg_data = NULL; + + crm_err("Could not add resource %s to LRM", rid); + register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); + } } return rsc; } -static void delete_resource( - const char *id, lrm_rsc_t *rsc, - const char *sys, const char *host, const char *user, ha_msg_input_t *request) +static void +delete_resource(const char *id, lrm_rsc_t * rsc, + const char *sys, const char *host, const char *user, ha_msg_input_t * request) { int rc = HA_OK; - crm_info("Removing resource %s for %s (%s) on %s", - id, sys, user?user:"internal", host); - - if(rsc) { - rc = fsa_lrm_conn->lrm_ops->delete_rsc(fsa_lrm_conn, id); + crm_info("Removing resource %s for %s (%s) on %s", id, sys, user ? user : "internal", host); + + if (rsc) { + rc = fsa_lrm_conn->lrm_ops->delete_rsc(fsa_lrm_conn, id); } - - if(rc == HA_OK) { - crm_trace("Resource '%s' deleted", id); - + + if (rc == HA_OK) { + crm_trace("Resource '%s' deleted", id); + #ifdef HAVE_LRM_OP_T_RSC_DELETED - } else if(rc == HA_RSCBUSY) { - crm_info("Deletion of resource '%s' pending", id); - if(request) { - struct pending_deletion_op_s *op = NULL; - char *ref = crm_element_value_copy(request->msg, XML_ATTR_REFERENCE); - - crm_malloc0(op, sizeof(struct pending_deletion_op_s)); - op->rsc = crm_strdup(rsc->id); - op->input = copy_ha_msg_input(request); - g_hash_table_insert(deletion_ops, ref, op); - } - return; - + } else if (rc == HA_RSCBUSY) { + crm_info("Deletion of resource '%s' pending", id); + if (request) { + struct pending_deletion_op_s *op = NULL; + char *ref = crm_element_value_copy(request->msg, XML_ATTR_REFERENCE); + + crm_malloc0(op, sizeof(struct pending_deletion_op_s)); + op->rsc = crm_strdup(rsc->id); + op->input = copy_ha_msg_input(request); + g_hash_table_insert(deletion_ops, ref, op); + } + return; + #endif } else { - crm_warn("Deletion of resource '%s' for %s (%s) on %s failed: %d", - id, sys, user?user:"internal", host, rc); + crm_warn("Deletion of resource '%s' for %s (%s) on %s failed: %d", + id, sys, user ? user : "internal", host, rc); } delete_rsc_entry(request, id, rc, user); } - /* A_LRM_INVOKE */ void do_lrm_invoke(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { gboolean done = FALSE; gboolean create_rsc = TRUE; const char *crm_op = NULL; const char *from_sys = NULL; const char *from_host = NULL; const char *operation = NULL; ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg); const char *user_name = NULL; #if ENABLE_ACL user_name = crm_element_value(input->msg, F_CRM_USER); crm_debug_2("LRM command from user '%s'", user_name); #endif - crm_op = crm_element_value(input->msg, F_CRM_TASK); - from_sys = crm_element_value(input->msg, F_CRM_SYS_FROM); - if(safe_str_neq(from_sys, CRM_SYSTEM_TENGINE)) { - from_host = crm_element_value(input->msg, F_CRM_HOST_FROM); + crm_op = crm_element_value(input->msg, F_CRM_TASK); + from_sys = crm_element_value(input->msg, F_CRM_SYS_FROM); + if (safe_str_neq(from_sys, CRM_SYSTEM_TENGINE)) { + from_host = crm_element_value(input->msg, F_CRM_HOST_FROM); } - + crm_debug_2("LRM command from: %s", from_sys); - - if(safe_str_eq(crm_op, CRM_OP_LRM_DELETE)) { - operation = CRMD_ACTION_DELETE; - } else if(safe_str_eq(operation, CRM_OP_LRM_REFRESH)) { - crm_op = CRM_OP_LRM_REFRESH; + if (safe_str_eq(crm_op, CRM_OP_LRM_DELETE)) { + operation = CRMD_ACTION_DELETE; - } else if(safe_str_eq(crm_op, CRM_OP_LRM_FAIL)) { + } else if (safe_str_eq(operation, CRM_OP_LRM_REFRESH)) { + crm_op = CRM_OP_LRM_REFRESH; + + } else if (safe_str_eq(crm_op, CRM_OP_LRM_FAIL)) { #if HAVE_STRUCT_LRM_OPS_FAIL_RSC - int rc = HA_OK; - lrm_op_t* op = NULL; + int rc = HA_OK; + lrm_op_t *op = NULL; + + lrm_rsc_t *rsc = NULL; + xmlNode *xml_rsc = find_xml_node(input->xml, XML_CIB_TAG_RESOURCE, TRUE); + + CRM_CHECK(xml_rsc != NULL, return); + + op = construct_op(input->xml, ID(xml_rsc), "fail"); + op->op_status = LRM_OP_ERROR; + op->rc = EXECRA_UNKNOWN_ERROR; + CRM_ASSERT(op != NULL); + +# if ENABLE_ACL + if (user_name && is_privileged(user_name) == FALSE) { + crm_err("%s does not have permission to fail %s", user_name, ID(xml_rsc)); + send_direct_ack(from_host, from_sys, NULL, op, ID(xml_rsc)); + free_lrm_op(op); + return; + } +# endif + + rsc = get_lrm_resource(xml_rsc, input->xml, create_rsc); + if (rsc) { + crm_info("Failing resource %s...", rsc->id); + + rc = fsa_lrm_conn->lrm_ops->fail_rsc(fsa_lrm_conn, rsc->id, 1, + "do_lrm_invoke: Async failure"); + if (rc != HA_OK) { + crm_err("Could not initiate an asynchronous failure for %s (%d)", rsc->id, rc); + } else { + op->op_status = LRM_OP_DONE; + op->rc = EXECRA_OK; + } + + lrm_free_rsc(rsc); + + } else { + crm_info("Cannot find/create resource in order to fail it..."); + crm_log_xml_warn(input->msg, "bad input"); + } + + send_direct_ack(from_host, from_sys, NULL, op, ID(xml_rsc)); + free_lrm_op(op); + return; +#else + crm_info("Failing resource..."); + operation = "fail"; +#endif - lrm_rsc_t *rsc = NULL; - xmlNode *xml_rsc = find_xml_node( - input->xml, XML_CIB_TAG_RESOURCE, TRUE); + } else if (input->xml != NULL) { + operation = crm_element_value(input->xml, XML_LRM_ATTR_TASK); + } - CRM_CHECK(xml_rsc != NULL, return); + if (safe_str_eq(crm_op, CRM_OP_LRM_REFRESH)) { + enum cib_errors rc = cib_ok; + xmlNode *fragment = do_lrm_query(TRUE); - op = construct_op(input->xml, ID(xml_rsc), "fail"); - op->op_status = LRM_OP_ERROR; - op->rc = EXECRA_UNKNOWN_ERROR; - CRM_ASSERT(op != NULL); + crm_info("Forcing a local LRM refresh"); -#if ENABLE_ACL - if(user_name && is_privileged(user_name) == FALSE) { - crm_err("%s does not have permission to fail %s", user_name, ID(xml_rsc)); - send_direct_ack(from_host, from_sys, NULL, op, ID(xml_rsc)); - free_lrm_op(op); - return; - } -#endif - - rsc = get_lrm_resource(xml_rsc, input->xml, create_rsc); - if(rsc) { - crm_info("Failing resource %s...", rsc->id); - - rc = fsa_lrm_conn->lrm_ops->fail_rsc(fsa_lrm_conn, rsc->id, 1, "do_lrm_invoke: Async failure"); - if(rc != HA_OK) { - crm_err("Could not initiate an asynchronous failure for %s (%d)", rsc->id, rc); - } else { - op->op_status = LRM_OP_DONE; - op->rc = EXECRA_OK; - } - - lrm_free_rsc(rsc); - - } else { - crm_info("Cannot find/create resource in order to fail it..."); - crm_log_xml_warn(input->msg, "bad input"); - } - - send_direct_ack(from_host, from_sys, NULL, op, ID(xml_rsc)); - free_lrm_op(op); - return; -#else - crm_info("Failing resource..."); - operation = "fail"; -#endif + fsa_cib_update(XML_CIB_TAG_STATUS, fragment, cib_quorum_override, rc, user_name); + free_xml(fragment); + + } else if (safe_str_eq(crm_op, CRM_OP_LRM_QUERY)) { + xmlNode *data = do_lrm_query(FALSE); + xmlNode *reply = create_reply(input->msg, data); + + if (relay_message(reply, TRUE) == FALSE) { + crm_err("Unable to route reply"); + crm_log_xml(LOG_ERR, "reply", reply); + } + free_xml(reply); + free_xml(data); + + } else if (safe_str_eq(operation, CRM_OP_PROBED)) { + update_attrd(NULL, CRM_OP_PROBED, XML_BOOLEAN_TRUE, user_name); + + } else if (safe_str_eq(crm_op, CRM_OP_REPROBE)) { + GHashTableIter gIter; + rsc_history_t *entry = NULL; + + crm_notice("Forcing the status of all resources to be redetected"); + + g_hash_table_iter_init(&gIter, resource_history); + while (g_hash_table_iter_next(&gIter, NULL, (void **)&entry)) { + lrm_rsc_t *rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, entry->id); + + delete_resource(entry->id, rsc, from_sys, from_host, user_name, NULL); + lrm_free_rsc(rsc); + } + + /* Now delete the copy in the CIB */ + erase_status_tag(fsa_our_uname, XML_CIB_TAG_LRM, cib_scope_local); + + /* And finally, _delete_ the value in attrd + * Setting it to FALSE results in the PE sending us back here again + */ + update_attrd(NULL, CRM_OP_PROBED, NULL, user_name); + + } else if (operation != NULL) { + lrm_rsc_t *rsc = NULL; + xmlNode *params = NULL; + xmlNode *xml_rsc = find_xml_node(input->xml, XML_CIB_TAG_RESOURCE, TRUE); + + CRM_CHECK(xml_rsc != NULL, return); + + /* only the first 16 chars are used by the LRM */ + params = find_xml_node(input->xml, XML_TAG_ATTRS, TRUE); + + if (safe_str_eq(operation, CRMD_ACTION_DELETE)) { + create_rsc = FALSE; + } + + rsc = get_lrm_resource(xml_rsc, input->xml, create_rsc); + + if (rsc == NULL && create_rsc) { + crm_err("Invalid resource definition"); + crm_log_xml_warn(input->msg, "bad input"); + + } else if (rsc == NULL) { + lrm_op_t *op = NULL; + + crm_notice("Not creating resource for a %s event: %s", operation, ID(input->xml)); + delete_rsc_entry(input, ID(xml_rsc), HA_OK, user_name); + + op = construct_op(input->xml, ID(xml_rsc), operation); + op->op_status = LRM_OP_DONE; + op->rc = EXECRA_OK; + CRM_ASSERT(op != NULL); + send_direct_ack(from_host, from_sys, NULL, op, ID(xml_rsc)); + free_lrm_op(op); + + } else if (safe_str_eq(operation, CRMD_ACTION_CANCEL)) { + lrm_op_t *op = NULL; + char *op_key = NULL; + char *meta_key = NULL; + int call = 0; + const char *call_id = NULL; + const char *op_task = NULL; + const char *op_interval = NULL; + + CRM_CHECK(params != NULL, crm_log_xml_warn(input->xml, "Bad command"); + return); + + meta_key = crm_meta_name(XML_LRM_ATTR_INTERVAL); + op_interval = crm_element_value(params, meta_key); + crm_free(meta_key); + + meta_key = crm_meta_name(XML_LRM_ATTR_TASK); + op_task = crm_element_value(params, meta_key); + crm_free(meta_key); + + meta_key = crm_meta_name(XML_LRM_ATTR_CALLID); + call_id = crm_element_value(params, meta_key); + crm_free(meta_key); + + CRM_CHECK(op_task != NULL, crm_log_xml_warn(input->xml, "Bad command"); + return); + CRM_CHECK(op_interval != NULL, crm_log_xml_warn(input->xml, "Bad command"); + return); + + op = construct_op(input->xml, rsc->id, op_task); + CRM_ASSERT(op != NULL); + op_key = generate_op_key(rsc->id, op_task, crm_parse_int(op_interval, "0")); + + crm_debug("PE requested op %s (call=%s) be cancelled", + op_key, call_id ? call_id : "NA"); + call = crm_parse_int(call_id, "0"); + if (call == 0) { + /* the normal case when the PE cancels a recurring op */ + done = cancel_op_key(rsc, op_key, TRUE); + + } else { + /* the normal case when the PE cancels an orphan op */ + done = cancel_op(rsc, NULL, call, TRUE); + } + + if (done == FALSE) { + crm_debug("Nothing known about operation %d for %s", call, op_key); + delete_op_entry(NULL, rsc->id, op_key, call); - } else if(input->xml != NULL) { - operation = crm_element_value(input->xml, XML_LRM_ATTR_TASK); - } - - if(safe_str_eq(crm_op, CRM_OP_LRM_REFRESH)) { - enum cib_errors rc = cib_ok; - xmlNode *fragment = do_lrm_query(TRUE); - crm_info("Forcing a local LRM refresh"); - - fsa_cib_update(XML_CIB_TAG_STATUS, fragment, - cib_quorum_override, rc, user_name); - free_xml(fragment); - - } else if(safe_str_eq(crm_op, CRM_OP_LRM_QUERY)) { - xmlNode *data = do_lrm_query(FALSE); - xmlNode *reply = create_reply(input->msg, data); - - if(relay_message(reply, TRUE) == FALSE) { - crm_err("Unable to route reply"); - crm_log_xml(LOG_ERR, "reply", reply); - } - free_xml(reply); - free_xml(data); - - } else if(safe_str_eq(operation, CRM_OP_PROBED)) { - update_attrd(NULL, CRM_OP_PROBED, XML_BOOLEAN_TRUE, user_name); - - } else if(safe_str_eq(crm_op, CRM_OP_REPROBE)) { - GHashTableIter gIter; - rsc_history_t *entry = NULL; - crm_notice("Forcing the status of all resources to be redetected"); - - g_hash_table_iter_init(&gIter, resource_history); - while (g_hash_table_iter_next (&gIter, NULL, (void**)&entry)) { - lrm_rsc_t *rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, entry->id); - delete_resource(entry->id, rsc, from_sys, from_host, user_name, NULL); - lrm_free_rsc(rsc); - } - - /* Now delete the copy in the CIB */ - erase_status_tag(fsa_our_uname, XML_CIB_TAG_LRM, cib_scope_local); - - /* And finally, _delete_ the value in attrd - * Setting it to FALSE results in the PE sending us back here again - */ - update_attrd(NULL, CRM_OP_PROBED, NULL, user_name); - - } else if(operation != NULL) { - lrm_rsc_t *rsc = NULL; - xmlNode *params = NULL; - xmlNode *xml_rsc = find_xml_node( - input->xml, XML_CIB_TAG_RESOURCE, TRUE); - - CRM_CHECK(xml_rsc != NULL, return); - - /* only the first 16 chars are used by the LRM */ - params = find_xml_node(input->xml, XML_TAG_ATTRS, TRUE); - - if(safe_str_eq(operation, CRMD_ACTION_DELETE)) { - create_rsc = FALSE; - } - - rsc = get_lrm_resource(xml_rsc, input->xml, create_rsc); - - if(rsc == NULL && create_rsc) { - crm_err("Invalid resource definition"); - crm_log_xml_warn(input->msg, "bad input"); - - } else if(rsc == NULL) { - lrm_op_t* op = NULL; - crm_notice("Not creating resource for a %s event: %s", - operation, ID(input->xml)); - delete_rsc_entry(input, ID(xml_rsc), HA_OK, user_name); - - op = construct_op(input->xml, ID(xml_rsc), operation); - op->op_status = LRM_OP_DONE; - op->rc = EXECRA_OK; - CRM_ASSERT(op != NULL); - send_direct_ack(from_host, from_sys, NULL, op, ID(xml_rsc)); - free_lrm_op(op); - - } else if(safe_str_eq(operation, CRMD_ACTION_CANCEL)) { - lrm_op_t* op = NULL; - char *op_key = NULL; - char *meta_key = NULL; - int call = 0; - const char *call_id = NULL; - const char *op_task = NULL; - const char *op_interval = NULL; - - CRM_CHECK(params != NULL, - crm_log_xml_warn(input->xml, "Bad command"); - return); - - - meta_key = crm_meta_name(XML_LRM_ATTR_INTERVAL); - op_interval = crm_element_value(params, meta_key); - crm_free(meta_key); - - meta_key = crm_meta_name(XML_LRM_ATTR_TASK); - op_task = crm_element_value(params, meta_key); - crm_free(meta_key); - - meta_key = crm_meta_name(XML_LRM_ATTR_CALLID); - call_id = crm_element_value(params, meta_key); - crm_free(meta_key); - - CRM_CHECK(op_task != NULL, - crm_log_xml_warn(input->xml, "Bad command"); - return); - CRM_CHECK(op_interval != NULL, - crm_log_xml_warn(input->xml, "Bad command"); - return); - - op = construct_op(input->xml, rsc->id, op_task); - CRM_ASSERT(op != NULL); - op_key = generate_op_key( - rsc->id,op_task,crm_parse_int(op_interval,"0")); - - crm_debug("PE requested op %s (call=%s) be cancelled", - op_key, call_id?call_id:"NA"); - call = crm_parse_int(call_id, "0"); - if(call == 0) { - /* the normal case when the PE cancels a recurring op */ - done = cancel_op_key(rsc, op_key, TRUE); - - } else { - /* the normal case when the PE cancels an orphan op */ - done = cancel_op(rsc, NULL, call, TRUE); - } - - if(done == FALSE) { - crm_debug("Nothing known about operation %d for %s", call, op_key); - delete_op_entry(NULL, rsc->id, op_key, call); - - /* needed?? surely not otherwise the cancel_op_(_key) wouldn't - * have failed in the first place - */ - g_hash_table_remove(pending_ops, op_key); - } - - op->rc = EXECRA_OK; - op->op_status = LRM_OP_DONE; - send_direct_ack(from_host, from_sys, rsc, op, rsc->id); - - crm_free(op_key); - free_lrm_op(op); - - } else if(safe_str_eq(operation, CRMD_ACTION_DELETE)) { - int cib_rc = cib_ok; - - CRM_ASSERT(rsc != NULL); - - cib_rc = delete_rsc_status(rsc->id, cib_dryrun|cib_sync_call, user_name); - if(cib_rc != cib_ok){ - lrm_op_t* op = NULL; - - crm_err("Attempt of deleting resource status '%s' from CIB for %s (user=%s) on %s failed: (rc=%d) %s", - rsc->id, from_sys, user_name?user_name:"unknown", from_host, cib_rc, cib_error2string(cib_rc)); - - op = construct_op(input->xml, rsc->id, operation); - op->op_status = LRM_OP_ERROR; - - if (cib_rc == cib_permission_denied) { - op->rc = EXECRA_INSUFFICIENT_PRIV; - } else { - op->rc = EXECRA_UNKNOWN_ERROR; - } - send_direct_ack(from_host, from_sys, NULL, op, rsc->id); - free_lrm_op(op); - return; - } - - delete_resource(rsc->id, rsc, from_sys, from_host, user_name, input); - - } else if(rsc != NULL) { - do_lrm_rsc_op(rsc, operation, input->xml, input->msg); - } - - lrm_free_rsc(rsc); + /* needed?? surely not otherwise the cancel_op_(_key) wouldn't + * have failed in the first place + */ + g_hash_table_remove(pending_ops, op_key); + } + + op->rc = EXECRA_OK; + op->op_status = LRM_OP_DONE; + send_direct_ack(from_host, from_sys, rsc, op, rsc->id); + + crm_free(op_key); + free_lrm_op(op); + + } else if (safe_str_eq(operation, CRMD_ACTION_DELETE)) { + int cib_rc = cib_ok; + + CRM_ASSERT(rsc != NULL); + + cib_rc = delete_rsc_status(rsc->id, cib_dryrun | cib_sync_call, user_name); + if (cib_rc != cib_ok) { + lrm_op_t *op = NULL; + + crm_err + ("Attempt of deleting resource status '%s' from CIB for %s (user=%s) on %s failed: (rc=%d) %s", + rsc->id, from_sys, user_name ? user_name : "unknown", from_host, cib_rc, + cib_error2string(cib_rc)); + + op = construct_op(input->xml, rsc->id, operation); + op->op_status = LRM_OP_ERROR; + + if (cib_rc == cib_permission_denied) { + op->rc = EXECRA_INSUFFICIENT_PRIV; + } else { + op->rc = EXECRA_UNKNOWN_ERROR; + } + send_direct_ack(from_host, from_sys, NULL, op, rsc->id); + free_lrm_op(op); + return; + } + + delete_resource(rsc->id, rsc, from_sys, from_host, user_name, input); + + } else if (rsc != NULL) { + do_lrm_rsc_op(rsc, operation, input->xml, input->msg); + } + + lrm_free_rsc(rsc); } else { - crm_err("Operation was neither a lrm_query, nor a rsc op. %s", - crm_str(crm_op)); - register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); + crm_err("Operation was neither a lrm_query, nor a rsc op. %s", crm_str(crm_op)); + register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL); } } - -static void copy_notify_keys(gpointer key, gpointer value, gpointer user_data) +static void +copy_notify_keys(gpointer key, gpointer value, gpointer user_data) { - if(strstr(key, CRM_META"_notify_") != NULL) { - g_hash_table_insert(user_data, strdup((const char *)key), strdup((const char *)value)); + if (strstr(key, CRM_META "_notify_") != NULL) { + g_hash_table_insert(user_data, strdup((const char *)key), strdup((const char *)value)); } } - lrm_op_t * -construct_op(xmlNode *rsc_op, const char *rsc_id, const char *operation) +construct_op(xmlNode * rsc_op, const char *rsc_id, const char *operation) { lrm_op_t *op = NULL; const char *op_delay = NULL; const char *op_timeout = NULL; const char *op_interval = NULL; GHashTable *params = NULL; - + const char *transition = NULL; + CRM_LOG_ASSERT(rsc_id != NULL); crm_malloc0(op, sizeof(lrm_op_t)); - op->op_type = crm_strdup(operation); + op->op_type = crm_strdup(operation); op->op_status = LRM_OP_PENDING; op->rc = -1; op->rsc_id = crm_strdup(rsc_id); op->interval = 0; - op->timeout = 0; + op->timeout = 0; op->start_delay = 0; op->copyparams = 0; op->app_name = crm_strdup(CRM_SYSTEM_CRMD); - if(rsc_op == NULL) { - CRM_LOG_ASSERT(safe_str_eq(CRMD_ACTION_STOP, operation)); - op->user_data = NULL; - op->user_data_len = 0; - /* the stop_all_resources() case - * by definition there is no DC (or they'd be shutting - * us down). - * So we should put our version here. - */ - op->params = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); - - g_hash_table_insert(op->params, - crm_strdup(XML_ATTR_CRM_VERSION), - crm_strdup(CRM_FEATURE_SET)); - - crm_debug_2("Constructed %s op for %s", operation, rsc_id); - return op; + if (rsc_op == NULL) { + CRM_LOG_ASSERT(safe_str_eq(CRMD_ACTION_STOP, operation)); + op->user_data = NULL; + op->user_data_len = 0; + /* the stop_all_resources() case + * by definition there is no DC (or they'd be shutting + * us down). + * So we should put our version here. + */ + op->params = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, g_hash_destroy_str); + + g_hash_table_insert(op->params, + crm_strdup(XML_ATTR_CRM_VERSION), crm_strdup(CRM_FEATURE_SET)); + + crm_debug_2("Constructed %s op for %s", operation, rsc_id); + return op; } params = xml2list(rsc_op); - g_hash_table_remove(params, CRM_META"_op_target_rc"); + g_hash_table_remove(params, CRM_META "_op_target_rc"); - op_delay = crm_meta_value(params, XML_OP_ATTR_START_DELAY); - op_timeout = crm_meta_value(params, XML_ATTR_TIMEOUT); + op_delay = crm_meta_value(params, XML_OP_ATTR_START_DELAY); + op_timeout = crm_meta_value(params, XML_ATTR_TIMEOUT); op_interval = crm_meta_value(params, XML_LRM_ATTR_INTERVAL); op->interval = crm_parse_int(op_interval, "0"); - op->timeout = crm_parse_int(op_timeout, "0"); + op->timeout = crm_parse_int(op_timeout, "0"); op->start_delay = crm_parse_int(op_delay, "0"); - if(safe_str_neq(operation, RSC_STOP)) { - op->params = params; + if (safe_str_neq(operation, RSC_STOP)) { + op->params = params; } else { - /* Create a blank parameter list so that we stop the resource - * with the old attributes, not the new ones - */ - const char *version = g_hash_table_lookup(params, XML_ATTR_CRM_VERSION); + /* Create a blank parameter list so that we stop the resource + * with the old attributes, not the new ones + */ + const char *version = g_hash_table_lookup(params, XML_ATTR_CRM_VERSION); - op->params = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); + op->params = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, g_hash_destroy_str); - if(version) { - g_hash_table_insert(op->params, - crm_strdup(XML_ATTR_CRM_VERSION), - crm_strdup(version)); - } + if (version) { + g_hash_table_insert(op->params, crm_strdup(XML_ATTR_CRM_VERSION), crm_strdup(version)); + } - g_hash_table_foreach(params, copy_notify_keys, op->params); - g_hash_table_destroy(params); params = NULL; + g_hash_table_foreach(params, copy_notify_keys, op->params); + g_hash_table_destroy(params); + params = NULL; } - + /* sanity */ - if(op->interval < 0) { - op->interval = 0; + if (op->interval < 0) { + op->interval = 0; } - if(op->timeout <= 0) { - op->timeout = op->interval; + if (op->timeout <= 0) { + op->timeout = op->interval; } - if(op->start_delay < 0) { - op->start_delay = 0; + if (op->start_delay < 0) { + op->start_delay = 0; } transition = crm_element_value(rsc_op, XML_ATTR_TRANSITION_KEY); CRM_CHECK(transition != NULL, return op); - + op->user_data = crm_strdup(transition); - op->user_data_len = 1+strlen(op->user_data); + op->user_data_len = 1 + strlen(op->user_data); - if(op->interval != 0) { - if(safe_str_eq(operation, CRMD_ACTION_START) - || safe_str_eq(operation, CRMD_ACTION_STOP)) { - crm_err("Start and Stop actions cannot have an interval: %d", op->interval); - op->interval = 0; - } + if (op->interval != 0) { + if (safe_str_eq(operation, CRMD_ACTION_START) + || safe_str_eq(operation, CRMD_ACTION_STOP)) { + crm_err("Start and Stop actions cannot have an interval: %d", op->interval); + op->interval = 0; + } } /* reset the resource's parameters? */ - if(op->interval == 0) { - if(safe_str_eq(CRMD_ACTION_START, operation) - || safe_str_eq(CRMD_ACTION_STATUS, operation)) { - op->copyparams = 1; - } - } - - crm_debug_2("Constructed %s op for %s: interval=%d", - operation, rsc_id, op->interval); - + if (op->interval == 0) { + if (safe_str_eq(CRMD_ACTION_START, operation) + || safe_str_eq(CRMD_ACTION_STATUS, operation)) { + op->copyparams = 1; + } + } + + crm_debug_2("Constructed %s op for %s: interval=%d", operation, rsc_id, op->interval); + return op; } void send_direct_ack(const char *to_host, const char *to_sys, - lrm_rsc_t *rsc, lrm_op_t* op, const char *rsc_id) + lrm_rsc_t * rsc, lrm_op_t * op, const char *rsc_id) { xmlNode *reply = NULL; xmlNode *update, *iter; xmlNode *fragment; - + CRM_CHECK(op != NULL, return); - if(op->rsc_id == NULL) { - CRM_LOG_ASSERT(rsc_id != NULL); - op->rsc_id = crm_strdup(rsc_id); + if (op->rsc_id == NULL) { + CRM_LOG_ASSERT(rsc_id != NULL); + op->rsc_id = crm_strdup(rsc_id); } - if(to_sys == NULL) { - to_sys = CRM_SYSTEM_TENGINE; + if (to_sys == NULL) { + to_sys = CRM_SYSTEM_TENGINE; } - update = create_node_state( - fsa_our_uname, NULL, NULL, NULL, NULL, NULL, FALSE, __FUNCTION__); + update = create_node_state(fsa_our_uname, NULL, NULL, NULL, NULL, NULL, FALSE, __FUNCTION__); iter = create_xml_node(update, XML_CIB_TAG_LRM); crm_xml_add(iter, XML_ATTR_ID, fsa_our_uuid); - iter = create_xml_node(iter, XML_LRM_TAG_RESOURCES); - iter = create_xml_node(iter, XML_LRM_TAG_RESOURCE); + iter = create_xml_node(iter, XML_LRM_TAG_RESOURCES); + iter = create_xml_node(iter, XML_LRM_TAG_RESOURCE); crm_xml_add(iter, XML_ATTR_ID, op->rsc_id); build_operation_update(iter, rsc, op, __FUNCTION__); fragment = create_cib_fragment(update, XML_CIB_TAG_STATUS); - reply = create_request(CRM_OP_INVOKE_LRM, fragment, to_host, - to_sys, CRM_SYSTEM_LRMD, NULL); + reply = create_request(CRM_OP_INVOKE_LRM, fragment, to_host, to_sys, CRM_SYSTEM_LRMD, NULL); crm_log_xml_debug_2(update, "ACK Update"); crm_info("ACK'ing resource op %s_%s_%d from %s: %s", - op->rsc_id, op->op_type, op->interval, op->user_data, - crm_element_value(reply, XML_ATTR_REFERENCE)); + op->rsc_id, op->op_type, op->interval, op->user_data, + crm_element_value(reply, XML_ATTR_REFERENCE)); - if(relay_message(reply, TRUE) == FALSE) { - crm_log_xml(LOG_ERR, "Unable to route reply", reply); + if (relay_message(reply, TRUE) == FALSE) { + crm_log_xml(LOG_ERR, "Unable to route reply", reply); } free_xml(fragment); free_xml(update); free_xml(reply); } static gboolean stop_recurring_action_by_rsc(gpointer key, gpointer value, gpointer user_data) { lrm_rsc_t *rsc = user_data; - struct recurring_op_s *op = (struct recurring_op_s*)value; - - if(op->interval != 0 && safe_str_eq(op->rsc_id, rsc->id)) { - if (cancel_op(rsc, key, op->call_id, FALSE) == FALSE) { - return TRUE; - } + struct recurring_op_s *op = (struct recurring_op_s *)value; + + if (op->interval != 0 && safe_str_eq(op->rsc_id, rsc->id)) { + if (cancel_op(rsc, key, op->call_id, FALSE) == FALSE) { + return TRUE; + } } return FALSE; } static gboolean stop_recurring_actions(gpointer key, gpointer value, gpointer user_data) { gboolean remove = FALSE; - struct recurring_op_s *op = (struct recurring_op_s*)value; - - if(op->interval != 0) { - lrm_rsc_t *rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, op->rsc_id); - if(rsc) { - remove = cancel_op(rsc, key, op->call_id, FALSE); - lrm_free_rsc(rsc); - } + struct recurring_op_s *op = (struct recurring_op_s *)value; + + if (op->interval != 0) { + lrm_rsc_t *rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, op->rsc_id); + + if (rsc) { + remove = cancel_op(rsc, key, op->call_id, FALSE); + lrm_free_rsc(rsc); + } } return remove; } void -do_lrm_rsc_op(lrm_rsc_t *rsc, const char *operation, - xmlNode *msg, xmlNode *request) +do_lrm_rsc_op(lrm_rsc_t * rsc, const char *operation, xmlNode * msg, xmlNode * request) { - int call_id = 0; - char *op_id = NULL; - lrm_op_t* op = NULL; + int call_id = 0; + char *op_id = NULL; + lrm_op_t *op = NULL; fsa_data_t *msg_data = NULL; - const char *transition = NULL; + const char *transition = NULL; CRM_CHECK(rsc != NULL, return); - - if(msg != NULL) { - transition = crm_element_value(msg, XML_ATTR_TRANSITION_KEY); - if(transition == NULL) { - crm_log_xml_err(msg, "Missing transition number"); - } + + if (msg != NULL) { + transition = crm_element_value(msg, XML_ATTR_TRANSITION_KEY); + if (transition == NULL) { + crm_log_xml_err(msg, "Missing transition number"); + } } op = construct_op(msg, rsc->id, operation); /* stop the monitor before stopping the resource */ - if(crm_str_eq(operation, CRMD_ACTION_STOP, TRUE) - || crm_str_eq(operation, CRMD_ACTION_DEMOTE, TRUE) - || crm_str_eq(operation, CRMD_ACTION_PROMOTE, TRUE) - || crm_str_eq(operation, CRMD_ACTION_MIGRATE, TRUE)) { - g_hash_table_foreach_remove(pending_ops, stop_recurring_action_by_rsc, rsc); + if (crm_str_eq(operation, CRMD_ACTION_STOP, TRUE) + || crm_str_eq(operation, CRMD_ACTION_DEMOTE, TRUE) + || crm_str_eq(operation, CRMD_ACTION_PROMOTE, TRUE) + || crm_str_eq(operation, CRMD_ACTION_MIGRATE, TRUE)) { + g_hash_table_foreach_remove(pending_ops, stop_recurring_action_by_rsc, rsc); } - + /* now do the op */ - crm_info("Performing key=%s op=%s_%s_%d )", - transition, rsc->id, operation, op->interval); - - if(fsa_state != S_NOT_DC - && fsa_state != S_POLICY_ENGINE - && fsa_state != S_TRANSITION_ENGINE) { - if(safe_str_neq(operation, "fail") - && safe_str_neq(operation, CRMD_ACTION_STOP)) { - crm_info("Discarding attempt to perform action %s on %s" - " in state %s", operation, rsc->id, - fsa_state2string(fsa_state)); - op->rc = 99; - op->op_status = LRM_OP_ERROR; - send_direct_ack(NULL, NULL, rsc, op, rsc->id); - free_lrm_op(op); - crm_free(op_id); - return; - } + crm_info("Performing key=%s op=%s_%s_%d )", transition, rsc->id, operation, op->interval); + + if (fsa_state != S_NOT_DC && fsa_state != S_POLICY_ENGINE && fsa_state != S_TRANSITION_ENGINE) { + if (safe_str_neq(operation, "fail") + && safe_str_neq(operation, CRMD_ACTION_STOP)) { + crm_info("Discarding attempt to perform action %s on %s" + " in state %s", operation, rsc->id, fsa_state2string(fsa_state)); + op->rc = 99; + op->op_status = LRM_OP_ERROR; + send_direct_ack(NULL, NULL, rsc, op, rsc->id); + free_lrm_op(op); + crm_free(op_id); + return; + } } op_id = generate_op_key(rsc->id, op->op_type, op->interval); - if(op->interval > 0) { - /* cancel it so we can then restart it without conflict */ - cancel_op_key(rsc, op_id, FALSE); - op->target_rc = CHANGED; + if (op->interval > 0) { + /* cancel it so we can then restart it without conflict */ + cancel_op_key(rsc, op_id, FALSE); + op->target_rc = CHANGED; } else { - op->target_rc = EVERYTIME; + op->target_rc = EVERYTIME; } call_id = rsc->ops->perform_op(rsc, op); - if(call_id <= 0) { - crm_err("Operation %s on %s failed: %d", - operation, rsc->id, call_id); - register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); + if (call_id <= 0) { + crm_err("Operation %s on %s failed: %d", operation, rsc->id, call_id); + register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); } else { - /* record all operations so we can wait - * for them to complete during shutdown - */ - char *call_id_s = make_stop_id(rsc->id, call_id); - struct recurring_op_s *pending = NULL; - crm_malloc0(pending, sizeof(struct recurring_op_s)); - crm_debug_2("Recording pending op: %d - %s %s", call_id, op_id, call_id_s); - - pending->call_id = call_id; - pending->interval = op->interval; - pending->op_key = crm_strdup(op_id); - pending->rsc_id = crm_strdup(rsc->id); - g_hash_table_replace(pending_ops, call_id_s, pending); - - if(op->interval > 0 && op->start_delay > START_DELAY_THRESHOLD) { - char *uuid = NULL; - int dummy = 0, target_rc = 0; - crm_info("Faking confirmation of %s: execution postponed for over 5 minutes", op_id); - - decode_transition_key(op->user_data, &uuid, &dummy, &dummy, &target_rc); - crm_free(uuid); - - op->rc = target_rc; - op->op_status = LRM_OP_DONE; - send_direct_ack(NULL, NULL, rsc, op, rsc->id); - } + /* record all operations so we can wait + * for them to complete during shutdown + */ + char *call_id_s = make_stop_id(rsc->id, call_id); + struct recurring_op_s *pending = NULL; + + crm_malloc0(pending, sizeof(struct recurring_op_s)); + crm_debug_2("Recording pending op: %d - %s %s", call_id, op_id, call_id_s); + + pending->call_id = call_id; + pending->interval = op->interval; + pending->op_key = crm_strdup(op_id); + pending->rsc_id = crm_strdup(rsc->id); + g_hash_table_replace(pending_ops, call_id_s, pending); + + if (op->interval > 0 && op->start_delay > START_DELAY_THRESHOLD) { + char *uuid = NULL; + int dummy = 0, target_rc = 0; + + crm_info("Faking confirmation of %s: execution postponed for over 5 minutes", op_id); + + decode_transition_key(op->user_data, &uuid, &dummy, &dummy, &target_rc); + crm_free(uuid); + + op->rc = target_rc; + op->op_status = LRM_OP_DONE; + send_direct_ack(NULL, NULL, rsc, op, rsc->id); + } } crm_free(op_id); - free_lrm_op(op); + free_lrm_op(op); return; } lrm_op_t * -copy_lrm_op(const lrm_op_t *op) +copy_lrm_op(const lrm_op_t * op) { lrm_op_t *op_copy = NULL; CRM_CHECK(op != NULL, return NULL); CRM_CHECK(op->rsc_id != NULL, return NULL); crm_malloc0(op_copy, sizeof(lrm_op_t)); op_copy->op_type = crm_strdup(op->op_type); /* input fields */ - op_copy->params = g_hash_table_new_full( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); - - if(op->params != NULL) { - g_hash_table_foreach(op->params, dup_attr, op_copy->params); + op_copy->params = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, g_hash_destroy_str); + + if (op->params != NULL) { + g_hash_table_foreach(op->params, dup_attr, op_copy->params); } - op_copy->timeout = op->timeout; - op_copy->interval = op->interval; - op_copy->target_rc = op->target_rc; + op_copy->timeout = op->timeout; + op_copy->interval = op->interval; + op_copy->target_rc = op->target_rc; /* in the CRM, this is always a string */ - if(op->user_data != NULL) { - op_copy->user_data = crm_strdup(op->user_data); + if (op->user_data != NULL) { + op_copy->user_data = crm_strdup(op->user_data); } - + /* output fields */ - op_copy->op_status = op->op_status; - op_copy->rc = op->rc; - op_copy->call_id = op->call_id; - op_copy->output = NULL; - op_copy->rsc_id = crm_strdup(op->rsc_id); - if(op->app_name != NULL) { - op_copy->app_name = crm_strdup(op->app_name); - } - if(op->output != NULL) { - op_copy->output = crm_strdup(op->output); - } - + op_copy->op_status = op->op_status; + op_copy->rc = op->rc; + op_copy->call_id = op->call_id; + op_copy->output = NULL; + op_copy->rsc_id = crm_strdup(op->rsc_id); + if (op->app_name != NULL) { + op_copy->app_name = crm_strdup(op->app_name); + } + if (op->output != NULL) { + op_copy->output = crm_strdup(op->output); + } + return op_copy; } - lrm_rsc_t * -copy_lrm_rsc(const lrm_rsc_t *rsc) +copy_lrm_rsc(const lrm_rsc_t * rsc) { lrm_rsc_t *rsc_copy = NULL; - if(rsc == NULL) { - return NULL; + if (rsc == NULL) { + return NULL; } - + crm_malloc0(rsc_copy, sizeof(lrm_rsc_t)); - rsc_copy->id = crm_strdup(rsc->id); - rsc_copy->type = crm_strdup(rsc->type); - rsc_copy->class = NULL; + rsc_copy->id = crm_strdup(rsc->id); + rsc_copy->type = crm_strdup(rsc->type); + rsc_copy->class = NULL; rsc_copy->provider = NULL; - if(rsc->class != NULL) { - rsc_copy->class = crm_strdup(rsc->class); + if (rsc->class != NULL) { + rsc_copy->class = crm_strdup(rsc->class); } - if(rsc->provider != NULL) { - rsc_copy->provider = crm_strdup(rsc->provider); + if (rsc->provider != NULL) { + rsc_copy->provider = crm_strdup(rsc->provider); } /* GHashTable* params; */ rsc_copy->params = NULL; - rsc_copy->ops = NULL; + rsc_copy->ops = NULL; return rsc_copy; } static void -cib_rsc_callback(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +cib_rsc_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - switch(rc) { - case cib_ok: - case cib_diff_failed: - case cib_diff_resync: - crm_debug_2("Resource update %d complete: rc=%d", call_id, rc); - break; - default: - crm_warn("Resource update %d failed: (rc=%d) %s", - call_id, rc, cib_error2string(rc)); + switch (rc) { + case cib_ok: + case cib_diff_failed: + case cib_diff_resync: + crm_debug_2("Resource update %d complete: rc=%d", call_id, rc); + break; + default: + crm_warn("Resource update %d failed: (rc=%d) %s", call_id, rc, cib_error2string(rc)); } } - static int -do_update_resource(lrm_rsc_t* rsc, lrm_op_t* op) +do_update_resource(lrm_rsc_t * rsc, lrm_op_t * op) { /* */ int rc = cib_ok; xmlNode *update, *iter = NULL; int call_opt = cib_quorum_override; - + CRM_CHECK(op != NULL, return 0); - if(fsa_state == S_ELECTION || fsa_state == S_PENDING) { - crm_info("Sending update to local CIB in state: %s", fsa_state2string(fsa_state)); - call_opt |= cib_scope_local; + if (fsa_state == S_ELECTION || fsa_state == S_PENDING) { + crm_info("Sending update to local CIB in state: %s", fsa_state2string(fsa_state)); + call_opt |= cib_scope_local; } - - iter = create_xml_node(iter, XML_CIB_TAG_STATUS); update = iter; + + iter = create_xml_node(iter, XML_CIB_TAG_STATUS); + update = iter; iter = create_xml_node(iter, XML_CIB_TAG_STATE); set_uuid(iter, XML_ATTR_UUID, fsa_our_uname); crm_xml_add(iter, XML_ATTR_UNAME, fsa_our_uname); crm_xml_add(iter, XML_ATTR_ORIGIN, __FUNCTION__); - + iter = create_xml_node(iter, XML_CIB_TAG_LRM); crm_xml_add(iter, XML_ATTR_ID, fsa_our_uuid); iter = create_xml_node(iter, XML_LRM_TAG_RESOURCES); iter = create_xml_node(iter, XML_LRM_TAG_RESOURCE); crm_xml_add(iter, XML_ATTR_ID, op->rsc_id); - + build_operation_update(iter, rsc, op, __FUNCTION__); - if(rsc) { - crm_xml_add(iter, XML_ATTR_TYPE, rsc->type); - crm_xml_add(iter, XML_AGENT_ATTR_CLASS, rsc->class); - crm_xml_add(iter, XML_AGENT_ATTR_PROVIDER,rsc->provider); + if (rsc) { + crm_xml_add(iter, XML_ATTR_TYPE, rsc->type); + crm_xml_add(iter, XML_AGENT_ATTR_CLASS, rsc->class); + crm_xml_add(iter, XML_AGENT_ATTR_PROVIDER, rsc->provider); - CRM_CHECK(rsc->type != NULL, - crm_err("Resource %s has no value for type", op->rsc_id)); - CRM_CHECK(rsc->class != NULL, - crm_err("Resource %s has no value for class", op->rsc_id)); + CRM_CHECK(rsc->type != NULL, crm_err("Resource %s has no value for type", op->rsc_id)); + CRM_CHECK(rsc->class != NULL, crm_err("Resource %s has no value for class", op->rsc_id)); } else { - crm_warn("Resource %s no longer exists in the lrmd", op->rsc_id); - goto cleanup; + crm_warn("Resource %s no longer exists in the lrmd", op->rsc_id); + goto cleanup; } /* make it an asyncronous call and be done with it * * Best case: * the resource state will be discovered during * the next signup or election. * * Bad case: * we are shutting down and there is no DC at the time, * but then why were we shutting down then anyway? * (probably because of an internal error) * * Worst case: * we get shot for having resources "running" when the really weren't * * the alternative however means blocking here for too long, which * isnt acceptable */ fsa_cib_update(XML_CIB_TAG_STATUS, update, call_opt, rc, NULL); - + /* the return code is a call number, not an error code */ crm_debug_2("Sent resource state update message: %d", rc); - fsa_cib_conn->cmds->register_callback( - fsa_cib_conn, rc, 60, FALSE, NULL, "cib_rsc_callback", cib_rsc_callback); - + fsa_cib_conn->cmds->register_callback(fsa_cib_conn, rc, 60, FALSE, NULL, "cib_rsc_callback", + cib_rsc_callback); + cleanup: free_xml(update); return rc; } void do_lrm_event(long long action, - enum crmd_fsa_cause cause, - enum crmd_fsa_state cur_state, - enum crmd_fsa_input cur_input, - fsa_data_t *msg_data) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, enum crmd_fsa_input cur_input, fsa_data_t * msg_data) { CRM_CHECK(FALSE, return); } gboolean -process_lrm_event(lrm_op_t *op) +process_lrm_event(lrm_op_t * op) { char *op_id = NULL; char *op_key = NULL; int update_id = 0; int log_level = LOG_ERR; gboolean removed = FALSE; lrm_rsc_t *rsc = NULL; - + struct recurring_op_s *pending = NULL; - + CRM_CHECK(op != NULL, return FALSE); CRM_CHECK(op->rsc_id != NULL, return FALSE); op_key = generate_op_key(op->rsc_id, op->op_type, op->interval); - - switch(op->op_status) { - case LRM_OP_ERROR: - case LRM_OP_PENDING: - case LRM_OP_NOTSUPPORTED: - break; - case LRM_OP_CANCELLED: - log_level = LOG_INFO; - break; - case LRM_OP_DONE: - log_level = LOG_INFO; - break; - case LRM_OP_TIMEOUT: - log_level = LOG_DEBUG_3; - crm_err("LRM operation %s (%d) %s (timeout=%dms)", - op_key, op->call_id, - op_status2text(op->op_status), op->timeout); - break; - default: - crm_err("Mapping unknown status (%d) to ERROR", - op->op_status); - op->op_status = LRM_OP_ERROR; - } - - if(op->op_status == LRM_OP_ERROR - && (op->rc == EXECRA_RUNNING_MASTER || op->rc == EXECRA_NOT_RUNNING)) { - /* Leave it up to the TE/PE to decide if this is an error */ - op->op_status = LRM_OP_DONE; - log_level = LOG_INFO; + + switch (op->op_status) { + case LRM_OP_ERROR: + case LRM_OP_PENDING: + case LRM_OP_NOTSUPPORTED: + break; + case LRM_OP_CANCELLED: + log_level = LOG_INFO; + break; + case LRM_OP_DONE: + log_level = LOG_INFO; + break; + case LRM_OP_TIMEOUT: + log_level = LOG_DEBUG_3; + crm_err("LRM operation %s (%d) %s (timeout=%dms)", + op_key, op->call_id, op_status2text(op->op_status), op->timeout); + break; + default: + crm_err("Mapping unknown status (%d) to ERROR", op->op_status); + op->op_status = LRM_OP_ERROR; + } + + if (op->op_status == LRM_OP_ERROR + && (op->rc == EXECRA_RUNNING_MASTER || op->rc == EXECRA_NOT_RUNNING)) { + /* Leave it up to the TE/PE to decide if this is an error */ + op->op_status = LRM_OP_DONE; + log_level = LOG_INFO; } op_id = make_stop_id(op->rsc_id, op->call_id); pending = g_hash_table_lookup(pending_ops, op_id); rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, op->rsc_id); - if(op->op_status != LRM_OP_CANCELLED) { - if(safe_str_eq(op->op_type, RSC_NOTIFY)) { - /* Keep notify ops out of the CIB */ - send_direct_ack(NULL, NULL, NULL, op, op->rsc_id); - } else { - update_id = do_update_resource(rsc, op); - } - - if(op->interval != 0) { - goto out; - } - - } else if(op->interval == 0) { - /* This will occur when "crm resource cleanup" is called while actions are in-flight */ - crm_err("Op %s (call=%d): Cancelled", op_key, op->call_id); - send_direct_ack(NULL, NULL, NULL, op, op->rsc_id); - - } else if(pending == NULL) { - crm_err("Op %s (call=%d): No 'pending' entry", - op_key, op->call_id); - - } else if(op->user_data == NULL) { - crm_err("Op %s (call=%d): No user data", op_key, op->call_id); - - } else if(pending->remove) { - delete_op_entry(op, op->rsc_id, op_key, op->call_id); + if (op->op_status != LRM_OP_CANCELLED) { + if (safe_str_eq(op->op_type, RSC_NOTIFY)) { + /* Keep notify ops out of the CIB */ + send_direct_ack(NULL, NULL, NULL, op, op->rsc_id); + } else { + update_id = do_update_resource(rsc, op); + } + + if (op->interval != 0) { + goto out; + } + + } else if (op->interval == 0) { + /* This will occur when "crm resource cleanup" is called while actions are in-flight */ + crm_err("Op %s (call=%d): Cancelled", op_key, op->call_id); + send_direct_ack(NULL, NULL, NULL, op, op->rsc_id); + + } else if (pending == NULL) { + crm_err("Op %s (call=%d): No 'pending' entry", op_key, op->call_id); + + } else if (op->user_data == NULL) { + crm_err("Op %s (call=%d): No user data", op_key, op->call_id); + + } else if (pending->remove) { + delete_op_entry(op, op->rsc_id, op_key, op->call_id); } else { - /* Before a stop is called, no need to direct ack */ - crm_debug_2("Op %s (call=%d): no delete event required", op_key, op->call_id); + /* Before a stop is called, no need to direct ack */ + crm_debug_2("Op %s (call=%d): no delete event required", op_key, op->call_id); } - if(g_hash_table_remove(pending_ops, op_id)) { - removed = TRUE; - crm_debug_2("Op %s (call=%d, stop-id=%s): Confirmed", op_key, op->call_id, op_id); + if (g_hash_table_remove(pending_ops, op_id)) { + removed = TRUE; + crm_debug_2("Op %s (call=%d, stop-id=%s): Confirmed", op_key, op->call_id, op_id); } out: - if(op->op_status == LRM_OP_DONE) { - do_crm_log(log_level, - "LRM operation %s (call=%d, rc=%d, cib-update=%d, confirmed=%s) %s", - op_key, op->call_id, op->rc, update_id, removed?"true":"false", - execra_code2string(op->rc)); + if (op->op_status == LRM_OP_DONE) { + do_crm_log(log_level, + "LRM operation %s (call=%d, rc=%d, cib-update=%d, confirmed=%s) %s", + op_key, op->call_id, op->rc, update_id, removed ? "true" : "false", + execra_code2string(op->rc)); } else { - do_crm_log(log_level, - "LRM operation %s (call=%d, status=%d, cib-update=%d, confirmed=%s) %s", - op_key, op->call_id, op->op_status, update_id, removed?"true":"false", - op_status2text(op->op_status)); - } - - if(op->rc != 0 && op->output != NULL) { - crm_info("Result: %s", op->output); - } else if(op->output != NULL) { - crm_debug("Result: %s", op->output); + do_crm_log(log_level, + "LRM operation %s (call=%d, status=%d, cib-update=%d, confirmed=%s) %s", + op_key, op->call_id, op->op_status, update_id, removed ? "true" : "false", + op_status2text(op->op_status)); } + if (op->rc != 0 && op->output != NULL) { + crm_info("Result: %s", op->output); + } else if (op->output != NULL) { + crm_debug("Result: %s", op->output); + } #ifdef HAVE_LRM_OP_T_RSC_DELETED - if(op->rsc_deleted) { - crm_info("Deletion of resource '%s' complete after %s", op->rsc_id, op_key); - delete_rsc_entry(NULL, op->rsc_id, HA_OK, NULL); + if (op->rsc_deleted) { + crm_info("Deletion of resource '%s' complete after %s", op->rsc_id, op_key); + delete_rsc_entry(NULL, op->rsc_id, HA_OK, NULL); } #endif - /* If a shutdown was escalated while operations were pending, * then the FSA will be stalled right now... allow it to continue */ mainloop_set_trigger(fsa_source); update_history_cache(rsc, op); lrm_free_rsc(rsc); crm_free(op_key); crm_free(op_id); - + return TRUE; } diff --git a/crmd/main.c b/crmd/main.c index 06aba441f0..46bf010fc1 100644 --- a/crmd/main.c +++ b/crmd/main.c @@ -1,172 +1,171 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define OPTARGS "hV" -void usage(const char* cmd, int exit_status); +void usage(const char *cmd, int exit_status); int crmd_init(void); -void crmd_hamsg_callback(const xmlNode * msg, void* private_data); +void crmd_hamsg_callback(const xmlNode * msg, void *private_data); extern void init_dotfile(void); -GMainLoop* crmd_mainloop = NULL; +GMainLoop *crmd_mainloop = NULL; int -main(int argc, char ** argv) +main(int argc, char **argv) { int flag; - int argerr = 0; + int argerr = 0; crm_system_name = CRM_SYSTEM_CRMD; - + while ((flag = getopt(argc, argv, OPTARGS)) != EOF) { - switch(flag) { - case 'V': - cl_log_enable_stderr(1); - alter_debug(DEBUG_INC); - break; - case 'h': /* Help message */ - usage(crm_system_name, LSB_EXIT_OK); - break; - default: - ++argerr; - break; - } + switch (flag) { + case 'V': + cl_log_enable_stderr(1); + alter_debug(DEBUG_INC); + break; + case 'h': /* Help message */ + usage(crm_system_name, LSB_EXIT_OK); + break; + default: + ++argerr; + break; + } } - if(argc - optind == 1 && safe_str_eq("metadata", argv[optind])) { - crmd_metadata(); - return 0; - } else if(argc - optind == 1 && safe_str_eq("version", argv[optind])) { - fprintf(stdout, "CRM Version: "); - fprintf(stdout, "%s (%s)\n", VERSION, BUILD_VERSION); - return 0; + if (argc - optind == 1 && safe_str_eq("metadata", argv[optind])) { + crmd_metadata(); + return 0; + } else if (argc - optind == 1 && safe_str_eq("version", argv[optind])) { + fprintf(stdout, "CRM Version: "); + fprintf(stdout, "%s (%s)\n", VERSION, BUILD_VERSION); + return 0; } crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv); - + crm_info("CRM Hg Version: %s\n", BUILD_VERSION); - + if (optind > argc) { - ++argerr; + ++argerr; } - + if (argerr) { - usage(crm_system_name, LSB_EXIT_GENERIC); + usage(crm_system_name, LSB_EXIT_GENERIC); } - - if(crm_is_writable(PE_STATE_DIR, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) { - crm_err("Bad permissions on "PE_STATE_DIR". Terminating"); - fprintf(stderr,"ERROR: Bad permissions on "PE_STATE_DIR". See logs for details\n"); - fflush(stderr); - return 100; - - } else if(crm_is_writable(CRM_CONFIG_DIR, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) { - crm_err("Bad permissions on "CRM_CONFIG_DIR". Terminating"); - fprintf(stderr,"ERROR: Bad permissions on "CRM_CONFIG_DIR". See logs for details\n"); - fflush(stderr); - return 100; + + if (crm_is_writable(PE_STATE_DIR, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) { + crm_err("Bad permissions on " PE_STATE_DIR ". Terminating"); + fprintf(stderr, "ERROR: Bad permissions on " PE_STATE_DIR ". See logs for details\n"); + fflush(stderr); + return 100; + + } else if (crm_is_writable(CRM_CONFIG_DIR, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == + FALSE) { + crm_err("Bad permissions on " CRM_CONFIG_DIR ". Terminating"); + fprintf(stderr, "ERROR: Bad permissions on " CRM_CONFIG_DIR ". See logs for details\n"); + fflush(stderr); + return 100; } - + return crmd_init(); } - int crmd_init(void) { int exit_code = 0; enum crmd_fsa_state state; fsa_state = S_STARTING; - fsa_input_register = 0; /* zero out the regester */ + fsa_input_register = 0; /* zero out the regester */ init_dotfile(); crm_info("Starting %s", crm_system_name); register_fsa_input(C_STARTUP, I_STARTUP, NULL); crm_peer_init(); state = s_crmd_fsa(C_STARTUP); - + if (state == S_PENDING || state == S_STARTING) { - /* Create the mainloop and run it... */ - crmd_mainloop = g_main_new(FALSE); - crm_info("Starting %s's mainloop", crm_system_name); - + /* Create the mainloop and run it... */ + crmd_mainloop = g_main_new(FALSE); + crm_info("Starting %s's mainloop", crm_system_name); + #ifdef REALTIME_SUPPORT - static int crm_realtime = 1; - if (crm_realtime == 1){ - cl_enable_realtime(); - }else if (crm_realtime == 0){ - cl_disable_realtime(); - } - cl_make_realtime(SCHED_RR, 5, 64, 64); + static int crm_realtime = 1; + + if (crm_realtime == 1) { + cl_enable_realtime(); + } else if (crm_realtime == 0) { + cl_disable_realtime(); + } + cl_make_realtime(SCHED_RR, 5, 64, 64); #endif - g_main_run(crmd_mainloop); - if(is_set(fsa_input_register, R_STAYDOWN)) { - crm_info("Inhibiting respawn by Heartbeat"); - exit_code = 100; - } + g_main_run(crmd_mainloop); + if (is_set(fsa_input_register, R_STAYDOWN)) { + crm_info("Inhibiting respawn by Heartbeat"); + exit_code = 100; + } } else { - crm_err("Startup of %s failed. Current state: %s", - crm_system_name, fsa_state2string(state)); - exit_code = 1; + crm_err("Startup of %s failed. Current state: %s", + crm_system_name, fsa_state2string(state)); + exit_code = 1; } - + crm_info("[%s] stopped (%d)", crm_system_name, exit_code); return exit_code; } - - void -usage(const char* cmd, int exit_status) +usage(const char *cmd, int exit_status) { - FILE* stream; + FILE *stream; stream = exit_status ? stderr : stdout; fprintf(stream, "usage: %s [-V] [-h|version|metadata]\n", cmd); fprintf(stream, "\t-h\t: this help message\n"); fprintf(stream, "\t-V\t: increase verbosity\n"); fprintf(stream, "\tmetadata\t: show configurable crmd options\n"); fprintf(stream, "\tversion\t\t: show version information and quit\n"); fflush(stream); exit(exit_status); } diff --git a/crmd/messages.c b/crmd/messages.c index 8d76ed8e56..59ee88e407 100644 --- a/crmd/messages.c +++ b/crmd/messages.c @@ -1,1024 +1,990 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include - GListPtr fsa_message_queue = NULL; extern void crm_shutdown(int nsig); -void handle_response(xmlNode *stored_msg); -enum crmd_fsa_input handle_request(xmlNode *stored_msg); -enum crmd_fsa_input handle_shutdown_request(xmlNode *stored_msg); +void handle_response(xmlNode * stored_msg); +enum crmd_fsa_input handle_request(xmlNode * stored_msg); +enum crmd_fsa_input handle_shutdown_request(xmlNode * stored_msg); gboolean ipc_queue_helper(gpointer key, gpointer value, gpointer user_data); - #ifdef MSG_LOG -# define ROUTER_RESULT(x) crm_debug_3("Router result: %s", x); \ +# define ROUTER_RESULT(x) crm_debug_3("Router result: %s", x); \ crm_log_xml(LOG_MSG, "router.log", msg); #else -# define ROUTER_RESULT(x) crm_debug_3("Router result: %s", x) +# define ROUTER_RESULT(x) crm_debug_3("Router result: %s", x) #endif /* debug only, can wrap all it likes */ int last_data_id = 0; void -register_fsa_error_adv( - enum crmd_fsa_cause cause, enum crmd_fsa_input input, - fsa_data_t *cur_data, void *new_data, const char *raised_from) +register_fsa_error_adv(enum crmd_fsa_cause cause, enum crmd_fsa_input input, + fsa_data_t * cur_data, void *new_data, const char *raised_from) { /* save the current actions if any */ - if(fsa_actions != A_NOTHING) { - register_fsa_input_adv( - cur_data?cur_data->fsa_cause:C_FSA_INTERNAL, - I_NULL, cur_data?cur_data->data:NULL, - fsa_actions, TRUE, __FUNCTION__); + if (fsa_actions != A_NOTHING) { + register_fsa_input_adv(cur_data ? cur_data->fsa_cause : C_FSA_INTERNAL, + I_NULL, cur_data ? cur_data->data : NULL, + fsa_actions, TRUE, __FUNCTION__); } - + /* reset the action list */ fsa_actions = A_NOTHING; /* register the error */ - register_fsa_input_adv( - cause, input, new_data, A_NOTHING, TRUE, raised_from); + register_fsa_input_adv(cause, input, new_data, A_NOTHING, TRUE, raised_from); } int -register_fsa_input_adv( - enum crmd_fsa_cause cause, enum crmd_fsa_input input, - void *data, long long with_actions, - gboolean prepend, const char *raised_from) +register_fsa_input_adv(enum crmd_fsa_cause cause, enum crmd_fsa_input input, + void *data, long long with_actions, + gboolean prepend, const char *raised_from) { - unsigned old_len = g_list_length(fsa_message_queue); + unsigned old_len = g_list_length(fsa_message_queue); fsa_data_t *fsa_data = NULL; last_data_id++; CRM_CHECK(raised_from != NULL, raised_from = ""); - - crm_debug_2("%s %s FSA input %d (%s) (cause=%s) %s data", - raised_from, prepend?"prepended":"appended",last_data_id, fsa_input2string(input), - fsa_cause2string(cause), data?"with":"without"); - - if(input == I_WAIT_FOR_EVENT) { - do_fsa_stall = TRUE; - crm_debug("Stalling the FSA pending further input: cause=%s", - fsa_cause2string(cause)); - if(old_len > 0) { - crm_warn("%s stalled the FSA with pending inputs", - raised_from); - fsa_dump_queue(LOG_DEBUG); - } - if(data == NULL) { - set_bit_inplace(fsa_actions, with_actions); - with_actions = A_NOTHING; - return 0; - } - crm_err("%s stalled the FSA with data - this may be broken", - raised_from); - } - if(input == I_NULL && with_actions == A_NOTHING /* && data == NULL */){ - /* no point doing anything */ - crm_err("Cannot add entry to queue: no input and no action"); - return 0; + crm_debug_2("%s %s FSA input %d (%s) (cause=%s) %s data", + raised_from, prepend ? "prepended" : "appended", last_data_id, + fsa_input2string(input), fsa_cause2string(cause), data ? "with" : "without"); + + if (input == I_WAIT_FOR_EVENT) { + do_fsa_stall = TRUE; + crm_debug("Stalling the FSA pending further input: cause=%s", fsa_cause2string(cause)); + if (old_len > 0) { + crm_warn("%s stalled the FSA with pending inputs", raised_from); + fsa_dump_queue(LOG_DEBUG); + } + if (data == NULL) { + set_bit_inplace(fsa_actions, with_actions); + with_actions = A_NOTHING; + return 0; + } + crm_err("%s stalled the FSA with data - this may be broken", raised_from); + } + + if (input == I_NULL && with_actions == A_NOTHING /* && data == NULL */ ) { + /* no point doing anything */ + crm_err("Cannot add entry to queue: no input and no action"); + return 0; } crm_malloc0(fsa_data, sizeof(fsa_data_t)); - fsa_data->id = last_data_id; + fsa_data->id = last_data_id; fsa_data->fsa_input = input; fsa_data->fsa_cause = cause; - fsa_data->origin = raised_from; - fsa_data->data = NULL; + fsa_data->origin = raised_from; + fsa_data->data = NULL; fsa_data->data_type = fsa_dt_none; - fsa_data->actions = with_actions; - - if(with_actions != A_NOTHING) { - crm_debug_3("Adding actions %.16llx to input", with_actions); + fsa_data->actions = with_actions; + + if (with_actions != A_NOTHING) { + crm_debug_3("Adding actions %.16llx to input", with_actions); + } + + if (data != NULL) { + switch (cause) { + case C_FSA_INTERNAL: + case C_CRMD_STATUS_CALLBACK: + case C_IPC_MESSAGE: + case C_HA_MESSAGE: + crm_debug_3("Copying %s data from %s as a HA msg", + fsa_cause2string(cause), raised_from); + CRM_CHECK(((ha_msg_input_t *) data)->msg != NULL, + crm_err("Bogus data from %s", raised_from)); + fsa_data->data = copy_ha_msg_input(data); + fsa_data->data_type = fsa_dt_ha_msg; + break; + + case C_LRM_OP_CALLBACK: + crm_debug_3("Copying %s data from %s as lrm_op_t", + fsa_cause2string(cause), raised_from); + fsa_data->data = copy_lrm_op((lrm_op_t *) data); + fsa_data->data_type = fsa_dt_lrm; + break; + + case C_CCM_CALLBACK: + case C_SUBSYSTEM_CONNECT: + case C_LRM_MONITOR_CALLBACK: + case C_TIMER_POPPED: + case C_SHUTDOWN: + case C_HEARTBEAT_FAILED: + case C_HA_DISCONNECT: + case C_ILLEGAL: + case C_UNKNOWN: + case C_STARTUP: + crm_err("Copying %s data (from %s)" + " not yet implemented", fsa_cause2string(cause), raised_from); + exit(1); + break; + } + crm_debug_4("%s data copied", fsa_cause2string(fsa_data->fsa_cause)); } - - if(data != NULL) { - switch(cause) { - case C_FSA_INTERNAL: - case C_CRMD_STATUS_CALLBACK: - case C_IPC_MESSAGE: - case C_HA_MESSAGE: - crm_debug_3("Copying %s data from %s as a HA msg", - fsa_cause2string(cause), - raised_from); - CRM_CHECK(((ha_msg_input_t*)data)->msg != NULL, - crm_err("Bogus data from %s", raised_from)); - fsa_data->data = copy_ha_msg_input(data); - fsa_data->data_type = fsa_dt_ha_msg; - break; - - case C_LRM_OP_CALLBACK: - crm_debug_3("Copying %s data from %s as lrm_op_t", - fsa_cause2string(cause), - raised_from); - fsa_data->data = copy_lrm_op((lrm_op_t*)data); - fsa_data->data_type = fsa_dt_lrm; - break; - - case C_CCM_CALLBACK: - case C_SUBSYSTEM_CONNECT: - case C_LRM_MONITOR_CALLBACK: - case C_TIMER_POPPED: - case C_SHUTDOWN: - case C_HEARTBEAT_FAILED: - case C_HA_DISCONNECT: - case C_ILLEGAL: - case C_UNKNOWN: - case C_STARTUP: - crm_err("Copying %s data (from %s)" - " not yet implemented", - fsa_cause2string(cause), raised_from); - exit(1); - break; - } - crm_debug_4("%s data copied", - fsa_cause2string(fsa_data->fsa_cause)); - } - + /* make sure to free it properly later */ - if(prepend) { - crm_debug_2("Prepending input"); - fsa_message_queue = g_list_prepend(fsa_message_queue, fsa_data); + if (prepend) { + crm_debug_2("Prepending input"); + fsa_message_queue = g_list_prepend(fsa_message_queue, fsa_data); } else { - fsa_message_queue = g_list_append(fsa_message_queue, fsa_data); + fsa_message_queue = g_list_append(fsa_message_queue, fsa_data); } - + crm_debug_2("Queue len: %d", g_list_length(fsa_message_queue)); fsa_dump_queue(LOG_DEBUG_2); - - if(old_len == g_list_length(fsa_message_queue)){ - crm_err("Couldnt add message to the queue"); + + if (old_len == g_list_length(fsa_message_queue)) { + crm_err("Couldnt add message to the queue"); } - if(fsa_source) { - crm_debug_3("Triggering FSA: %s", __FUNCTION__); - mainloop_set_trigger(fsa_source); + if (fsa_source) { + crm_debug_3("Triggering FSA: %s", __FUNCTION__); + mainloop_set_trigger(fsa_source); } return last_data_id; } void -fsa_dump_queue(int log_level) +fsa_dump_queue(int log_level) { int offset = 0; GListPtr lpc = NULL; - if(log_level < (int)crm_log_level) { - return; + + if (log_level < (int)crm_log_level) { + return; + } + for (lpc = fsa_message_queue; lpc != NULL; lpc = lpc->next) { + fsa_data_t *data = (fsa_data_t *) lpc->data; + + do_crm_log(log_level, + "queue[%d(%d)]: input %s raised by %s()\t(cause=%s)", + offset++, data->id, fsa_input2string(data->fsa_input), + data->origin, fsa_cause2string(data->fsa_cause)); } - for(lpc = fsa_message_queue; lpc != NULL; lpc = lpc->next) { - fsa_data_t *data = (fsa_data_t*)lpc->data; - - do_crm_log(log_level, - "queue[%d(%d)]: input %s raised by %s()\t(cause=%s)", - offset++, data->id, fsa_input2string(data->fsa_input), - data->origin, fsa_cause2string(data->fsa_cause)); - } } ha_msg_input_t * -copy_ha_msg_input(ha_msg_input_t *orig) +copy_ha_msg_input(ha_msg_input_t * orig) { ha_msg_input_t *copy = NULL; xmlNodePtr data = NULL; - - if(orig != NULL) { - crm_debug_4("Copy msg"); - data = copy_xml(orig->msg); + + if (orig != NULL) { + crm_debug_4("Copy msg"); + data = copy_xml(orig->msg); } else { - crm_debug_3("No message to copy"); + crm_debug_3("No message to copy"); } copy = new_ha_msg_input(data); - if(orig && orig->msg != NULL) { - CRM_CHECK(copy->msg != NULL, crm_err("copy failed")); + if (orig && orig->msg != NULL) { + CRM_CHECK(copy->msg != NULL, crm_err("copy failed")); } return copy; } - void -delete_fsa_input(fsa_data_t *fsa_data) +delete_fsa_input(fsa_data_t * fsa_data) { lrm_op_t *op = NULL; xmlNode *foo = NULL; - if(fsa_data == NULL) { - return; + if (fsa_data == NULL) { + return; } - crm_debug_4("About to free %s data", - fsa_cause2string(fsa_data->fsa_cause)); - - if(fsa_data->data != NULL) { - switch(fsa_data->data_type) { - case fsa_dt_ha_msg: - delete_ha_msg_input(fsa_data->data); - break; - - case fsa_dt_xml: - foo = fsa_data->data; - free_xml(foo); - break; - - case fsa_dt_lrm: - op = (lrm_op_t*)fsa_data->data; - free_lrm_op(op); - break; - - case fsa_dt_none: - if(fsa_data->data != NULL) { - crm_err("Dont know how to free %s data from %s", - fsa_cause2string(fsa_data->fsa_cause), - fsa_data->origin); - exit(1); - } - break; - } - crm_debug_4("%s data freed", - fsa_cause2string(fsa_data->fsa_cause)); + crm_debug_4("About to free %s data", fsa_cause2string(fsa_data->fsa_cause)); + + if (fsa_data->data != NULL) { + switch (fsa_data->data_type) { + case fsa_dt_ha_msg: + delete_ha_msg_input(fsa_data->data); + break; + + case fsa_dt_xml: + foo = fsa_data->data; + free_xml(foo); + break; + + case fsa_dt_lrm: + op = (lrm_op_t *) fsa_data->data; + free_lrm_op(op); + break; + + case fsa_dt_none: + if (fsa_data->data != NULL) { + crm_err("Dont know how to free %s data from %s", + fsa_cause2string(fsa_data->fsa_cause), fsa_data->origin); + exit(1); + } + break; + } + crm_debug_4("%s data freed", fsa_cause2string(fsa_data->fsa_cause)); } crm_free(fsa_data); } /* returns the next message */ fsa_data_t * get_message(void) { - fsa_data_t* message = g_list_nth_data(fsa_message_queue, 0); + fsa_data_t *message = g_list_nth_data(fsa_message_queue, 0); + fsa_message_queue = g_list_remove(fsa_message_queue, message); crm_debug_2("Processing input %d", message->id); return message; } /* returns the current head of the FIFO queue */ gboolean is_message(void) { return (g_list_length(fsa_message_queue) > 0); } - void * -fsa_typed_data_adv( - fsa_data_t *fsa_data, enum fsa_data_type a_type, const char *caller) +fsa_typed_data_adv(fsa_data_t * fsa_data, enum fsa_data_type a_type, const char *caller) { void *ret_val = NULL; - if(fsa_data == NULL) { - do_crm_log(LOG_ERR, "%s: No FSA data available", caller); - - } else if(fsa_data->data == NULL) { - do_crm_log(LOG_ERR, "%s: No message data available. Origin: %s", - caller, fsa_data->origin); - - } else if(fsa_data->data_type != a_type) { - do_crm_log(LOG_CRIT, - "%s: Message data was the wrong type! %d vs. requested=%d." - " Origin: %s", caller, - fsa_data->data_type, a_type, fsa_data->origin); - CRM_ASSERT(fsa_data->data_type == a_type); + + if (fsa_data == NULL) { + do_crm_log(LOG_ERR, "%s: No FSA data available", caller); + + } else if (fsa_data->data == NULL) { + do_crm_log(LOG_ERR, "%s: No message data available. Origin: %s", caller, fsa_data->origin); + + } else if (fsa_data->data_type != a_type) { + do_crm_log(LOG_CRIT, + "%s: Message data was the wrong type! %d vs. requested=%d." + " Origin: %s", caller, fsa_data->data_type, a_type, fsa_data->origin); + CRM_ASSERT(fsa_data->data_type == a_type); } else { - ret_val = fsa_data->data; + ret_val = fsa_data->data; } - + return ret_val; } - /* A_MSG_ROUTE */ void do_msg_route(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg); + route_message(msg_data->fsa_cause, input->msg); } void -route_message(enum crmd_fsa_cause cause, xmlNode *input) +route_message(enum crmd_fsa_cause cause, xmlNode * input) { ha_msg_input_t fsa_input; enum crmd_fsa_input result = I_NULL; fsa_input.msg = input; CRM_CHECK(cause == C_IPC_MESSAGE || cause == C_HA_MESSAGE, return); /* try passing the buck first */ - if(relay_message(input, cause==C_IPC_MESSAGE)) { - return; + if (relay_message(input, cause == C_IPC_MESSAGE)) { + return; } - + /* handle locally */ result = handle_message(input); /* done or process later? */ - switch(result) { - case I_NULL: - case I_CIB_OP: - case I_ROUTER: - case I_NODE_JOIN: - case I_JOIN_REQUEST: - case I_JOIN_RESULT: - break; - default: - /* Defering local processing of message */ - register_fsa_input_later(cause, result, &fsa_input); - return; - } - - if(result != I_NULL) { - /* add to the front of the queue */ - register_fsa_input(cause, result, &fsa_input); + switch (result) { + case I_NULL: + case I_CIB_OP: + case I_ROUTER: + case I_NODE_JOIN: + case I_JOIN_REQUEST: + case I_JOIN_RESULT: + break; + default: + /* Defering local processing of message */ + register_fsa_input_later(cause, result, &fsa_input); + return; + } + + if (result != I_NULL) { + /* add to the front of the queue */ + register_fsa_input(cause, result, &fsa_input); } } gboolean -relay_message(xmlNode *msg, gboolean originated_locally) +relay_message(xmlNode * msg, gboolean originated_locally) { int dest = 1; - int is_for_dc = 0; - int is_for_dcib = 0; - int is_for_te = 0; - int is_for_crm = 0; - int is_for_cib = 0; - int is_local = 0; + int is_for_dc = 0; + int is_for_dcib = 0; + int is_for_te = 0; + int is_for_crm = 0; + int is_for_cib = 0; + int is_local = 0; gboolean processing_complete = FALSE; const char *host_to = crm_element_value(msg, F_CRM_HOST_TO); - const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); - const char *sys_from= crm_element_value(msg, F_CRM_SYS_FROM); - const char *type = crm_element_value(msg, F_TYPE); + const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); + const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM); + const char *type = crm_element_value(msg, F_TYPE); const char *msg_error = NULL; - crm_debug_3("Routing message %s", - crm_element_value(msg, XML_ATTR_REFERENCE)); + crm_debug_3("Routing message %s", crm_element_value(msg, XML_ATTR_REFERENCE)); - if(msg == NULL) { - msg_error = "Cannot route empty message"; + if (msg == NULL) { + msg_error = "Cannot route empty message"; - } else if(safe_str_eq(CRM_OP_HELLO, - crm_element_value(msg, F_CRM_TASK))){ - /* quietly ignore */ - processing_complete = TRUE; + } else if (safe_str_eq(CRM_OP_HELLO, crm_element_value(msg, F_CRM_TASK))) { + /* quietly ignore */ + processing_complete = TRUE; - } else if(safe_str_neq(type, T_CRM)) { - msg_error = "Bad message type"; + } else if (safe_str_neq(type, T_CRM)) { + msg_error = "Bad message type"; - } else if(sys_to == NULL) { - msg_error = "Bad message destination: no subsystem"; + } else if (sys_to == NULL) { + msg_error = "Bad message destination: no subsystem"; } - if(msg_error != NULL) { - processing_complete = TRUE; - crm_err("%s", msg_error); - crm_log_xml(LOG_WARNING, "bad msg", msg); + if (msg_error != NULL) { + processing_complete = TRUE; + crm_err("%s", msg_error); + crm_log_xml(LOG_WARNING, "bad msg", msg); } - if(processing_complete) { - return TRUE; + if (processing_complete) { + return TRUE; } - + processing_complete = TRUE; - - is_for_dc = (strcasecmp(CRM_SYSTEM_DC, sys_to) == 0); + + is_for_dc = (strcasecmp(CRM_SYSTEM_DC, sys_to) == 0); is_for_dcib = (strcasecmp(CRM_SYSTEM_DCIB, sys_to) == 0); - is_for_te = (strcasecmp(CRM_SYSTEM_TENGINE, sys_to) == 0); - is_for_cib = (strcasecmp(CRM_SYSTEM_CIB, sys_to) == 0); - is_for_crm = (strcasecmp(CRM_SYSTEM_CRMD, sys_to) == 0); - + is_for_te = (strcasecmp(CRM_SYSTEM_TENGINE, sys_to) == 0); + is_for_cib = (strcasecmp(CRM_SYSTEM_CIB, sys_to) == 0); + is_for_crm = (strcasecmp(CRM_SYSTEM_CRMD, sys_to) == 0); + is_local = 0; - if(host_to == NULL || strlen(host_to) == 0) { - if(is_for_dc || is_for_te) { - is_local = 0; - - } else if(is_for_crm && originated_locally) { - is_local = 0; - - } else { - is_local = 1; - } - - } else if(safe_str_eq(fsa_our_uname, host_to)) { - is_local=1; - } - - if(is_for_dc || is_for_dcib || is_for_te) { - if(AM_I_DC && is_for_te) { - ROUTER_RESULT("Message result: Local relay"); - send_msg_via_ipc(msg, sys_to); - - } else if(AM_I_DC) { - ROUTER_RESULT("Message result: DC/CRMd process"); - processing_complete = FALSE; /* more to be done by caller */ - } else if(originated_locally - && safe_str_neq(sys_from, CRM_SYSTEM_PENGINE) - && safe_str_neq(sys_from, CRM_SYSTEM_TENGINE)) { - - /* Neither the TE or PE should be sending messages - * to DC's on other nodes - * - * By definition, if we are no longer the DC, then - * the PE or TE's data should be discarded - */ - + if (host_to == NULL || strlen(host_to) == 0) { + if (is_for_dc || is_for_te) { + is_local = 0; + + } else if (is_for_crm && originated_locally) { + is_local = 0; + + } else { + is_local = 1; + } + + } else if (safe_str_eq(fsa_our_uname, host_to)) { + is_local = 1; + } + + if (is_for_dc || is_for_dcib || is_for_te) { + if (AM_I_DC && is_for_te) { + ROUTER_RESULT("Message result: Local relay"); + send_msg_via_ipc(msg, sys_to); + + } else if (AM_I_DC) { + ROUTER_RESULT("Message result: DC/CRMd process"); + processing_complete = FALSE; /* more to be done by caller */ + } else if (originated_locally && safe_str_neq(sys_from, CRM_SYSTEM_PENGINE) + && safe_str_neq(sys_from, CRM_SYSTEM_TENGINE)) { + + /* Neither the TE or PE should be sending messages + * to DC's on other nodes + * + * By definition, if we are no longer the DC, then + * the PE or TE's data should be discarded + */ + #if SUPPORT_COROSYNC - if(is_openais_cluster()) { - dest = text2msg_type(sys_to); - } + if (is_openais_cluster()) { + dest = text2msg_type(sys_to); + } #endif - ROUTER_RESULT("Message result: External relay to DC"); - send_cluster_message(host_to, dest, msg, TRUE); - - } else { - /* discard */ - ROUTER_RESULT("Message result: Discard, not DC"); - } - - } else if(is_local && (is_for_crm || is_for_cib)) { - ROUTER_RESULT("Message result: CRMd process"); - processing_complete = FALSE; /* more to be done by caller */ - - } else if(is_local) { - ROUTER_RESULT("Message result: Local relay"); - send_msg_via_ipc(msg, sys_to); - + ROUTER_RESULT("Message result: External relay to DC"); + send_cluster_message(host_to, dest, msg, TRUE); + + } else { + /* discard */ + ROUTER_RESULT("Message result: Discard, not DC"); + } + + } else if (is_local && (is_for_crm || is_for_cib)) { + ROUTER_RESULT("Message result: CRMd process"); + processing_complete = FALSE; /* more to be done by caller */ + + } else if (is_local) { + ROUTER_RESULT("Message result: Local relay"); + send_msg_via_ipc(msg, sys_to); + } else { #if SUPPORT_COROSYNC - if(is_openais_cluster()) { - dest = text2msg_type(sys_to); - } + if (is_openais_cluster()) { + dest = text2msg_type(sys_to); + } #endif - ROUTER_RESULT("Message result: External relay"); - send_cluster_message(host_to, dest, msg, TRUE); + ROUTER_RESULT("Message result: External relay"); + send_cluster_message(host_to, dest, msg, TRUE); } - + return processing_complete; } gboolean -crmd_authorize_message(xmlNode *client_msg, crmd_client_t *curr_client) +crmd_authorize_message(xmlNode * client_msg, crmd_client_t * curr_client) { /* check the best case first */ const char *sys_from = crm_element_value(client_msg, F_CRM_SYS_FROM); char *uuid = NULL; char *client_name = NULL; char *major_version = NULL; char *minor_version = NULL; const char *filtered_from; gpointer table_key = NULL; gboolean auth_result = FALSE; struct crm_subsystem_s *the_subsystem = NULL; gboolean can_reply = FALSE; /* no-one has registered with this id */ xmlNode *xml = NULL; const char *op = crm_element_value(client_msg, F_CRM_TASK); - if (safe_str_neq(CRM_OP_HELLO, op)) { - - if(sys_from == NULL) { - crm_warn("Message [%s] was had no value for %s... discarding", - crm_element_value(client_msg, XML_ATTR_REFERENCE), - F_CRM_SYS_FROM); - return FALSE; - } - - filtered_from = sys_from; - - /* The CIB can have two names on the DC */ - if(strcasecmp(sys_from, CRM_SYSTEM_DCIB) == 0) - filtered_from = CRM_SYSTEM_CIB; - - if (g_hash_table_lookup (ipc_clients, filtered_from) != NULL) { - can_reply = TRUE; /* reply can be routed */ - } - - crm_debug_2("Message reply can%s be routed from %s.", - can_reply?"":" not", sys_from); - - if(can_reply == FALSE) { - crm_warn("Message [%s] not authorized", - crm_element_value(client_msg, XML_ATTR_REFERENCE)); - } - - return can_reply; + if (safe_str_neq(CRM_OP_HELLO, op)) { + + if (sys_from == NULL) { + crm_warn("Message [%s] was had no value for %s... discarding", + crm_element_value(client_msg, XML_ATTR_REFERENCE), F_CRM_SYS_FROM); + return FALSE; + } + + filtered_from = sys_from; + + /* The CIB can have two names on the DC */ + if (strcasecmp(sys_from, CRM_SYSTEM_DCIB) == 0) + filtered_from = CRM_SYSTEM_CIB; + + if (g_hash_table_lookup(ipc_clients, filtered_from) != NULL) { + can_reply = TRUE; /* reply can be routed */ + } + + crm_debug_2("Message reply can%s be routed from %s.", can_reply ? "" : " not", sys_from); + + if (can_reply == FALSE) { + crm_warn("Message [%s] not authorized", + crm_element_value(client_msg, XML_ATTR_REFERENCE)); + } + + return can_reply; } - + crm_debug_3("received client join msg"); crm_log_xml(LOG_MSG, "join", client_msg); xml = get_message_xml(client_msg, F_CRM_DATA); - auth_result = process_hello_message( - xml, &uuid, &client_name, - &major_version, &minor_version); + auth_result = process_hello_message(xml, &uuid, &client_name, &major_version, &minor_version); if (auth_result == TRUE) { - if(client_name == NULL || uuid == NULL) { - crm_err("Bad client details (client_name=%s, uuid=%s)", - crm_str(client_name), crm_str(uuid)); - auth_result = FALSE; - } + if (client_name == NULL || uuid == NULL) { + crm_err("Bad client details (client_name=%s, uuid=%s)", + crm_str(client_name), crm_str(uuid)); + auth_result = FALSE; + } } if (auth_result == TRUE) { - /* check version */ - int mav = atoi(major_version); - int miv = atoi(minor_version); - crm_debug_3("Checking client version number"); - if (mav < 0 || miv < 0) { - crm_err("Client version (%d:%d) is not acceptable", - mav, miv); - auth_result = FALSE; - } - crm_free(major_version); - crm_free(minor_version); + /* check version */ + int mav = atoi(major_version); + int miv = atoi(minor_version); + + crm_debug_3("Checking client version number"); + if (mav < 0 || miv < 0) { + crm_err("Client version (%d:%d) is not acceptable", mav, miv); + auth_result = FALSE; + } + crm_free(major_version); + crm_free(minor_version); } - + if (safe_str_eq(CRM_SYSTEM_PENGINE, client_name)) { - the_subsystem = pe_subsystem; - + the_subsystem = pe_subsystem; + } else if (safe_str_eq(CRM_SYSTEM_TENGINE, client_name)) { - the_subsystem = te_subsystem; + the_subsystem = te_subsystem; } /* TODO: Is this code required anymore?? */ if (auth_result == TRUE && the_subsystem != NULL) { - /* if we already have one of those clients - * only applies to te, pe etc. not admin clients - */ - crm_err("Checking if %s is required/already connected", - client_name); - - table_key = (gpointer)crm_strdup(client_name); - - if(is_set(fsa_input_register, the_subsystem->flag_connected)) { - auth_result = FALSE; - crm_free(table_key); - table_key = NULL; - crm_warn("Bit\t%.16llx set in %.16llx", - the_subsystem->flag_connected, - fsa_input_register); - crm_err("Client %s is already connected", - client_name); - - } else if(FALSE == is_set(fsa_input_register, - the_subsystem->flag_required)) { - crm_warn("Bit\t%.16llx not set in %.16llx", - the_subsystem->flag_connected, - fsa_input_register); - crm_warn("Client %s joined but we dont need it", - client_name); - stop_subsystem(the_subsystem, TRUE); - - } else { - the_subsystem->ipc = curr_client->client_channel; - set_bit_inplace(fsa_input_register, - the_subsystem->flag_connected); - } + /* if we already have one of those clients + * only applies to te, pe etc. not admin clients + */ + crm_err("Checking if %s is required/already connected", client_name); + + table_key = (gpointer) crm_strdup(client_name); + + if (is_set(fsa_input_register, the_subsystem->flag_connected)) { + auth_result = FALSE; + crm_free(table_key); + table_key = NULL; + crm_warn("Bit\t%.16llx set in %.16llx", + the_subsystem->flag_connected, fsa_input_register); + crm_err("Client %s is already connected", client_name); + + } else if (FALSE == is_set(fsa_input_register, the_subsystem->flag_required)) { + crm_warn("Bit\t%.16llx not set in %.16llx", + the_subsystem->flag_connected, fsa_input_register); + crm_warn("Client %s joined but we dont need it", client_name); + stop_subsystem(the_subsystem, TRUE); + + } else { + the_subsystem->ipc = curr_client->client_channel; + set_bit_inplace(fsa_input_register, the_subsystem->flag_connected); + } } else { - table_key = (gpointer)generate_hash_key(client_name, uuid); + table_key = (gpointer) generate_hash_key(client_name, uuid); } - + if (auth_result == TRUE) { - crm_debug_2("Accepted client %s", crm_str(table_key)); - - curr_client->table_key = table_key; - curr_client->sub_sys = crm_strdup(client_name); - curr_client->uuid = crm_strdup(uuid); - - g_hash_table_insert (ipc_clients, - table_key, curr_client->client_channel); - - send_hello_message(curr_client->client_channel, - "n/a", CRM_SYSTEM_CRMD, - "0", "1"); - - crm_debug_3("Updated client list with %s", crm_str(table_key)); - - crm_debug_3("Triggering FSA: %s", __FUNCTION__); - mainloop_set_trigger(fsa_source); - - if(the_subsystem != NULL) { - CRM_CHECK(the_subsystem->client == NULL, - process_client_disconnect(the_subsystem->client)); - the_subsystem->client = curr_client; - } + crm_debug_2("Accepted client %s", crm_str(table_key)); + + curr_client->table_key = table_key; + curr_client->sub_sys = crm_strdup(client_name); + curr_client->uuid = crm_strdup(uuid); + + g_hash_table_insert(ipc_clients, table_key, curr_client->client_channel); + + send_hello_message(curr_client->client_channel, "n/a", CRM_SYSTEM_CRMD, "0", "1"); + + crm_debug_3("Updated client list with %s", crm_str(table_key)); + + crm_debug_3("Triggering FSA: %s", __FUNCTION__); + mainloop_set_trigger(fsa_source); + + if (the_subsystem != NULL) { + CRM_CHECK(the_subsystem->client == NULL, + process_client_disconnect(the_subsystem->client)); + the_subsystem->client = curr_client; + } } else { - crm_free(table_key); - crm_warn("Rejected client logon request"); - curr_client->client_channel->ch_status = IPC_DISC_PENDING; + crm_free(table_key); + crm_warn("Rejected client logon request"); + curr_client->client_channel->ch_status = IPC_DISC_PENDING; } - - if(uuid != NULL) crm_free(uuid); - if(minor_version != NULL) crm_free(minor_version); - if(major_version != NULL) crm_free(major_version); - if(client_name != NULL) crm_free(client_name); + + if (uuid != NULL) + crm_free(uuid); + if (minor_version != NULL) + crm_free(minor_version); + if (major_version != NULL) + crm_free(major_version); + if (client_name != NULL) + crm_free(client_name); /* hello messages should never be processed further */ return FALSE; } enum crmd_fsa_input -handle_message(xmlNode *msg) +handle_message(xmlNode * msg) { const char *type = NULL; + CRM_CHECK(msg != NULL, return I_NULL); - + type = crm_element_value(msg, F_CRM_MSG_TYPE); - if(crm_str_eq(type, XML_ATTR_REQUEST, TRUE)) { - return handle_request(msg); - - } else if(crm_str_eq(type, XML_ATTR_RESPONSE, TRUE)) { - handle_response(msg); - return I_NULL; + if (crm_str_eq(type, XML_ATTR_REQUEST, TRUE)) { + return handle_request(msg); + + } else if (crm_str_eq(type, XML_ATTR_RESPONSE, TRUE)) { + handle_response(msg); + return I_NULL; } - + crm_err("Unknown message type: %s", type); return I_NULL; } static enum crmd_fsa_input -handle_failcount_op(xmlNode *stored_msg) +handle_failcount_op(xmlNode * stored_msg) { const char *rsc = NULL; - xmlNode *xml_rsc = get_xpath_object("//"XML_CIB_TAG_RESOURCE, stored_msg, LOG_ERR); + xmlNode *xml_rsc = get_xpath_object("//" XML_CIB_TAG_RESOURCE, stored_msg, LOG_ERR); - if(xml_rsc) { - rsc = ID(xml_rsc); + if (xml_rsc) { + rsc = ID(xml_rsc); } - - if(rsc) { - char *attr = NULL; - crm_info("Removing failcount for %s", rsc); - attr = crm_concat("fail-count", rsc, '-'); - update_attrd(NULL, attr, NULL, NULL); - crm_free(attr); + if (rsc) { + char *attr = NULL; + + crm_info("Removing failcount for %s", rsc); - attr = crm_concat("last-failure", rsc, '-'); - update_attrd(NULL, attr, NULL, NULL); - crm_free(attr); + attr = crm_concat("fail-count", rsc, '-'); + update_attrd(NULL, attr, NULL, NULL); + crm_free(attr); + + attr = crm_concat("last-failure", rsc, '-'); + update_attrd(NULL, attr, NULL, NULL); + crm_free(attr); } else { - crm_log_xml_warn(stored_msg, "invalid failcount op"); + crm_log_xml_warn(stored_msg, "invalid failcount op"); } - + return I_NULL; } enum crmd_fsa_input -handle_request(xmlNode *stored_msg) +handle_request(xmlNode * stored_msg) { xmlNode *msg = NULL; const char *op = crm_element_value(stored_msg, F_CRM_TASK); /* Optimize this for the DC - it has the most to do */ - if(op == NULL) { - crm_log_xml(LOG_ERR, "Bad message", stored_msg); - return I_NULL; + if (op == NULL) { + crm_log_xml(LOG_ERR, "Bad message", stored_msg); + return I_NULL; } - + /*========== DC-Only Actions ==========*/ - if(AM_I_DC) { - if(strcmp(op, CRM_OP_JOIN_ANNOUNCE) == 0) { - return I_NODE_JOIN; - - } else if(strcmp(op, CRM_OP_JOIN_REQUEST) == 0) { - return I_JOIN_REQUEST; - - } else if(strcmp(op, CRM_OP_JOIN_CONFIRM) == 0) { - return I_JOIN_RESULT; - - } else if(strcmp(op, CRM_OP_SHUTDOWN) == 0) { - const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM); - gboolean dc_match = safe_str_eq(host_from, fsa_our_dc); - if(is_set(fsa_input_register, R_SHUTDOWN)) { - crm_info("Shutting ourselves down (DC)"); - return I_STOP; - - } else if(dc_match) { - crm_err("We didnt ask to be shut down, yet our" - " TE is telling us too." - " Better get out now!"); - return I_TERMINATE; - - } else if(fsa_state != S_STOPPING) { - crm_err("Another node is asking us to shutdown" - " but we think we're ok."); - return I_ELECTION; - } - - } else if(strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) { - /* a slave wants to shut down */ - /* create cib fragment and add to message */ - return handle_shutdown_request(stored_msg); - } + if (AM_I_DC) { + if (strcmp(op, CRM_OP_JOIN_ANNOUNCE) == 0) { + return I_NODE_JOIN; + + } else if (strcmp(op, CRM_OP_JOIN_REQUEST) == 0) { + return I_JOIN_REQUEST; + + } else if (strcmp(op, CRM_OP_JOIN_CONFIRM) == 0) { + return I_JOIN_RESULT; + + } else if (strcmp(op, CRM_OP_SHUTDOWN) == 0) { + const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM); + gboolean dc_match = safe_str_eq(host_from, fsa_our_dc); + + if (is_set(fsa_input_register, R_SHUTDOWN)) { + crm_info("Shutting ourselves down (DC)"); + return I_STOP; + + } else if (dc_match) { + crm_err("We didnt ask to be shut down, yet our" + " TE is telling us too." " Better get out now!"); + return I_TERMINATE; + + } else if (fsa_state != S_STOPPING) { + crm_err("Another node is asking us to shutdown" " but we think we're ok."); + return I_ELECTION; + } + + } else if (strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) { + /* a slave wants to shut down */ + /* create cib fragment and add to message */ + return handle_shutdown_request(stored_msg); + } } - + /*========== common actions ==========*/ - if(strcmp(op, CRM_OP_NOVOTE) == 0) { - ha_msg_input_t fsa_input; - fsa_input.msg = stored_msg; - register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input, - A_ELECTION_COUNT|A_ELECTION_CHECK, FALSE, __FUNCTION__); - - } else if(strcmp(op, CRM_OP_CLEAR_FAILCOUNT) == 0) { - return handle_failcount_op(stored_msg); - - } else if(strcmp(op, CRM_OP_VOTE) == 0) { - /* count the vote and decide what to do after that */ - ha_msg_input_t fsa_input; - fsa_input.msg = stored_msg; - register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input, - A_ELECTION_COUNT|A_ELECTION_CHECK, FALSE, __FUNCTION__); - - /* Sometimes we _must_ go into S_ELECTION */ - if(fsa_state == S_HALT) { - crm_debug("Forcing an election from S_HALT"); - return I_ELECTION; + if (strcmp(op, CRM_OP_NOVOTE) == 0) { + ha_msg_input_t fsa_input; + + fsa_input.msg = stored_msg; + register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input, + A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__); + + } else if (strcmp(op, CRM_OP_CLEAR_FAILCOUNT) == 0) { + return handle_failcount_op(stored_msg); + + } else if (strcmp(op, CRM_OP_VOTE) == 0) { + /* count the vote and decide what to do after that */ + ha_msg_input_t fsa_input; + + fsa_input.msg = stored_msg; + register_fsa_input_adv(C_HA_MESSAGE, I_NULL, &fsa_input, + A_ELECTION_COUNT | A_ELECTION_CHECK, FALSE, __FUNCTION__); + + /* Sometimes we _must_ go into S_ELECTION */ + if (fsa_state == S_HALT) { + crm_debug("Forcing an election from S_HALT"); + return I_ELECTION; #if 0 - } else if(AM_I_DC) { - /* This is the old way of doing things but what is gained? */ - return I_ELECTION; + } else if (AM_I_DC) { + /* This is the old way of doing things but what is gained? */ + return I_ELECTION; #endif - } - - } else if(strcmp(op, CRM_OP_JOIN_OFFER) == 0) { - crm_debug("Raising I_JOIN_OFFER: join-%s", - crm_element_value(stored_msg, F_CRM_JOIN_ID)); - return I_JOIN_OFFER; - - } else if(strcmp(op, CRM_OP_JOIN_ACKNAK) == 0) { - crm_debug("Raising I_JOIN_RESULT: join-%s", - crm_element_value(stored_msg, F_CRM_JOIN_ID)); - return I_JOIN_RESULT; - - } else if(strcmp(op, CRM_OP_LRM_DELETE) == 0 - || strcmp(op, CRM_OP_LRM_FAIL) == 0 - || strcmp(op, CRM_OP_LRM_REFRESH) == 0 - || strcmp(op, CRM_OP_REPROBE) == 0) { - - crm_xml_add(stored_msg, F_CRM_SYS_TO, CRM_SYSTEM_LRMD); - return I_ROUTER; - - } else if(strcmp(op, CRM_OP_NOOP) == 0) { - return I_NULL; - - } else if(strcmp(op, CRM_OP_LOCAL_SHUTDOWN) == 0) { - - crm_shutdown(SIGTERM); - /*return I_SHUTDOWN; */ - return I_NULL; - - /*========== (NOT_DC)-Only Actions ==========*/ - } else if(AM_I_DC == FALSE && strcmp(op, CRM_OP_SHUTDOWN) == 0) { - - const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM); - gboolean dc_match = safe_str_eq(host_from, fsa_our_dc); - - if(dc_match || fsa_our_dc == NULL) { - if(is_set(fsa_input_register, R_SHUTDOWN) == FALSE) { - crm_err("We didn't ask to be shut down, yet our" - " DC is telling us too."); - set_bit_inplace(fsa_input_register, R_STAYDOWN); - return I_STOP; - } - crm_info("Shutting down"); - return I_STOP; - - } else { - crm_warn("Discarding %s op from %s", op, host_from); - } - - } else if(strcmp(op, CRM_OP_PING) == 0) { - /* eventually do some stuff to figure out - * if we /are/ ok - */ - const char *sys_to = crm_element_value(stored_msg, F_CRM_SYS_TO); - xmlNode *ping = createPingAnswerFragment(sys_to, "ok"); - - crm_xml_add(ping, "crmd_state", fsa_state2string(fsa_state)); - - crm_info("Current ping state: %s", fsa_state2string(fsa_state)); - - msg = create_reply(stored_msg, ping); - relay_message(msg, TRUE); - - free_xml(ping); - free_xml(msg); - - /* probably better to do this via signals on the - * local node - */ - } else if(strcmp(op, CRM_OP_DEBUG_UP) == 0) { - alter_debug(DEBUG_INC); - crm_info("Debug set to %d", get_crm_log_level()); - - } else if(strcmp(op, CRM_OP_DEBUG_DOWN) == 0) { - alter_debug(DEBUG_DEC); - crm_info("Debug set to %d", get_crm_log_level()); + } + + } else if (strcmp(op, CRM_OP_JOIN_OFFER) == 0) { + crm_debug("Raising I_JOIN_OFFER: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID)); + return I_JOIN_OFFER; + + } else if (strcmp(op, CRM_OP_JOIN_ACKNAK) == 0) { + crm_debug("Raising I_JOIN_RESULT: join-%s", crm_element_value(stored_msg, F_CRM_JOIN_ID)); + return I_JOIN_RESULT; + + } else if (strcmp(op, CRM_OP_LRM_DELETE) == 0 + || strcmp(op, CRM_OP_LRM_FAIL) == 0 + || strcmp(op, CRM_OP_LRM_REFRESH) == 0 || strcmp(op, CRM_OP_REPROBE) == 0) { + + crm_xml_add(stored_msg, F_CRM_SYS_TO, CRM_SYSTEM_LRMD); + return I_ROUTER; + + } else if (strcmp(op, CRM_OP_NOOP) == 0) { + return I_NULL; + + } else if (strcmp(op, CRM_OP_LOCAL_SHUTDOWN) == 0) { + + crm_shutdown(SIGTERM); + /*return I_SHUTDOWN; */ + return I_NULL; + + /*========== (NOT_DC)-Only Actions ==========*/ + } else if (AM_I_DC == FALSE && strcmp(op, CRM_OP_SHUTDOWN) == 0) { + + const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM); + gboolean dc_match = safe_str_eq(host_from, fsa_our_dc); + + if (dc_match || fsa_our_dc == NULL) { + if (is_set(fsa_input_register, R_SHUTDOWN) == FALSE) { + crm_err("We didn't ask to be shut down, yet our" " DC is telling us too."); + set_bit_inplace(fsa_input_register, R_STAYDOWN); + return I_STOP; + } + crm_info("Shutting down"); + return I_STOP; + + } else { + crm_warn("Discarding %s op from %s", op, host_from); + } + + } else if (strcmp(op, CRM_OP_PING) == 0) { + /* eventually do some stuff to figure out + * if we /are/ ok + */ + const char *sys_to = crm_element_value(stored_msg, F_CRM_SYS_TO); + xmlNode *ping = createPingAnswerFragment(sys_to, "ok"); + + crm_xml_add(ping, "crmd_state", fsa_state2string(fsa_state)); + + crm_info("Current ping state: %s", fsa_state2string(fsa_state)); + + msg = create_reply(stored_msg, ping); + relay_message(msg, TRUE); + + free_xml(ping); + free_xml(msg); + + /* probably better to do this via signals on the + * local node + */ + } else if (strcmp(op, CRM_OP_DEBUG_UP) == 0) { + alter_debug(DEBUG_INC); + crm_info("Debug set to %d", get_crm_log_level()); + + } else if (strcmp(op, CRM_OP_DEBUG_DOWN) == 0) { + alter_debug(DEBUG_DEC); + crm_info("Debug set to %d", get_crm_log_level()); } else { - crm_err("Unexpected request (%s) sent to %s", op, AM_I_DC?"the DC":"non-DC node"); - crm_log_xml(LOG_ERR, "Unexpected", stored_msg); + crm_err("Unexpected request (%s) sent to %s", op, AM_I_DC ? "the DC" : "non-DC node"); + crm_log_xml(LOG_ERR, "Unexpected", stored_msg); } return I_NULL; } void -handle_response(xmlNode *stored_msg) +handle_response(xmlNode * stored_msg) { const char *op = crm_element_value(stored_msg, F_CRM_TASK); - if(op == NULL) { - crm_log_xml(LOG_ERR, "Bad message", stored_msg); - - } else if(AM_I_DC && strcmp(op, CRM_OP_PECALC) == 0) { - /* Check if the PE answer been superceeded by a subsequent request? */ - const char *msg_ref = crm_element_value(stored_msg, XML_ATTR_REFERENCE); - if(msg_ref == NULL) { - crm_err("%s - Ignoring calculation with no reference", op); - - } else if(safe_str_eq(msg_ref, fsa_pe_ref)) { - ha_msg_input_t fsa_input; - fsa_input.msg = stored_msg; - register_fsa_input_later(C_IPC_MESSAGE, I_PE_SUCCESS, &fsa_input); - crm_debug_2("Completed: %s...", fsa_pe_ref); - - } else { - crm_info("%s calculation %s is obsolete", op, msg_ref); - } - - } else if(strcmp(op, CRM_OP_VOTE) == 0 - || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0 - || strcmp(op, CRM_OP_SHUTDOWN) == 0) { - + if (op == NULL) { + crm_log_xml(LOG_ERR, "Bad message", stored_msg); + + } else if (AM_I_DC && strcmp(op, CRM_OP_PECALC) == 0) { + /* Check if the PE answer been superceeded by a subsequent request? */ + const char *msg_ref = crm_element_value(stored_msg, XML_ATTR_REFERENCE); + + if (msg_ref == NULL) { + crm_err("%s - Ignoring calculation with no reference", op); + + } else if (safe_str_eq(msg_ref, fsa_pe_ref)) { + ha_msg_input_t fsa_input; + + fsa_input.msg = stored_msg; + register_fsa_input_later(C_IPC_MESSAGE, I_PE_SUCCESS, &fsa_input); + crm_debug_2("Completed: %s...", fsa_pe_ref); + + } else { + crm_info("%s calculation %s is obsolete", op, msg_ref); + } + + } else if (strcmp(op, CRM_OP_VOTE) == 0 + || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0 || strcmp(op, CRM_OP_SHUTDOWN) == 0) { + } else { - const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM); - crm_err("Unexpected response (op=%s, src=%s) sent to the %s", - op, host_from, AM_I_DC?"DC":"CRMd"); + const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM); + + crm_err("Unexpected response (op=%s, src=%s) sent to the %s", + op, host_from, AM_I_DC ? "DC" : "CRMd"); } } enum crmd_fsa_input -handle_shutdown_request(xmlNode *stored_msg) +handle_shutdown_request(xmlNode * stored_msg) { /* handle here to avoid potential version issues * where the shutdown message/proceedure may have * been changed in later versions. * * This way the DC is always in control of the shutdown */ - + char *now_s = NULL; time_t now = time(NULL); xmlNode *node_state = NULL; const char *host_from = crm_element_value(stored_msg, F_CRM_HOST_FROM); - if(host_from == NULL) { - /* we're shutting down and the DC */ - host_from = fsa_our_uname; + if (host_from == NULL) { + /* we're shutting down and the DC */ + host_from = fsa_our_uname; } - - crm_info("Creating shutdown request for %s (state=%s)", - host_from, fsa_state2string(fsa_state)); + + crm_info("Creating shutdown request for %s (state=%s)", host_from, fsa_state2string(fsa_state)); crm_log_xml(LOG_MSG, "message", stored_msg); - node_state = create_node_state( - host_from, NULL, NULL, NULL, NULL, - CRMD_STATE_INACTIVE, FALSE, __FUNCTION__); - + node_state = create_node_state(host_from, NULL, NULL, NULL, NULL, + CRMD_STATE_INACTIVE, FALSE, __FUNCTION__); + fsa_cib_anon_update(XML_CIB_TAG_STATUS, node_state, cib_quorum_override); crm_log_xml_debug_2(node_state, "Shutdown update"); free_xml(node_state); now_s = crm_itoa(now); update_attrd(host_from, XML_CIB_ATTR_SHUTDOWN, now_s, NULL); crm_free(now_s); - + /* will be picked up by the TE as long as its running */ return I_NULL; } /* msg is deleted by the time this returns */ -extern gboolean process_te_message(xmlNode *msg, xmlNode *xml_data); +extern gboolean process_te_message(xmlNode * msg, xmlNode * xml_data); gboolean -send_msg_via_ipc(xmlNode *msg, const char *sys) +send_msg_via_ipc(xmlNode * msg, const char *sys) { gboolean send_ok = TRUE; IPC_Channel *client_channel; - - client_channel = (IPC_Channel*)g_hash_table_lookup(ipc_clients, sys); - if(crm_element_value(msg, F_CRM_HOST_FROM) == NULL) { - crm_xml_add(msg, F_CRM_HOST_FROM, fsa_our_uname); + client_channel = (IPC_Channel *) g_hash_table_lookup(ipc_clients, sys); + + if (crm_element_value(msg, F_CRM_HOST_FROM) == NULL) { + crm_xml_add(msg, F_CRM_HOST_FROM, fsa_our_uname); } - + if (client_channel != NULL) { - crm_debug_3("Sending message via channel %s.", sys); - send_ok = send_ipc_message(client_channel, msg); - - } else if(sys != NULL && strcmp(sys, CRM_SYSTEM_TENGINE) == 0) { - xmlNode *data = get_message_xml(msg, F_CRM_DATA); - process_te_message(msg, data); - - } else if(sys != NULL && strcmp(sys, CRM_SYSTEM_LRMD) == 0) { - fsa_data_t fsa_data; - ha_msg_input_t fsa_input; - - fsa_input.msg = msg; - fsa_input.xml = get_message_xml(msg, F_CRM_DATA); - - fsa_data.id = 0; - fsa_data.actions = 0; - fsa_data.data = &fsa_input; - fsa_data.fsa_input = I_MESSAGE; - fsa_data.fsa_cause = C_IPC_MESSAGE; - fsa_data.origin = __FUNCTION__; - fsa_data.data_type = fsa_dt_ha_msg; - + crm_debug_3("Sending message via channel %s.", sys); + send_ok = send_ipc_message(client_channel, msg); + + } else if (sys != NULL && strcmp(sys, CRM_SYSTEM_TENGINE) == 0) { + xmlNode *data = get_message_xml(msg, F_CRM_DATA); + + process_te_message(msg, data); + + } else if (sys != NULL && strcmp(sys, CRM_SYSTEM_LRMD) == 0) { + fsa_data_t fsa_data; + ha_msg_input_t fsa_input; + + fsa_input.msg = msg; + fsa_input.xml = get_message_xml(msg, F_CRM_DATA); + + fsa_data.id = 0; + fsa_data.actions = 0; + fsa_data.data = &fsa_input; + fsa_data.fsa_input = I_MESSAGE; + fsa_data.fsa_cause = C_IPC_MESSAGE; + fsa_data.origin = __FUNCTION__; + fsa_data.data_type = fsa_dt_ha_msg; + #ifdef FSA_TRACE - crm_debug_2("Invoking action A_LRM_INVOKE (%.16llx)", A_LRM_INVOKE); + crm_debug_2("Invoking action A_LRM_INVOKE (%.16llx)", A_LRM_INVOKE); #endif - do_lrm_invoke(A_LRM_INVOKE, C_IPC_MESSAGE, fsa_state, I_MESSAGE, &fsa_data); - + do_lrm_invoke(A_LRM_INVOKE, C_IPC_MESSAGE, fsa_state, I_MESSAGE, &fsa_data); + } else { - crm_err("Unknown Sub-system (%s)... discarding message.", - crm_str(sys)); - send_ok = FALSE; - } + crm_err("Unknown Sub-system (%s)... discarding message.", crm_str(sys)); + send_ok = FALSE; + } return send_ok; -} - +} void -msg_queue_helper(void) +msg_queue_helper(void) { #if SUPPORT_HEARTBEAT IPC_Channel *ipc = NULL; - if(fsa_cluster_conn != NULL) { - ipc = fsa_cluster_conn->llc_ops->ipcchan( - fsa_cluster_conn); + + if (fsa_cluster_conn != NULL) { + ipc = fsa_cluster_conn->llc_ops->ipcchan(fsa_cluster_conn); } - if(ipc != NULL) { - ipc->ops->resume_io(ipc); + if (ipc != NULL) { + ipc->ops->resume_io(ipc); } /* g_hash_table_foreach_remove(ipc_clients, ipc_queue_helper, NULL); */ #endif } - gboolean -ipc_queue_helper(gpointer key, gpointer value, gpointer user_data) +ipc_queue_helper(gpointer key, gpointer value, gpointer user_data) { crmd_client_t *ipc_client = value; - if(ipc_client->client_channel != NULL) { - ipc_client->client_channel->ops->is_message_pending(ipc_client->client_channel); + + if (ipc_client->client_channel != NULL) { + ipc_client->client_channel->ops->is_message_pending(ipc_client->client_channel); } return FALSE; } diff --git a/crmd/misc.c b/crmd/misc.c index 18d2cae40a..c04053582c 100644 --- a/crmd/misc.c +++ b/crmd/misc.c @@ -1,73 +1,72 @@ /* * 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 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 #include #include #include #include #include #include /* A_LOG, A_WARN, A_ERROR */ void do_log(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) + enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - unsigned log_type = LOG_DEBUG_3; + unsigned log_type = LOG_DEBUG_3; - if(action & A_LOG) { - log_type = LOG_DEBUG_2; - } else if(action & A_WARN) { - log_type = LOG_WARNING; - } else if(action & A_ERROR) { - log_type = LOG_ERR; - } - - do_crm_log(log_type, - "FSA: Input %s from %s() received in state %s", - fsa_input2string(msg_data->fsa_input), - msg_data->origin, - fsa_state2string(cur_state)); - - if(msg_data->data_type == fsa_dt_ha_msg) { - ha_msg_input_t *input = fsa_typed_data(msg_data->data_type); - if(log_type > LOG_DEBUG) { - crm_log_xml(log_type, "input", input->msg); - } - - } else if(msg_data->data_type == fsa_dt_xml) { - xmlNode *input = fsa_typed_data(msg_data->data_type); - if(crm_log_level >= log_type) { - do_crm_log_xml(log_type, __FUNCTION__, input); - } + if (action & A_LOG) { + log_type = LOG_DEBUG_2; + } else if (action & A_WARN) { + log_type = LOG_WARNING; + } else if (action & A_ERROR) { + log_type = LOG_ERR; + } - } else if(msg_data->data_type == fsa_dt_lrm) { - lrm_op_t *input = fsa_typed_data(msg_data->data_type); - do_crm_log(log_type, - "Resource %s: Call ID %d returned %d (%d)." - " New status if rc=0: %s", - input->rsc_id, input->call_id, input->rc, - input->op_status, (char*)input->user_data); - } -} + do_crm_log(log_type, + "FSA: Input %s from %s() received in state %s", + fsa_input2string(msg_data->fsa_input), + msg_data->origin, fsa_state2string(cur_state)); + + if (msg_data->data_type == fsa_dt_ha_msg) { + ha_msg_input_t *input = fsa_typed_data(msg_data->data_type); + + if (log_type > LOG_DEBUG) { + crm_log_xml(log_type, "input", input->msg); + } + + } else if (msg_data->data_type == fsa_dt_xml) { + xmlNode *input = fsa_typed_data(msg_data->data_type); + if (crm_log_level >= log_type) { + do_crm_log_xml(log_type, __FUNCTION__, input); + } + + } else if (msg_data->data_type == fsa_dt_lrm) { + lrm_op_t *input = fsa_typed_data(msg_data->data_type); + + do_crm_log(log_type, + "Resource %s: Call ID %d returned %d (%d)." + " New status if rc=0: %s", + input->rsc_id, input->call_id, input->rc, + input->op_status, (char *)input->user_data); + } +} diff --git a/crmd/pengine.c b/crmd/pengine.c index f9585e8ea2..e5fda48b14 100644 --- a/crmd/pengine.c +++ b/crmd/pengine.c @@ -1,342 +1,323 @@ /* * 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 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 #include #include #include #include #include -#include /* for access */ +#include /* for access */ +#include /* for calls to open */ +#include /* for calls to open */ +#include /* for calls to open */ +#include /* for getpwuid */ +#include /* for initgroups */ - -#include /* for calls to open */ -#include /* for calls to open */ -#include /* for calls to open */ -#include /* for getpwuid */ -#include /* for initgroups */ - -#include /* for getrlimit */ -#include /* for getrlimit */ +#include /* for getrlimit */ +#include /* for getrlimit */ #include #include #include #include #include #include #include #include - static GCHSource *pe_source = NULL; -struct crm_subsystem_s *pe_subsystem = NULL; -void do_pe_invoke_callback(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data); - +struct crm_subsystem_s *pe_subsystem = NULL; +void do_pe_invoke_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data); static void -save_cib_contents(xmlNode *msg, int call_id, int rc, xmlNode *output, void *user_data) +save_cib_contents(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { char *id = user_data; + register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__); CRM_CHECK(id != NULL, return); - if(rc == cib_ok) { - int len = 15; - char *filename = NULL; - - len += strlen(id); - len += strlen(PE_STATE_DIR); + if (rc == cib_ok) { + int len = 15; + char *filename = NULL; + + len += strlen(id); + len += strlen(PE_STATE_DIR); - crm_malloc0(filename, len); - CRM_CHECK(filename != NULL, return); + crm_malloc0(filename, len); + CRM_CHECK(filename != NULL, return); - sprintf(filename, PE_STATE_DIR "/pe-core-%s.bz2", id); - if(write_xml_file(output, filename, TRUE) < 0) { - crm_err("Could not save CIB contents after PE crash to %s", filename); - } else { - crm_notice("Saved CIB contents after PE crash to %s", filename); - } + sprintf(filename, PE_STATE_DIR "/pe-core-%s.bz2", id); + if (write_xml_file(output, filename, TRUE) < 0) { + crm_err("Could not save CIB contents after PE crash to %s", filename); + } else { + crm_notice("Saved CIB contents after PE crash to %s", filename); + } - crm_free(filename); + crm_free(filename); } - + crm_free(id); } static void pe_connection_destroy(gpointer user_data) { pe_source = NULL; clear_bit_inplace(fsa_input_register, pe_subsystem->flag_connected); - if(is_set(fsa_input_register, pe_subsystem->flag_required)) { - int rc = cib_ok; - cl_uuid_t new_uuid; - char uuid_str[UU_UNPARSE_SIZEOF]; - - cl_uuid_generate(&new_uuid); - cl_uuid_unparse(&new_uuid, uuid_str); - - crm_crit("Connection to the Policy Engine failed (pid=%d, uuid=%s)", - pe_subsystem->pid, uuid_str); - - /* - *The PE died... - * - * Save the current CIB so that we have a chance of - * figuring out what killed it. - * - * Delay raising the I_ERROR until the query below completes or - * 5s is up, whichever comes first. - * - */ - rc = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local); - fsa_cib_conn->cmds->register_callback( - fsa_cib_conn, rc, 5, FALSE, crm_strdup(uuid_str), - "save_cib_contents", save_cib_contents); - + if (is_set(fsa_input_register, pe_subsystem->flag_required)) { + int rc = cib_ok; + cl_uuid_t new_uuid; + char uuid_str[UU_UNPARSE_SIZEOF]; + + cl_uuid_generate(&new_uuid); + cl_uuid_unparse(&new_uuid, uuid_str); + + crm_crit("Connection to the Policy Engine failed (pid=%d, uuid=%s)", + pe_subsystem->pid, uuid_str); + + /* + *The PE died... + * + * Save the current CIB so that we have a chance of + * figuring out what killed it. + * + * Delay raising the I_ERROR until the query below completes or + * 5s is up, whichever comes first. + * + */ + rc = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local); + fsa_cib_conn->cmds->register_callback(fsa_cib_conn, rc, 5, FALSE, crm_strdup(uuid_str), + "save_cib_contents", save_cib_contents); + } else { - crm_info("Connection to the Policy Engine released"); + crm_info("Connection to the Policy Engine released"); } - + pe_subsystem->pid = -1; pe_subsystem->ipc = NULL; pe_subsystem->client = NULL; mainloop_set_trigger(fsa_source); return; } static gboolean -pe_msg_dispatch(IPC_Channel *client, gpointer user_data) +pe_msg_dispatch(IPC_Channel * client, gpointer user_data) { xmlNode *msg = NULL; gboolean stay_connected = TRUE; - - while(IPC_ISRCONN(client) - && client->ops->is_message_pending(client)) { - - msg = xmlfromIPC(client, MAX_IPC_DELAY); - if (msg != NULL) { - route_message(C_IPC_MESSAGE, msg); - free_xml(msg); - } + + while (IPC_ISRCONN(client) + && client->ops->is_message_pending(client)) { + + msg = xmlfromIPC(client, MAX_IPC_DELAY); + if (msg != NULL) { + route_message(C_IPC_MESSAGE, msg); + free_xml(msg); + } } - + if (client->ch_status != IPC_CONNECT) { - crm_info("Received HUP from %s:[%d]", pe_subsystem->name, pe_subsystem->pid); - stay_connected = FALSE; + crm_info("Received HUP from %s:[%d]", pe_subsystem->name, pe_subsystem->pid); + stay_connected = FALSE; } mainloop_set_trigger(fsa_source); return stay_connected; } /* A_PE_START, A_PE_STOP, A_TE_RESTART */ void do_pe_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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { struct crm_subsystem_s *this_subsys = pe_subsystem; long long stop_actions = A_PE_STOP; long long start_actions = A_PE_START; - - if(action & stop_actions) { - clear_bit_inplace(fsa_input_register, pe_subsystem->flag_required); - - if(is_heartbeat_cluster()) { - stop_subsystem(this_subsys, FALSE); - - } else { - if(pe_source) { - G_main_del_IPC_Channel(pe_source); - pe_source = NULL; - } - - if(pe_subsystem->ipc) { - pe_subsystem->ipc->ops->destroy(pe_subsystem->ipc); - pe_subsystem->ipc = NULL; - } - clear_bit_inplace(fsa_input_register, pe_subsystem->flag_connected); - } + + if (action & stop_actions) { + clear_bit_inplace(fsa_input_register, pe_subsystem->flag_required); + + if (is_heartbeat_cluster()) { + stop_subsystem(this_subsys, FALSE); + + } else { + if (pe_source) { + G_main_del_IPC_Channel(pe_source); + pe_source = NULL; + } + + if (pe_subsystem->ipc) { + pe_subsystem->ipc->ops->destroy(pe_subsystem->ipc); + pe_subsystem->ipc = NULL; + } + clear_bit_inplace(fsa_input_register, pe_subsystem->flag_connected); + } } - - if(action & start_actions) { - if(cur_state != S_STOPPING) { - if(is_openais_cluster()) { - set_bit_inplace(fsa_input_register, pe_subsystem->flag_required); - - } else if(is_heartbeat_cluster()) { - if(start_subsystem(this_subsys) == FALSE) { - register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); - return; - } - sleep(4); - } - - pe_subsystem->ipc = init_client_ipc_comms_nodispatch(CRM_SYSTEM_PENGINE); - if(pe_subsystem->ipc == NULL) { - crm_warn("Setup of client connection failed," - " not adding channel to mainloop"); - register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); - return; - } - - if(is_openais_cluster()) { - pe_subsystem->pid = pe_subsystem->ipc->farside_pid;; - } - - set_bit_inplace(fsa_input_register, pe_subsystem->flag_connected); - pe_source = G_main_add_IPC_Channel( - G_PRIORITY_HIGH, pe_subsystem->ipc, FALSE, pe_msg_dispatch, NULL, - pe_connection_destroy); - - } else { - crm_info("Ignoring request to start %s while shutting down", - this_subsys->name); - } + + if (action & start_actions) { + if (cur_state != S_STOPPING) { + if (is_openais_cluster()) { + set_bit_inplace(fsa_input_register, pe_subsystem->flag_required); + + } else if (is_heartbeat_cluster()) { + if (start_subsystem(this_subsys) == FALSE) { + register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); + return; + } + sleep(4); + } + + pe_subsystem->ipc = init_client_ipc_comms_nodispatch(CRM_SYSTEM_PENGINE); + if (pe_subsystem->ipc == NULL) { + crm_warn("Setup of client connection failed," " not adding channel to mainloop"); + register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); + return; + } + + if (is_openais_cluster()) { + pe_subsystem->pid = pe_subsystem->ipc->farside_pid;; + } + + set_bit_inplace(fsa_input_register, pe_subsystem->flag_connected); + pe_source = + G_main_add_IPC_Channel(G_PRIORITY_HIGH, pe_subsystem->ipc, FALSE, pe_msg_dispatch, + NULL, pe_connection_destroy); + + } else { + crm_info("Ignoring request to start %s while shutting down", this_subsys->name); + } } } int fsa_pe_query = 0; char *fsa_pe_ref = NULL; /* A_PE_INVOKE */ void do_pe_invoke(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - if(AM_I_DC == FALSE) { - crm_err("Not DC: No need to invoke the PE (anymore): %s", - fsa_action2string(action)); - return; - } - - if(is_set(fsa_input_register, R_PE_CONNECTED) == FALSE){ - if(is_set(fsa_input_register, R_SHUTDOWN)) { - crm_err("Cannot shut down gracefully without the PE"); - register_fsa_input_before(C_FSA_INTERNAL, I_TERMINATE, NULL); - - } else { - crm_info("Waiting for the PE to connect"); - crmd_fsa_stall(NULL); - register_fsa_action(A_PE_START); - } - return; - } - - if(is_set(fsa_input_register, R_HAVE_CIB) == FALSE) { - crm_err("Attempted to invoke the PE without a consistent" - " copy of the CIB!"); - - /* start the join from scratch */ - register_fsa_input_before(C_FSA_INTERNAL, I_ELECTION, NULL); - return; - } - - fsa_pe_query = fsa_cib_conn->cmds->query( - fsa_cib_conn, NULL, NULL, cib_scope_local); - - crm_info("Query %d: Requesting the current CIB: %s", fsa_pe_query, fsa_state2string(fsa_state)); - - /* Make sure any queued calculations are discarded */ - crm_free(fsa_pe_ref); - fsa_pe_ref = NULL; - - fsa_cib_conn->cmds->register_callback( - fsa_cib_conn, fsa_pe_query, 60, FALSE, NULL, - "do_pe_invoke_callback", do_pe_invoke_callback); + if (AM_I_DC == FALSE) { + crm_err("Not DC: No need to invoke the PE (anymore): %s", fsa_action2string(action)); + return; + } + + if (is_set(fsa_input_register, R_PE_CONNECTED) == FALSE) { + if (is_set(fsa_input_register, R_SHUTDOWN)) { + crm_err("Cannot shut down gracefully without the PE"); + register_fsa_input_before(C_FSA_INTERNAL, I_TERMINATE, NULL); + + } else { + crm_info("Waiting for the PE to connect"); + crmd_fsa_stall(NULL); + register_fsa_action(A_PE_START); + } + return; + } + + if (is_set(fsa_input_register, R_HAVE_CIB) == FALSE) { + crm_err("Attempted to invoke the PE without a consistent" " copy of the CIB!"); + + /* start the join from scratch */ + register_fsa_input_before(C_FSA_INTERNAL, I_ELECTION, NULL); + return; + } + + fsa_pe_query = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local); + + crm_info("Query %d: Requesting the current CIB: %s", fsa_pe_query, fsa_state2string(fsa_state)); + + /* Make sure any queued calculations are discarded */ + crm_free(fsa_pe_ref); + fsa_pe_ref = NULL; + + fsa_cib_conn->cmds->register_callback(fsa_cib_conn, fsa_pe_query, 60, FALSE, NULL, + "do_pe_invoke_callback", do_pe_invoke_callback); } void -do_pe_invoke_callback(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +do_pe_invoke_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - xmlNode *cmd = NULL; - - if(rc != cib_ok) { - crm_err("Cant retrieve the CIB: %s", cib_error2string(rc)); - register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__); - return; - - } else if(call_id != fsa_pe_query) { - crm_debug_2("Skipping superceeded CIB query: %d (current=%d)", - call_id, fsa_pe_query); - return; - - } else if(AM_I_DC == FALSE - || is_set(fsa_input_register, R_PE_CONNECTED) == FALSE) { - crm_debug("No need to invoke the PE anymore"); - return; - - } else if(fsa_state != S_POLICY_ENGINE) { - crm_debug("Discarding PE request in state: %s", - fsa_state2string(fsa_state)); - return; - - } else if(last_peer_update != 0) { - crm_debug("Re-asking for the CIB: peer update %d still pending", - last_peer_update); - - sleep(1); - register_fsa_action(A_PE_INVOKE); - return; - - } else if(fsa_state != S_POLICY_ENGINE) { - crm_err("Invoking PE in state: %s", fsa_state2string(fsa_state)); - return; - } - - CRM_LOG_ASSERT(output != NULL); - - crm_xml_add(output, XML_ATTR_DC_UUID, fsa_our_uuid); - crm_xml_add_int(output, XML_ATTR_HAVE_QUORUM, fsa_has_quorum); - - if(ever_had_quorum && crm_have_quorum == FALSE) { - crm_xml_add_int(output, XML_ATTR_QUORUM_PANIC, 1); - } - - cmd = create_request(CRM_OP_PECALC, output, NULL, - CRM_SYSTEM_PENGINE, CRM_SYSTEM_DC, NULL); - - crm_free(fsa_pe_ref); - fsa_pe_ref = crm_element_value_copy(cmd, XML_ATTR_REFERENCE); - - if(send_ipc_message(pe_subsystem->ipc, cmd) == FALSE) { - crm_err("Could not contact the pengine"); - register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__); - } - - crm_info("Invoking the PE: query=%d, ref=%s, seq=%llu, quorate=%d", - fsa_pe_query, fsa_pe_ref, crm_peer_seq, fsa_has_quorum); - free_xml(cmd); + xmlNode *cmd = NULL; + + if (rc != cib_ok) { + crm_err("Cant retrieve the CIB: %s", cib_error2string(rc)); + register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__); + return; + + } else if (call_id != fsa_pe_query) { + crm_debug_2("Skipping superceeded CIB query: %d (current=%d)", call_id, fsa_pe_query); + return; + + } else if (AM_I_DC == FALSE || is_set(fsa_input_register, R_PE_CONNECTED) == FALSE) { + crm_debug("No need to invoke the PE anymore"); + return; + + } else if (fsa_state != S_POLICY_ENGINE) { + crm_debug("Discarding PE request in state: %s", fsa_state2string(fsa_state)); + return; + + } else if (last_peer_update != 0) { + crm_debug("Re-asking for the CIB: peer update %d still pending", last_peer_update); + + sleep(1); + register_fsa_action(A_PE_INVOKE); + return; + + } else if (fsa_state != S_POLICY_ENGINE) { + crm_err("Invoking PE in state: %s", fsa_state2string(fsa_state)); + return; + } + + CRM_LOG_ASSERT(output != NULL); + + crm_xml_add(output, XML_ATTR_DC_UUID, fsa_our_uuid); + crm_xml_add_int(output, XML_ATTR_HAVE_QUORUM, fsa_has_quorum); + + if (ever_had_quorum && crm_have_quorum == FALSE) { + crm_xml_add_int(output, XML_ATTR_QUORUM_PANIC, 1); + } + + cmd = create_request(CRM_OP_PECALC, output, NULL, CRM_SYSTEM_PENGINE, CRM_SYSTEM_DC, NULL); + + crm_free(fsa_pe_ref); + fsa_pe_ref = crm_element_value_copy(cmd, XML_ATTR_REFERENCE); + + if (send_ipc_message(pe_subsystem->ipc, cmd) == FALSE) { + crm_err("Could not contact the pengine"); + register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__); + } + + crm_info("Invoking the PE: query=%d, ref=%s, seq=%llu, quorate=%d", + fsa_pe_query, fsa_pe_ref, crm_peer_seq, fsa_has_quorum); + free_xml(cmd); } diff --git a/crmd/subsystems.c b/crmd/subsystems.c index 4a12adf7a5..6857bf3951 100644 --- a/crmd/subsystems.c +++ b/crmd/subsystems.c @@ -1,234 +1,228 @@ /* * 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 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 -#include /* for access */ -#include /* for calls to open */ -#include /* for calls to open */ -#include /* for calls to open */ -#include /* for getpwuid */ -#include /* for initgroups */ +#include /* for access */ +#include /* for calls to open */ +#include /* for calls to open */ +#include /* for calls to open */ +#include /* for getpwuid */ +#include /* for initgroups */ #include #include -#include /* for getrlimit */ +#include /* for getrlimit */ #include #include -#include /* for getrlimit */ +#include /* for getrlimit */ #include #include #include #include #include #include #include #include #include #include static void -crmdManagedChildRegistered(ProcTrack* p) +crmdManagedChildRegistered(ProcTrack * p) { - struct crm_subsystem_s *the_subsystem = p->privatedata; - the_subsystem->pid = p->pid; + struct crm_subsystem_s *the_subsystem = p->privatedata; + + the_subsystem->pid = p->pid; } static void -crmdManagedChildDied( - ProcTrack* p, int status, int signo, int exitcode, int waslogged) +crmdManagedChildDied(ProcTrack * p, int status, int signo, int exitcode, int waslogged) { - struct crm_subsystem_s *the_subsystem = p->privatedata; - - crm_info("Process %s:[%d] exited (signal=%d, exitcode=%d)", - the_subsystem->name, the_subsystem->pid, signo, exitcode); + struct crm_subsystem_s *the_subsystem = p->privatedata; + + crm_info("Process %s:[%d] exited (signal=%d, exitcode=%d)", + the_subsystem->name, the_subsystem->pid, signo, exitcode); #if 0 - /* everything below is now handled in pe_connection_destroy() */ - the_subsystem->pid = -1; - the_subsystem->ipc = NULL; - clear_bit_inplace(fsa_input_register, the_subsystem->flag_connected); - - crm_debug_3("Triggering FSA: %s", __FUNCTION__); - mainloop_set_trigger(fsa_source); - - if(is_set(fsa_input_register, the_subsystem->flag_required)) { - /* this wasnt supposed to happen */ - crm_warn("The %s subsystem terminated unexpectedly", - the_subsystem->name); - - if(the_subsystem->flag_connected == R_PE_CONNECTED) { - int rc = cib_ok; - char *pid = crm_itoa(the_subsystem->pid); - - /* the PE died... - * save the current CIB so that we have a chance of - * figuring out what killed it - */ - rc = fsa_cib_conn->cmds->query( - fsa_cib_conn, NULL, NULL, cib_scope_local); - add_cib_op_callback(fsa_cib_conn, rc, TRUE, pid, save_cib_contents); - } - - register_fsa_input_before(C_FSA_INTERNAL, I_ERROR, NULL); - } + /* everything below is now handled in pe_connection_destroy() */ + the_subsystem->pid = -1; + the_subsystem->ipc = NULL; + clear_bit_inplace(fsa_input_register, the_subsystem->flag_connected); + + crm_debug_3("Triggering FSA: %s", __FUNCTION__); + mainloop_set_trigger(fsa_source); + + if (is_set(fsa_input_register, the_subsystem->flag_required)) { + /* this wasnt supposed to happen */ + crm_warn("The %s subsystem terminated unexpectedly", the_subsystem->name); + + if (the_subsystem->flag_connected == R_PE_CONNECTED) { + int rc = cib_ok; + char *pid = crm_itoa(the_subsystem->pid); + + /* the PE died... + * save the current CIB so that we have a chance of + * figuring out what killed it + */ + rc = fsa_cib_conn->cmds->query(fsa_cib_conn, NULL, NULL, cib_scope_local); + add_cib_op_callback(fsa_cib_conn, rc, TRUE, pid, save_cib_contents); + } + + register_fsa_input_before(C_FSA_INTERNAL, I_ERROR, NULL); + } #endif - p->privatedata = NULL; + p->privatedata = NULL; } static const char * -crmdManagedChildName(ProcTrack* p) +crmdManagedChildName(ProcTrack * p) { - struct crm_subsystem_s *the_subsystem = p->privatedata; - return the_subsystem->name; + struct crm_subsystem_s *the_subsystem = p->privatedata; + + return the_subsystem->name; } static ProcTrack_ops crmd_managed_child_ops = { - crmdManagedChildDied, - crmdManagedChildRegistered, - crmdManagedChildName + crmdManagedChildDied, + crmdManagedChildRegistered, + crmdManagedChildName }; gboolean stop_subsystem(struct crm_subsystem_s *the_subsystem, gboolean force_quit) { - int quit_signal = SIGTERM; - crm_debug_2("Stopping sub-system \"%s\"", the_subsystem->name); - clear_bit_inplace(fsa_input_register, the_subsystem->flag_required); - - if (the_subsystem->pid <= 0) { - crm_debug_2("Client %s not running", the_subsystem->name); - return FALSE; - - } + int quit_signal = SIGTERM; - if(is_set(fsa_input_register, the_subsystem->flag_connected) == FALSE) { - /* running but not yet connected */ - crm_debug("Stopping %s before it had connected", - the_subsystem->name); - } + crm_debug_2("Stopping sub-system \"%s\"", the_subsystem->name); + clear_bit_inplace(fsa_input_register, the_subsystem->flag_required); + + if (the_subsystem->pid <= 0) { + crm_debug_2("Client %s not running", the_subsystem->name); + return FALSE; + + } + + if (is_set(fsa_input_register, the_subsystem->flag_connected) == FALSE) { + /* running but not yet connected */ + crm_debug("Stopping %s before it had connected", the_subsystem->name); + } /* if(force_quit && the_subsystem->sent_kill == FALSE) { quit_signal = SIGKILL; } else if(force_quit) { crm_debug("Already sent -KILL to %s: [%d]", the_subsystem->name, the_subsystem->pid); } */ - errno = 0; - if(kill(the_subsystem->pid, quit_signal) == 0) { - crm_info("Sent -TERM to %s: [%d]", - the_subsystem->name, the_subsystem->pid); - the_subsystem->sent_kill = TRUE; - - } else { - crm_perror(LOG_ERR,"Sent -TERM to %s: [%d]", - the_subsystem->name, the_subsystem->pid); - } - - return TRUE; -} + errno = 0; + if (kill(the_subsystem->pid, quit_signal) == 0) { + crm_info("Sent -TERM to %s: [%d]", the_subsystem->name, the_subsystem->pid); + the_subsystem->sent_kill = TRUE; + + } else { + crm_perror(LOG_ERR, "Sent -TERM to %s: [%d]", the_subsystem->name, the_subsystem->pid); + } + return TRUE; +} gboolean -start_subsystem(struct crm_subsystem_s* the_subsystem) +start_subsystem(struct crm_subsystem_s * the_subsystem) { - pid_t pid; - struct stat buf; - int s_res; - unsigned int j; - struct rlimit oflimits; - const char *devnull = "/dev/null"; - - crm_info("Starting sub-system \"%s\"", the_subsystem->name); - set_bit_inplace(fsa_input_register, the_subsystem->flag_required); - - if (the_subsystem->pid > 0) { - crm_warn("Client %s already running as pid %d", - the_subsystem->name, (int) the_subsystem->pid); - - /* starting a started X is not an error */ - return TRUE; - } - - /* - * We want to ensure that the exec will succeed before - * we bother forking. - */ - - if (access(the_subsystem->path, F_OK|X_OK) != 0) { - crm_perror(LOG_ERR,"Cannot (access) exec %s", the_subsystem->path); - return FALSE; - } - - s_res = stat(the_subsystem->command, &buf); - if(s_res != 0) { - crm_perror(LOG_ERR,"Cannot (stat) exec %s", the_subsystem->command); - return FALSE; - } - - /* We need to fork so we can make child procs not real time */ - switch(pid=fork()) { - case -1: - crm_err("Cannot fork."); - return FALSE; - - default: /* Parent */ - NewTrackedProc(pid, 0, PT_LOGNORMAL, - the_subsystem, &crmd_managed_child_ops); - crm_debug_2("Client %s is has pid: %d", - the_subsystem->name, pid); - the_subsystem->pid = pid; - return TRUE; - - case 0: /* Child */ - /* create a new process group to avoid - * being interupted by heartbeat - */ - setpgid(0, 0); - break; - } - - crm_debug("Executing \"%s (%s)\" (pid %d)", - the_subsystem->command, the_subsystem->name, (int) getpid()); - - /* A precautionary measure */ - getrlimit(RLIMIT_NOFILE, &oflimits); - for (j=0; j < oflimits.rlim_cur; ++j) { - close(j); - } - - (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */ - (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */ - (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */ - - { - char *opts[] = { crm_strdup(the_subsystem->command), NULL }; - (void)execvp(the_subsystem->command, opts); - } - - /* Should not happen */ - crm_perror(LOG_ERR,"FATAL: Cannot exec %s", the_subsystem->command); - - exit(100); /* Suppress respawning */ - return TRUE; /* never reached */ + pid_t pid; + struct stat buf; + int s_res; + unsigned int j; + struct rlimit oflimits; + const char *devnull = "/dev/null"; + + crm_info("Starting sub-system \"%s\"", the_subsystem->name); + set_bit_inplace(fsa_input_register, the_subsystem->flag_required); + + if (the_subsystem->pid > 0) { + crm_warn("Client %s already running as pid %d", + the_subsystem->name, (int)the_subsystem->pid); + + /* starting a started X is not an error */ + return TRUE; + } + + /* + * We want to ensure that the exec will succeed before + * we bother forking. + */ + + if (access(the_subsystem->path, F_OK | X_OK) != 0) { + crm_perror(LOG_ERR, "Cannot (access) exec %s", the_subsystem->path); + return FALSE; + } + + s_res = stat(the_subsystem->command, &buf); + if (s_res != 0) { + crm_perror(LOG_ERR, "Cannot (stat) exec %s", the_subsystem->command); + return FALSE; + } + + /* We need to fork so we can make child procs not real time */ + switch (pid = fork()) { + case -1: + crm_err("Cannot fork."); + return FALSE; + + default: /* Parent */ + NewTrackedProc(pid, 0, PT_LOGNORMAL, the_subsystem, &crmd_managed_child_ops); + crm_debug_2("Client %s is has pid: %d", the_subsystem->name, pid); + the_subsystem->pid = pid; + return TRUE; + + case 0: /* Child */ + /* create a new process group to avoid + * being interupted by heartbeat + */ + setpgid(0, 0); + break; + } + + crm_debug("Executing \"%s (%s)\" (pid %d)", + the_subsystem->command, the_subsystem->name, (int)getpid()); + + /* A precautionary measure */ + getrlimit(RLIMIT_NOFILE, &oflimits); + for (j = 0; j < oflimits.rlim_cur; ++j) { + close(j); + } + + (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */ + (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */ + (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */ + + { + char *opts[] = { crm_strdup(the_subsystem->command), NULL }; + (void)execvp(the_subsystem->command, opts); + } + + /* Should not happen */ + crm_perror(LOG_ERR, "FATAL: Cannot exec %s", the_subsystem->command); + + exit(100); /* Suppress respawning */ + return TRUE; /* never reached */ } diff --git a/crmd/te_actions.c b/crmd/te_actions.c index c4aae9fc85..32988bc22e 100644 --- a/crmd/te_actions.c +++ b/crmd/te_actions.c @@ -1,527 +1,518 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include char *te_uuid = NULL; -void send_rsc_command(crm_action_t *action); +void send_rsc_command(crm_action_t * action); static void -te_start_action_timer(crm_graph_t *graph, crm_action_t *action) +te_start_action_timer(crm_graph_t * graph, crm_action_t * action) { - crm_malloc0(action->timer, sizeof(crm_action_timer_t)); - action->timer->timeout = action->timeout; - action->timer->reason = timeout_action; - action->timer->action = action; - action->timer->source_id = g_timeout_add( - action->timer->timeout + graph->network_delay, - action_timer_callback, (void*)action->timer); - - CRM_ASSERT(action->timer->source_id != 0); + crm_malloc0(action->timer, sizeof(crm_action_timer_t)); + action->timer->timeout = action->timeout; + action->timer->reason = timeout_action; + action->timer->action = action; + action->timer->source_id = g_timeout_add(action->timer->timeout + graph->network_delay, + action_timer_callback, (void *)action->timer); + + CRM_ASSERT(action->timer->source_id != 0); } - static gboolean -te_pseudo_action(crm_graph_t *graph, crm_action_t *pseudo) +te_pseudo_action(crm_graph_t * graph, crm_action_t * pseudo) { - crm_info("Pseudo action %d fired and confirmed", pseudo->id); - pseudo->confirmed = TRUE; - update_graph(graph, pseudo); - trigger_graph(); - return TRUE; + crm_info("Pseudo action %d fired and confirmed", pseudo->id); + pseudo->confirmed = TRUE; + update_graph(graph, pseudo); + trigger_graph(); + return TRUE; } void -send_stonith_update(crm_action_t *action, const char *target, const char *uuid) +send_stonith_update(crm_action_t * action, const char *target, const char *uuid) { - enum cib_errors rc = cib_ok; - - /* zero out the node-status & remove all LRM status info */ - xmlNode *node_state = create_xml_node(NULL, XML_CIB_TAG_STATE); - - CRM_CHECK(target != NULL, return); - CRM_CHECK(uuid != NULL, return); - - crm_xml_add(node_state, XML_ATTR_UUID, uuid); - crm_xml_add(node_state, XML_ATTR_UNAME, target); - crm_xml_add(node_state, XML_CIB_ATTR_HASTATE, DEADSTATUS); - crm_xml_add(node_state, XML_CIB_ATTR_INCCM, XML_BOOLEAN_NO); - crm_xml_add(node_state, XML_CIB_ATTR_CRMDSTATE, OFFLINESTATUS); - crm_xml_add(node_state, XML_CIB_ATTR_JOINSTATE, CRMD_JOINSTATE_DOWN); - crm_xml_add(node_state, XML_CIB_ATTR_EXPSTATE, CRMD_JOINSTATE_DOWN); - crm_xml_add(node_state, XML_ATTR_ORIGIN, __FUNCTION__); - - rc = fsa_cib_conn->cmds->update( - fsa_cib_conn, XML_CIB_TAG_STATUS, node_state, - cib_quorum_override|cib_scope_local|cib_can_create); - - /* Delay processing the trigger until the update completes */ - crm_info("Sending fencing update %d for %s", rc, target); - add_cib_op_callback(fsa_cib_conn, rc, FALSE, crm_strdup(target), cib_fencing_updated); - - /* Make sure it sticks */ - /* fsa_cib_conn->cmds->bump_epoch(fsa_cib_conn, cib_quorum_override|cib_scope_local); */ - - erase_status_tag(target, XML_CIB_TAG_LRM, cib_scope_local); - erase_status_tag(target, XML_TAG_TRANSIENT_NODEATTRS, cib_scope_local); - - free_xml(node_state); - - /* Make sure the membership cache is accurate */ - crm_update_peer(0, 0, 0, -1, crm_proc_none, uuid, target, NULL, CRM_NODE_LOST); - - return; + enum cib_errors rc = cib_ok; + + /* zero out the node-status & remove all LRM status info */ + xmlNode *node_state = create_xml_node(NULL, XML_CIB_TAG_STATE); + + CRM_CHECK(target != NULL, return); + CRM_CHECK(uuid != NULL, return); + + crm_xml_add(node_state, XML_ATTR_UUID, uuid); + crm_xml_add(node_state, XML_ATTR_UNAME, target); + crm_xml_add(node_state, XML_CIB_ATTR_HASTATE, DEADSTATUS); + crm_xml_add(node_state, XML_CIB_ATTR_INCCM, XML_BOOLEAN_NO); + crm_xml_add(node_state, XML_CIB_ATTR_CRMDSTATE, OFFLINESTATUS); + crm_xml_add(node_state, XML_CIB_ATTR_JOINSTATE, CRMD_JOINSTATE_DOWN); + crm_xml_add(node_state, XML_CIB_ATTR_EXPSTATE, CRMD_JOINSTATE_DOWN); + crm_xml_add(node_state, XML_ATTR_ORIGIN, __FUNCTION__); + + rc = fsa_cib_conn->cmds->update(fsa_cib_conn, XML_CIB_TAG_STATUS, node_state, + cib_quorum_override | cib_scope_local | cib_can_create); + + /* Delay processing the trigger until the update completes */ + crm_info("Sending fencing update %d for %s", rc, target); + add_cib_op_callback(fsa_cib_conn, rc, FALSE, crm_strdup(target), cib_fencing_updated); + + /* Make sure it sticks */ + /* fsa_cib_conn->cmds->bump_epoch(fsa_cib_conn, cib_quorum_override|cib_scope_local); */ + + erase_status_tag(target, XML_CIB_TAG_LRM, cib_scope_local); + erase_status_tag(target, XML_TAG_TRANSIENT_NODEATTRS, cib_scope_local); + + free_xml(node_state); + + /* Make sure the membership cache is accurate */ + crm_update_peer(0, 0, 0, -1, crm_proc_none, uuid, target, NULL, CRM_NODE_LOST); + + return; } static gboolean -te_fence_node(crm_graph_t *graph, crm_action_t *action) +te_fence_node(crm_graph_t * graph, crm_action_t * action) { - int rc = 0; - const char *id = NULL; - const char *uuid = NULL; - const char *target = NULL; - const char *type = NULL; - gboolean invalid_action = FALSE; - enum stonith_call_options options = st_opt_none; - - id = ID(action->xml); - target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); - uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); - type = crm_meta_value(action->params, "stonith_action"); - - CRM_CHECK(id != NULL, invalid_action = TRUE); - CRM_CHECK(uuid != NULL, invalid_action = TRUE); - CRM_CHECK(type != NULL, invalid_action = TRUE); - CRM_CHECK(target != NULL, invalid_action = TRUE); - - if(invalid_action) { - crm_log_xml_warn(action->xml, "BadAction"); - return FALSE; - } - - te_log_action(LOG_INFO, - "Executing %s fencing operation (%s) on %s (timeout=%d)", - type, id, target, transition_graph->stonith_timeout); - - /* Passing NULL means block until we can connect... */ - te_connect_stonith(NULL); - - if(finalized_nodes && g_hash_table_size(finalized_nodes) == 1) { - options |= st_opt_allow_suicide; - } - - rc = stonith_api->cmds->fence( - stonith_api, options, target, type, transition_graph->stonith_timeout/1000); - - stonith_api->cmds->register_callback( - stonith_api, rc, transition_graph->stonith_timeout/1000, FALSE, - generate_transition_key(transition_graph->id, action->id, 0, te_uuid), - "tengine_stonith_callback", tengine_stonith_callback); - - return TRUE; + int rc = 0; + const char *id = NULL; + const char *uuid = NULL; + const char *target = NULL; + const char *type = NULL; + gboolean invalid_action = FALSE; + enum stonith_call_options options = st_opt_none; + + id = ID(action->xml); + target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); + uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); + type = crm_meta_value(action->params, "stonith_action"); + + CRM_CHECK(id != NULL, invalid_action = TRUE); + CRM_CHECK(uuid != NULL, invalid_action = TRUE); + CRM_CHECK(type != NULL, invalid_action = TRUE); + CRM_CHECK(target != NULL, invalid_action = TRUE); + + if (invalid_action) { + crm_log_xml_warn(action->xml, "BadAction"); + return FALSE; + } + + te_log_action(LOG_INFO, + "Executing %s fencing operation (%s) on %s (timeout=%d)", + type, id, target, transition_graph->stonith_timeout); + + /* Passing NULL means block until we can connect... */ + te_connect_stonith(NULL); + + if (finalized_nodes && g_hash_table_size(finalized_nodes) == 1) { + options |= st_opt_allow_suicide; + } + + rc = stonith_api->cmds->fence(stonith_api, options, target, type, + transition_graph->stonith_timeout / 1000); + + stonith_api->cmds->register_callback(stonith_api, rc, transition_graph->stonith_timeout / 1000, + FALSE, generate_transition_key(transition_graph->id, + action->id, 0, te_uuid), + "tengine_stonith_callback", tengine_stonith_callback); + + return TRUE; } -static int get_target_rc(crm_action_t *action) +static int +get_target_rc(crm_action_t * action) { - const char *target_rc_s = crm_meta_value(action->params, XML_ATTR_TE_TARGET_RC); + const char *target_rc_s = crm_meta_value(action->params, XML_ATTR_TE_TARGET_RC); - if(target_rc_s != NULL) { - return crm_parse_int(target_rc_s, "0"); - } - return 0; + if (target_rc_s != NULL) { + return crm_parse_int(target_rc_s, "0"); + } + return 0; } static gboolean -te_crm_command(crm_graph_t *graph, crm_action_t *action) +te_crm_command(crm_graph_t * graph, crm_action_t * action) { - char *counter = NULL; - xmlNode *cmd = NULL; - gboolean is_local = FALSE; - - const char *id = NULL; - const char *task = NULL; - const char *value = NULL; - const char *on_node = NULL; - - gboolean rc = TRUE; - gboolean no_wait = FALSE; - - id = ID(action->xml); - task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); - on_node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); - - CRM_CHECK(on_node != NULL && strlen(on_node) != 0, - te_log_action(LOG_ERR, "Corrupted command (id=%s) %s: no node", - crm_str(id), crm_str(task)); - return FALSE); - - te_log_action(LOG_INFO, "Executing crm-event (%s): %s on %s%s%s", - crm_str(id), crm_str(task), on_node, - is_local?" (local)":"", no_wait?" - no waiting":""); - - if(safe_str_eq(on_node, fsa_our_uname)) { - is_local = TRUE; - } - - value = crm_meta_value(action->params, XML_ATTR_TE_NOWAIT); - if(crm_is_true(value)) { - no_wait = TRUE; - } - - if(is_local && safe_str_eq(task, CRM_OP_SHUTDOWN)) { - /* defer until everything else completes */ - te_log_action(LOG_INFO, "crm-event (%s) is a local shutdown", crm_str(id)); - graph->completion_action = tg_shutdown; - graph->abort_reason = "local shutdown"; - action->confirmed = TRUE; - update_graph(graph, action); - trigger_graph(); - return TRUE; - } - - cmd = create_request(task, action->xml, on_node, CRM_SYSTEM_CRMD, - CRM_SYSTEM_TENGINE, NULL); - - counter = generate_transition_key( - transition_graph->id, action->id, get_target_rc(action), te_uuid); - crm_xml_add(cmd, XML_ATTR_TRANSITION_KEY, counter); - - rc = send_cluster_message(on_node, crm_msg_crmd, cmd, TRUE); - crm_free(counter); - free_xml(cmd); - - if(rc == FALSE) { - crm_err("Action %d failed: send", action->id); - return FALSE; - - } else if(no_wait) { - action->confirmed = TRUE; - update_graph(graph, action); - trigger_graph(); - - } else { - if(action->timeout <= 0) { - crm_err("Action %d: %s on %s had an invalid timeout (%dms). Using %dms instead", - action->id, task, on_node, action->timeout, graph->network_delay); - action->timeout = graph->network_delay; - } - te_start_action_timer(graph, action); - } - - return TRUE; + char *counter = NULL; + xmlNode *cmd = NULL; + gboolean is_local = FALSE; + + const char *id = NULL; + const char *task = NULL; + const char *value = NULL; + const char *on_node = NULL; + + gboolean rc = TRUE; + gboolean no_wait = FALSE; + + id = ID(action->xml); + task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); + on_node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); + + CRM_CHECK(on_node != NULL && strlen(on_node) != 0, + te_log_action(LOG_ERR, "Corrupted command (id=%s) %s: no node", + crm_str(id), crm_str(task)); + return FALSE); + + te_log_action(LOG_INFO, "Executing crm-event (%s): %s on %s%s%s", + crm_str(id), crm_str(task), on_node, + is_local ? " (local)" : "", no_wait ? " - no waiting" : ""); + + if (safe_str_eq(on_node, fsa_our_uname)) { + is_local = TRUE; + } + + value = crm_meta_value(action->params, XML_ATTR_TE_NOWAIT); + if (crm_is_true(value)) { + no_wait = TRUE; + } + + if (is_local && safe_str_eq(task, CRM_OP_SHUTDOWN)) { + /* defer until everything else completes */ + te_log_action(LOG_INFO, "crm-event (%s) is a local shutdown", crm_str(id)); + graph->completion_action = tg_shutdown; + graph->abort_reason = "local shutdown"; + action->confirmed = TRUE; + update_graph(graph, action); + trigger_graph(); + return TRUE; + } + + cmd = create_request(task, action->xml, on_node, CRM_SYSTEM_CRMD, CRM_SYSTEM_TENGINE, NULL); + + counter = + generate_transition_key(transition_graph->id, action->id, get_target_rc(action), te_uuid); + crm_xml_add(cmd, XML_ATTR_TRANSITION_KEY, counter); + + rc = send_cluster_message(on_node, crm_msg_crmd, cmd, TRUE); + crm_free(counter); + free_xml(cmd); + + if (rc == FALSE) { + crm_err("Action %d failed: send", action->id); + return FALSE; + + } else if (no_wait) { + action->confirmed = TRUE; + update_graph(graph, action); + trigger_graph(); + + } else { + if (action->timeout <= 0) { + crm_err("Action %d: %s on %s had an invalid timeout (%dms). Using %dms instead", + action->id, task, on_node, action->timeout, graph->network_delay); + action->timeout = graph->network_delay; + } + te_start_action_timer(graph, action); + } + + return TRUE; } gboolean -cib_action_update(crm_action_t *action, int status, int op_rc) +cib_action_update(crm_action_t * action, int status, int op_rc) { - lrm_op_t *op = NULL; - xmlNode *state = NULL; - xmlNode *rsc = NULL; - xmlNode *xml_op = NULL; - xmlNode *action_rsc = NULL; - - enum cib_errors rc = cib_ok; - - const char *name = NULL; - const char *value = NULL; - const char *rsc_id = NULL; - const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); - const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); - const char *task_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY); - const char *target_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); - - int call_options = cib_quorum_override|cib_scope_local; - int target_rc = get_target_rc(action); - - if(status == LRM_OP_PENDING) { - crm_debug("%s %d: Recording pending operation %s on %s", - crm_element_name(action->xml), action->id, task_uuid, target); - } else { - crm_warn("%s %d: %s on %s timed out", - crm_element_name(action->xml), action->id, task_uuid, target); - } - - action_rsc = find_xml_node(action->xml, XML_CIB_TAG_RESOURCE, TRUE); - if(action_rsc == NULL) { - return FALSE; - } - - rsc_id = ID(action_rsc); - CRM_CHECK(rsc_id != NULL, - crm_log_xml_err(action->xml, "Bad:action"); - return FALSE); - + lrm_op_t *op = NULL; + xmlNode *state = NULL; + xmlNode *rsc = NULL; + xmlNode *xml_op = NULL; + xmlNode *action_rsc = NULL; + + enum cib_errors rc = cib_ok; + + const char *name = NULL; + const char *value = NULL; + const char *rsc_id = NULL; + const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); + const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); + const char *task_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY); + const char *target_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); + + int call_options = cib_quorum_override | cib_scope_local; + int target_rc = get_target_rc(action); + + if (status == LRM_OP_PENDING) { + crm_debug("%s %d: Recording pending operation %s on %s", + crm_element_name(action->xml), action->id, task_uuid, target); + } else { + crm_warn("%s %d: %s on %s timed out", + crm_element_name(action->xml), action->id, task_uuid, target); + } + + action_rsc = find_xml_node(action->xml, XML_CIB_TAG_RESOURCE, TRUE); + if (action_rsc == NULL) { + return FALSE; + } + + rsc_id = ID(action_rsc); + CRM_CHECK(rsc_id != NULL, crm_log_xml_err(action->xml, "Bad:action"); + return FALSE); + /* update the CIB */ - state = create_xml_node(NULL, XML_CIB_TAG_STATE); - - crm_xml_add(state, XML_ATTR_UUID, target_uuid); - crm_xml_add(state, XML_ATTR_UNAME, target); - - rsc = create_xml_node(state, XML_CIB_TAG_LRM); - crm_xml_add(rsc, XML_ATTR_ID, target_uuid); - - rsc = create_xml_node(rsc, XML_LRM_TAG_RESOURCES); - rsc = create_xml_node(rsc, XML_LRM_TAG_RESOURCE); - crm_xml_add(rsc, XML_ATTR_ID, rsc_id); - - name = XML_ATTR_TYPE; - value = crm_element_value(action_rsc, name); - crm_xml_add(rsc, name, value); - name = XML_AGENT_ATTR_CLASS; - value = crm_element_value(action_rsc, name); - crm_xml_add(rsc, name, value); - name = XML_AGENT_ATTR_PROVIDER; - value = crm_element_value(action_rsc, name); - crm_xml_add(rsc, name, value); - - op = convert_graph_action(NULL, action, status, op_rc); - op->call_id = -1; - op->user_data = generate_transition_key( - transition_graph->id, action->id, target_rc, te_uuid); - - xml_op = create_operation_update( - rsc, op, CRM_FEATURE_SET, target_rc, __FUNCTION__, LOG_INFO); - free_lrm_op(op); - - crm_debug_3("Updating CIB with \"%s\" (%s): %s %s on %s", - status<0?"new action":XML_ATTR_TIMEOUT, - crm_element_name(action->xml), crm_str(task), rsc_id, target); - crm_log_xml_trace(xml_op, "Op"); - - rc = fsa_cib_conn->cmds->update( - fsa_cib_conn, XML_CIB_TAG_STATUS, state, call_options); - - crm_debug_2("Updating CIB with %s action %d: %s on %s (call_id=%d)", - op_status2text(status), action->id, task_uuid, target, rc); - - add_cib_op_callback(fsa_cib_conn, rc, FALSE, NULL, cib_action_updated); - free_xml(state); - - action->sent_update = TRUE; - - if(rc < cib_ok) { - return FALSE; - } - - return TRUE; -} + state = create_xml_node(NULL, XML_CIB_TAG_STATE); + crm_xml_add(state, XML_ATTR_UUID, target_uuid); + crm_xml_add(state, XML_ATTR_UNAME, target); + + rsc = create_xml_node(state, XML_CIB_TAG_LRM); + crm_xml_add(rsc, XML_ATTR_ID, target_uuid); + + rsc = create_xml_node(rsc, XML_LRM_TAG_RESOURCES); + rsc = create_xml_node(rsc, XML_LRM_TAG_RESOURCE); + crm_xml_add(rsc, XML_ATTR_ID, rsc_id); + + name = XML_ATTR_TYPE; + value = crm_element_value(action_rsc, name); + crm_xml_add(rsc, name, value); + name = XML_AGENT_ATTR_CLASS; + value = crm_element_value(action_rsc, name); + crm_xml_add(rsc, name, value); + name = XML_AGENT_ATTR_PROVIDER; + value = crm_element_value(action_rsc, name); + crm_xml_add(rsc, name, value); + + op = convert_graph_action(NULL, action, status, op_rc); + op->call_id = -1; + op->user_data = generate_transition_key(transition_graph->id, action->id, target_rc, te_uuid); + + xml_op = create_operation_update(rsc, op, CRM_FEATURE_SET, target_rc, __FUNCTION__, LOG_INFO); + free_lrm_op(op); + + crm_debug_3("Updating CIB with \"%s\" (%s): %s %s on %s", + status < 0 ? "new action" : XML_ATTR_TIMEOUT, + crm_element_name(action->xml), crm_str(task), rsc_id, target); + crm_log_xml_trace(xml_op, "Op"); + + rc = fsa_cib_conn->cmds->update(fsa_cib_conn, XML_CIB_TAG_STATUS, state, call_options); + + crm_debug_2("Updating CIB with %s action %d: %s on %s (call_id=%d)", + op_status2text(status), action->id, task_uuid, target, rc); + + add_cib_op_callback(fsa_cib_conn, rc, FALSE, NULL, cib_action_updated); + free_xml(state); + + action->sent_update = TRUE; + + if (rc < cib_ok) { + return FALSE; + } + + return TRUE; +} static gboolean -te_rsc_command(crm_graph_t *graph, crm_action_t *action) +te_rsc_command(crm_graph_t * graph, crm_action_t * action) { - /* never overwrite stop actions in the CIB with - * anything other than completed results - * - * Writing pending stops makes it look like the - * resource is running again - */ - xmlNode *cmd = NULL; - xmlNode *rsc_op = NULL; - - gboolean rc = TRUE; - gboolean no_wait = FALSE; - gboolean is_local = FALSE; - - char *counter = NULL; - const char *task = NULL; - const char *value = NULL; - const char *on_node = NULL; - const char *task_uuid = NULL; - - CRM_ASSERT(action != NULL); - CRM_ASSERT(action->xml != NULL); - - action->executed = FALSE; - on_node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); - - CRM_CHECK(on_node != NULL && strlen(on_node) != 0, - te_log_action(LOG_ERR, "Corrupted command(id=%s) %s: no node", - ID(action->xml), crm_str(task)); - return FALSE); - - rsc_op = action->xml; - task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); - task_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY); - on_node = crm_element_value(rsc_op, XML_LRM_ATTR_TARGET); - counter = generate_transition_key( - transition_graph->id, action->id, get_target_rc(action), te_uuid); - crm_xml_add(rsc_op, XML_ATTR_TRANSITION_KEY, counter); - - if(safe_str_eq(on_node, fsa_our_uname)) { - is_local = TRUE; - } - - value = crm_meta_value(action->params, XML_ATTR_TE_NOWAIT); - if(crm_is_true(value)) { - no_wait = TRUE; - } - - crm_info("Initiating action %d: %s %s on %s%s%s", - action->id, task, task_uuid, on_node, - is_local?" (local)":"", no_wait?" - no waiting":""); - - cmd = create_request(CRM_OP_INVOKE_LRM, rsc_op, on_node, - CRM_SYSTEM_LRMD, CRM_SYSTEM_TENGINE, NULL); - - if(is_local) { - /* shortcut local resource commands */ - ha_msg_input_t data = { - .msg = cmd, - .xml = rsc_op, - }; - - fsa_data_t msg = { - .id = 0, - .data = &data, - .data_type = fsa_dt_ha_msg, - .fsa_input = I_NULL, - .fsa_cause = C_FSA_INTERNAL, - .actions = A_LRM_INVOKE, - .origin = __FUNCTION__, - }; - - do_lrm_invoke(A_LRM_INVOKE, C_FSA_INTERNAL, fsa_state, I_NULL, &msg); - - } else { - rc = send_cluster_message(on_node, crm_msg_lrmd, cmd, TRUE); - } - - crm_free(counter); - free_xml(cmd); - - action->executed = TRUE; - if(rc == FALSE) { - crm_err("Action %d failed: send", action->id); - return FALSE; - - } else if(no_wait) { - action->confirmed = TRUE; - update_graph(transition_graph, action); - trigger_graph(); - - } else { - if(action->timeout <= 0) { - crm_err("Action %d: %s %s on %s had an invalid timeout (%dms). Using %dms instead", - action->id, task, task_uuid, on_node, action->timeout, graph->network_delay); - action->timeout = graph->network_delay; - } - te_start_action_timer(graph, action); - } - - value = crm_meta_value(action->params, XML_OP_ATTR_PENDING); - if(crm_is_true(value)) { - /* write a "pending" entry to the CIB, inhibit notification */ - crm_info("Recording pending op %s in the CIB", task_uuid); - cib_action_update(action, LRM_OP_PENDING, EXECRA_STATUS_UNKNOWN); - } - - return TRUE; + /* never overwrite stop actions in the CIB with + * anything other than completed results + * + * Writing pending stops makes it look like the + * resource is running again + */ + xmlNode *cmd = NULL; + xmlNode *rsc_op = NULL; + + gboolean rc = TRUE; + gboolean no_wait = FALSE; + gboolean is_local = FALSE; + + char *counter = NULL; + const char *task = NULL; + const char *value = NULL; + const char *on_node = NULL; + const char *task_uuid = NULL; + + CRM_ASSERT(action != NULL); + CRM_ASSERT(action->xml != NULL); + + action->executed = FALSE; + on_node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); + + CRM_CHECK(on_node != NULL && strlen(on_node) != 0, + te_log_action(LOG_ERR, "Corrupted command(id=%s) %s: no node", + ID(action->xml), crm_str(task)); + return FALSE); + + rsc_op = action->xml; + task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); + task_uuid = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY); + on_node = crm_element_value(rsc_op, XML_LRM_ATTR_TARGET); + counter = + generate_transition_key(transition_graph->id, action->id, get_target_rc(action), te_uuid); + crm_xml_add(rsc_op, XML_ATTR_TRANSITION_KEY, counter); + + if (safe_str_eq(on_node, fsa_our_uname)) { + is_local = TRUE; + } + + value = crm_meta_value(action->params, XML_ATTR_TE_NOWAIT); + if (crm_is_true(value)) { + no_wait = TRUE; + } + + crm_info("Initiating action %d: %s %s on %s%s%s", + action->id, task, task_uuid, on_node, + is_local ? " (local)" : "", no_wait ? " - no waiting" : ""); + + cmd = create_request(CRM_OP_INVOKE_LRM, rsc_op, on_node, + CRM_SYSTEM_LRMD, CRM_SYSTEM_TENGINE, NULL); + + if (is_local) { + /* shortcut local resource commands */ + ha_msg_input_t data = { + .msg = cmd, + .xml = rsc_op, + }; + + fsa_data_t msg = { + .id = 0, + .data = &data, + .data_type = fsa_dt_ha_msg, + .fsa_input = I_NULL, + .fsa_cause = C_FSA_INTERNAL, + .actions = A_LRM_INVOKE, + .origin = __FUNCTION__, + }; + + do_lrm_invoke(A_LRM_INVOKE, C_FSA_INTERNAL, fsa_state, I_NULL, &msg); + + } else { + rc = send_cluster_message(on_node, crm_msg_lrmd, cmd, TRUE); + } + + crm_free(counter); + free_xml(cmd); + + action->executed = TRUE; + if (rc == FALSE) { + crm_err("Action %d failed: send", action->id); + return FALSE; + + } else if (no_wait) { + action->confirmed = TRUE; + update_graph(transition_graph, action); + trigger_graph(); + + } else { + if (action->timeout <= 0) { + crm_err("Action %d: %s %s on %s had an invalid timeout (%dms). Using %dms instead", + action->id, task, task_uuid, on_node, action->timeout, graph->network_delay); + action->timeout = graph->network_delay; + } + te_start_action_timer(graph, action); + } + + value = crm_meta_value(action->params, XML_OP_ATTR_PENDING); + if (crm_is_true(value)) { + /* write a "pending" entry to the CIB, inhibit notification */ + crm_info("Recording pending op %s in the CIB", task_uuid); + cib_action_update(action, LRM_OP_PENDING, EXECRA_STATUS_UNKNOWN); + } + + return TRUE; } crm_graph_functions_t te_graph_fns = { - te_pseudo_action, - te_rsc_command, - te_crm_command, - te_fence_node + te_pseudo_action, + te_rsc_command, + te_crm_command, + te_fence_node }; void -notify_crmd(crm_graph_t *graph) +notify_crmd(crm_graph_t * graph) { - int log_level = LOG_DEBUG; - const char *type = "unknown"; - enum crmd_fsa_input event = I_NULL; - - crm_debug("Processing transition completion in state %s", fsa_state2string(fsa_state)); - - CRM_CHECK(graph->complete, graph->complete = TRUE); - - switch(graph->completion_action) { - case tg_stop: - type = "stop"; - /* fall through */ - case tg_done: - type = "done"; - log_level = LOG_INFO; - if(fsa_state == S_TRANSITION_ENGINE) { - event = I_TE_SUCCESS; - } - break; - - case tg_restart: - type = "restart"; - if(fsa_state == S_TRANSITION_ENGINE) { - if(transition_timer->period_ms > 0) { - crm_timer_start(transition_timer); - } else { - event = I_PE_CALC; - } - - } else if(fsa_state == S_POLICY_ENGINE) { - register_fsa_action(A_PE_INVOKE); - } - break; - - case tg_shutdown: - type = "shutdown"; - if(is_set(fsa_input_register, R_SHUTDOWN)) { - event = I_STOP; - - } else { - crm_err("We didn't ask to be shut down, yet our" - " PE is telling us too."); - event = I_TERMINATE; - } - } - - te_log_action(log_level, "Transition %d status: %s - %s", - graph->id, type, crm_str(graph->abort_reason)); - - graph->abort_reason = NULL; - graph->completion_action = tg_done; - clear_bit_inplace(fsa_input_register, R_IN_TRANSITION); - - if(event != I_NULL) { - register_fsa_input(C_FSA_INTERNAL, event, NULL); - - } else if(fsa_source) { - mainloop_set_trigger(fsa_source); - } + int log_level = LOG_DEBUG; + const char *type = "unknown"; + enum crmd_fsa_input event = I_NULL; + + crm_debug("Processing transition completion in state %s", fsa_state2string(fsa_state)); + + CRM_CHECK(graph->complete, graph->complete = TRUE); + + switch (graph->completion_action) { + case tg_stop: + type = "stop"; + /* fall through */ + case tg_done: + type = "done"; + log_level = LOG_INFO; + if (fsa_state == S_TRANSITION_ENGINE) { + event = I_TE_SUCCESS; + } + break; + + case tg_restart: + type = "restart"; + if (fsa_state == S_TRANSITION_ENGINE) { + if (transition_timer->period_ms > 0) { + crm_timer_start(transition_timer); + } else { + event = I_PE_CALC; + } + + } else if (fsa_state == S_POLICY_ENGINE) { + register_fsa_action(A_PE_INVOKE); + } + break; + + case tg_shutdown: + type = "shutdown"; + if (is_set(fsa_input_register, R_SHUTDOWN)) { + event = I_STOP; + + } else { + crm_err("We didn't ask to be shut down, yet our" " PE is telling us too."); + event = I_TERMINATE; + } + } + + te_log_action(log_level, "Transition %d status: %s - %s", + graph->id, type, crm_str(graph->abort_reason)); + + graph->abort_reason = NULL; + graph->completion_action = tg_done; + clear_bit_inplace(fsa_input_register, R_IN_TRANSITION); + + if (event != I_NULL) { + register_fsa_input(C_FSA_INTERNAL, event, NULL); + + } else if (fsa_source) { + mainloop_set_trigger(fsa_source); + } } diff --git a/crmd/te_callbacks.c b/crmd/te_callbacks.c index 38df2f109c..45f0d6dca6 100644 --- a/crmd/te_callbacks.c +++ b/crmd/te_callbacks.c @@ -1,534 +1,554 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include /* For ONLINESTATUS etc */ -void te_update_confirm(const char *event, xmlNode *msg); +void te_update_confirm(const char *event, xmlNode * msg); extern char *te_uuid; gboolean shuttingdown = FALSE; crm_graph_t *transition_graph; crm_trigger_t *transition_trigger = NULL; /* #define rsc_op_template "//"XML_TAG_DIFF_ADDED"//"XML_TAG_CIB"//"XML_CIB_TAG_STATE"[@uname='%s']"//"XML_LRM_TAG_RSC_OP"[@id='%s]" */ #define rsc_op_template "//"XML_TAG_DIFF_ADDED"//"XML_TAG_CIB"//"XML_LRM_TAG_RSC_OP"[@id='%s']" -static const char *get_node_id(xmlNode *rsc_op) +static const char * +get_node_id(xmlNode * rsc_op) { xmlNode *node = rsc_op; - while(node != NULL && safe_str_neq(XML_CIB_TAG_STATE, TYPE(node))) { - node = node->parent; + + while (node != NULL && safe_str_neq(XML_CIB_TAG_STATE, TYPE(node))) { + node = node->parent; } - + CRM_CHECK(node != NULL, return NULL); return ID(node); } - -static void process_resource_updates(xmlXPathObject *xpathObj) +static void +process_resource_updates(xmlXPathObject * xpathObj) { /* */ int lpc = 0, max = xpathObj->nodesetval->nodeNr; - for(lpc = 0; lpc < max; lpc++) { - xmlNode *rsc_op = getXpathResult(xpathObj, lpc); - const char *node = get_node_id(rsc_op); - process_graph_event(rsc_op, node); + + for (lpc = 0; lpc < max; lpc++) { + xmlNode *rsc_op = getXpathResult(xpathObj, lpc); + const char *node = get_node_id(rsc_op); + + process_graph_event(rsc_op, node); } } void -te_update_diff(const char *event, xmlNode *msg) +te_update_diff(const char *event, xmlNode * msg) { - int rc = -1; - const char *op = NULL; - - xmlNode *diff = NULL; - xmlXPathObject *xpathObj = NULL; - - int diff_add_updates = 0; - int diff_add_epoch = 0; - int diff_add_admin_epoch = 0; - - int diff_del_updates = 0; - int diff_del_epoch = 0; - int diff_del_admin_epoch = 0; - - CRM_CHECK(msg != NULL, return); - crm_element_value_int(msg, F_CIB_RC, &rc); - - if(transition_graph == NULL) { - crm_debug_3("No graph"); - return; - - } else if(rc < cib_ok) { - crm_debug_3("Filter rc=%d (%s)", rc, cib_error2string(rc)); - return; - - } else if(transition_graph->complete == TRUE - && fsa_state != S_IDLE - && fsa_state != S_TRANSITION_ENGINE - && fsa_state != S_POLICY_ENGINE) { - crm_debug_2("Filter state=%s, complete=%d", fsa_state2string(fsa_state), transition_graph->complete); - return; - } - - op = crm_element_value(msg, F_CIB_OPERATION); - diff = get_message_xml(msg, F_CIB_UPDATE_RESULT); - - cib_diff_version_details( - diff, - &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, - &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); - - crm_debug("Processing diff (%s): %d.%d.%d -> %d.%d.%d (%s)", op, - diff_del_admin_epoch,diff_del_epoch,diff_del_updates, - diff_add_admin_epoch,diff_add_epoch,diff_add_updates, - fsa_state2string(fsa_state)); - log_cib_diff(LOG_DEBUG_2, diff, op); - - if(cib_config_changed(NULL, NULL, &diff)) { - abort_transition(INFINITY, tg_restart, "Non-status change", diff); - goto bail; /* configuration changed */ - } - - /* Tickets Attributes - Added/Updated */ - xpathObj = xpath_search(diff,"//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_CIB_TAG_TICKETS); - if(xpathObj && xpathObj->nodesetval->nodeNr > 0) { - xmlNode *aborted = getXpathResult(xpathObj, 0); - abort_transition(INFINITY, tg_restart, "Ticket attribute: update", aborted); - goto bail; - - } else if(xpathObj) { - xmlXPathFreeObject(xpathObj); - } - - /* Tickets Attributes - Removed */ - xpathObj = xpath_search(diff,"//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_REMOVED"//"XML_CIB_TAG_TICKETS); - if(xpathObj && xpathObj->nodesetval->nodeNr > 0) { - xmlNode *aborted = getXpathResult(xpathObj, 0); - abort_transition(INFINITY, tg_restart, "Ticket attribute: removal", aborted); - goto bail; - - } else if(xpathObj) { - xmlXPathFreeObject(xpathObj); - } - - /* Transient Attributes - Added/Updated */ - xpathObj = xpath_search(diff,"//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_TAG_TRANSIENT_NODEATTRS"//"XML_CIB_TAG_NVPAIR); - if(xpathObj && xpathObj->nodesetval->nodeNr > 0) { - int lpc; - for(lpc = 0; lpc < xpathObj->nodesetval->nodeNr; lpc++) { - xmlNode *attr = getXpathResult(xpathObj, lpc); - const char *name = crm_element_value(attr, XML_NVPAIR_ATTR_NAME); - const char *value = NULL; - - if(safe_str_eq(CRM_OP_PROBED, name)) { - value = crm_element_value(attr, XML_NVPAIR_ATTR_VALUE); - } - - if(crm_is_true(value) == FALSE) { - abort_transition(INFINITY, tg_restart, "Transient attribute: update", attr); - crm_log_xml_trace(attr, "Abort"); - goto bail; - } - } - - } else if(xpathObj) { - xmlXPathFreeObject(xpathObj); - } - - /* Transient Attributes - Removed */ - xpathObj = xpath_search(diff,"//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_REMOVED"//"XML_TAG_TRANSIENT_NODEATTRS); - if(xpathObj && xpathObj->nodesetval->nodeNr > 0) { - xmlNode *aborted = getXpathResult(xpathObj, 0); - abort_transition(INFINITY, tg_restart, "Transient attribute: removal", aborted); - goto bail; - - } else if(xpathObj) { - xmlXPathFreeObject(xpathObj); - } - - /* Check for node state updates... possibly from a shutdown we requested */ - xpathObj = xpath_search(diff, "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_CIB_TAG_STATE); - if(xpathObj) { - int lpc = 0, max = xpathObj->nodesetval->nodeNr; - for(lpc = 0; lpc < max; lpc++) { - xmlNode *node = getXpathResult(xpathObj, lpc); - const char *event_node = crm_element_value(node, XML_ATTR_ID); - const char *ccm_state = crm_element_value(node, XML_CIB_ATTR_INCCM); - const char *ha_state = crm_element_value(node, XML_CIB_ATTR_HASTATE); - const char *shutdown_s = crm_element_value(node, XML_CIB_ATTR_SHUTDOWN); - const char *crmd_state = crm_element_value(node, XML_CIB_ATTR_CRMDSTATE); - - if(safe_str_eq(ccm_state, XML_BOOLEAN_FALSE) - || safe_str_eq(ha_state, DEADSTATUS) - || safe_str_eq(crmd_state, CRMD_JOINSTATE_DOWN)) { - crm_action_t *shutdown = match_down_event(0, event_node, NULL); - - if(shutdown != NULL) { - const char *task = crm_element_value(shutdown->xml, XML_LRM_ATTR_TASK); - if(safe_str_neq(task, CRM_OP_FENCE)) { - /* Wait for stonithd to tell us it is complete via tengine_stonith_callback() */ - crm_debug("Confirming %s op %d", task, shutdown->id); - /* match->confirmed = TRUE; */ - stop_te_timer(shutdown->timer); - update_graph(transition_graph, shutdown); - trigger_graph(); - } - - } else { - crm_info("Stonith/shutdown of %s not matched", event_node); - abort_transition(INFINITY, tg_restart, "Node failure", node); - } - fail_incompletable_actions(transition_graph, event_node); - } - - if(shutdown_s) { - int shutdown = crm_parse_int(shutdown_s, NULL); - if(shutdown > 0) { - crm_info("Aborting on "XML_CIB_ATTR_SHUTDOWN" attribute for %s", event_node); - abort_transition(INFINITY, tg_restart, "Shutdown request", node); - } - } - } - xmlXPathFreeObject(xpathObj); - } - - /* - * Check for and fast-track the processing of LRM refreshes - * In large clusters this can result in _huge_ speedups - * - * Unfortunately we can only do so when there are no pending actions - * Otherwise we could miss updates we're waiting for and stall - * - */ - xpathObj = NULL; - if(transition_graph->pending == 0) { - xpathObj = xpath_search(diff, "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_LRM_TAG_RESOURCE); - } - - if(xpathObj) { - int updates = xpathObj->nodesetval->nodeNr; - if(updates > 1) { - /* Updates by, or in response to, TE actions will never contain updates - * for more than one resource at a time - */ - crm_info("Detected LRM refresh - %d resources updated: Skipping all resource events", updates); - abort_transition(INFINITY, tg_restart, "LRM Refresh", diff); - goto bail; - } - xmlXPathFreeObject(xpathObj); - } - - /* Process operation updates */ - xpathObj = xpath_search(diff, "//"F_CIB_UPDATE_RESULT"//"XML_TAG_DIFF_ADDED"//"XML_LRM_TAG_RSC_OP); - if(xpathObj) { - process_resource_updates(xpathObj); - xmlXPathFreeObject(xpathObj); - } - - /* Detect deleted (as opposed to replaced or added) actions - eg. crm_resource -C */ - xpathObj = xpath_search(diff, "//"XML_TAG_DIFF_REMOVED"//"XML_LRM_TAG_RSC_OP); - if(xpathObj) { - int lpc = 0, max = xpathObj->nodesetval->nodeNr; - - for(lpc = 0; lpc < max; lpc++) { - int max = 0; - const char *op_id = NULL; - char *rsc_op_xpath = NULL; - xmlXPathObject *op_match = NULL; - xmlNode *match = getXpathResult(xpathObj, lpc); - CRM_CHECK(match != NULL, continue); - - op_id = ID(match); - - max = strlen(rsc_op_template) + strlen(op_id) + 1; - crm_malloc0(rsc_op_xpath, max); - snprintf(rsc_op_xpath, max, rsc_op_template, op_id); - - op_match = xpath_search(diff, rsc_op_xpath); - if(op_match == NULL || op_match->nodesetval->nodeNr == 0) { - /* Prevent false positives by matching cancelations too */ - const char *node = get_node_id(match); - crm_action_t *cancelled = get_cancel_action(op_id, node); - - if(cancelled == NULL) { - crm_debug("No match for deleted action %s (%s on %s)", rsc_op_xpath, op_id, node); - abort_transition(INFINITY, tg_restart, "Resource op removal", match); - if(op_match) { - xmlXPathFreeObject(op_match); - } - crm_free(rsc_op_xpath); - goto bail; - - } else { - crm_debug("Deleted lrm_rsc_op %s on %s was for graph event %d", - op_id, node, cancelled->id); - } - } - - if(op_match) { - xmlXPathFreeObject(op_match); - } - crm_free(rsc_op_xpath); - } - } + int rc = -1; + const char *op = NULL; + + xmlNode *diff = NULL; + xmlXPathObject *xpathObj = NULL; + + int diff_add_updates = 0; + int diff_add_epoch = 0; + int diff_add_admin_epoch = 0; + + int diff_del_updates = 0; + int diff_del_epoch = 0; + int diff_del_admin_epoch = 0; + + CRM_CHECK(msg != NULL, return); + crm_element_value_int(msg, F_CIB_RC, &rc); + + if (transition_graph == NULL) { + crm_debug_3("No graph"); + return; + + } else if (rc < cib_ok) { + crm_debug_3("Filter rc=%d (%s)", rc, cib_error2string(rc)); + return; + + } else if (transition_graph->complete == TRUE + && fsa_state != S_IDLE + && fsa_state != S_TRANSITION_ENGINE && fsa_state != S_POLICY_ENGINE) { + crm_debug_2("Filter state=%s, complete=%d", fsa_state2string(fsa_state), + transition_graph->complete); + return; + } + + op = crm_element_value(msg, F_CIB_OPERATION); + diff = get_message_xml(msg, F_CIB_UPDATE_RESULT); + + cib_diff_version_details(diff, + &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, + &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); + + crm_debug("Processing diff (%s): %d.%d.%d -> %d.%d.%d (%s)", op, + diff_del_admin_epoch, diff_del_epoch, diff_del_updates, + diff_add_admin_epoch, diff_add_epoch, diff_add_updates, fsa_state2string(fsa_state)); + log_cib_diff(LOG_DEBUG_2, diff, op); + + if (cib_config_changed(NULL, NULL, &diff)) { + abort_transition(INFINITY, tg_restart, "Non-status change", diff); + goto bail; /* configuration changed */ + } + + /* Tickets Attributes - Added/Updated */ + xpathObj = + xpath_search(diff, + "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_CIB_TAG_TICKETS); + if (xpathObj && xpathObj->nodesetval->nodeNr > 0) { + xmlNode *aborted = getXpathResult(xpathObj, 0); + + abort_transition(INFINITY, tg_restart, "Ticket attribute: update", aborted); + goto bail; + + } else if (xpathObj) { + xmlXPathFreeObject(xpathObj); + } + + /* Tickets Attributes - Removed */ + xpathObj = + xpath_search(diff, + "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_CIB_TAG_TICKETS); + if (xpathObj && xpathObj->nodesetval->nodeNr > 0) { + xmlNode *aborted = getXpathResult(xpathObj, 0); + + abort_transition(INFINITY, tg_restart, "Ticket attribute: removal", aborted); + goto bail; + + } else if (xpathObj) { + xmlXPathFreeObject(xpathObj); + } + + /* Transient Attributes - Added/Updated */ + xpathObj = + xpath_search(diff, + "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" + XML_TAG_TRANSIENT_NODEATTRS "//" XML_CIB_TAG_NVPAIR); + if (xpathObj && xpathObj->nodesetval->nodeNr > 0) { + int lpc; + + for (lpc = 0; lpc < xpathObj->nodesetval->nodeNr; lpc++) { + xmlNode *attr = getXpathResult(xpathObj, lpc); + const char *name = crm_element_value(attr, XML_NVPAIR_ATTR_NAME); + const char *value = NULL; + + if (safe_str_eq(CRM_OP_PROBED, name)) { + value = crm_element_value(attr, XML_NVPAIR_ATTR_VALUE); + } + + if (crm_is_true(value) == FALSE) { + abort_transition(INFINITY, tg_restart, "Transient attribute: update", attr); + crm_log_xml_trace(attr, "Abort"); + goto bail; + } + } + + } else if (xpathObj) { + xmlXPathFreeObject(xpathObj); + } + + /* Transient Attributes - Removed */ + xpathObj = + xpath_search(diff, + "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" + XML_TAG_TRANSIENT_NODEATTRS); + if (xpathObj && xpathObj->nodesetval->nodeNr > 0) { + xmlNode *aborted = getXpathResult(xpathObj, 0); + + abort_transition(INFINITY, tg_restart, "Transient attribute: removal", aborted); + goto bail; + + } else if (xpathObj) { + xmlXPathFreeObject(xpathObj); + } + + /* Check for node state updates... possibly from a shutdown we requested */ + xpathObj = + xpath_search(diff, "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_CIB_TAG_STATE); + if (xpathObj) { + int lpc = 0, max = xpathObj->nodesetval->nodeNr; + + for (lpc = 0; lpc < max; lpc++) { + xmlNode *node = getXpathResult(xpathObj, lpc); + const char *event_node = crm_element_value(node, XML_ATTR_ID); + const char *ccm_state = crm_element_value(node, XML_CIB_ATTR_INCCM); + const char *ha_state = crm_element_value(node, XML_CIB_ATTR_HASTATE); + const char *shutdown_s = crm_element_value(node, XML_CIB_ATTR_SHUTDOWN); + const char *crmd_state = crm_element_value(node, XML_CIB_ATTR_CRMDSTATE); + + if (safe_str_eq(ccm_state, XML_BOOLEAN_FALSE) + || safe_str_eq(ha_state, DEADSTATUS) + || safe_str_eq(crmd_state, CRMD_JOINSTATE_DOWN)) { + crm_action_t *shutdown = match_down_event(0, event_node, NULL); + + if (shutdown != NULL) { + const char *task = crm_element_value(shutdown->xml, XML_LRM_ATTR_TASK); + + if (safe_str_neq(task, CRM_OP_FENCE)) { + /* Wait for stonithd to tell us it is complete via tengine_stonith_callback() */ + crm_debug("Confirming %s op %d", task, shutdown->id); + /* match->confirmed = TRUE; */ + stop_te_timer(shutdown->timer); + update_graph(transition_graph, shutdown); + trigger_graph(); + } + + } else { + crm_info("Stonith/shutdown of %s not matched", event_node); + abort_transition(INFINITY, tg_restart, "Node failure", node); + } + fail_incompletable_actions(transition_graph, event_node); + } + + if (shutdown_s) { + int shutdown = crm_parse_int(shutdown_s, NULL); + + if (shutdown > 0) { + crm_info("Aborting on " XML_CIB_ATTR_SHUTDOWN " attribute for %s", event_node); + abort_transition(INFINITY, tg_restart, "Shutdown request", node); + } + } + } + xmlXPathFreeObject(xpathObj); + } + + /* + * Check for and fast-track the processing of LRM refreshes + * In large clusters this can result in _huge_ speedups + * + * Unfortunately we can only do so when there are no pending actions + * Otherwise we could miss updates we're waiting for and stall + * + */ + xpathObj = NULL; + if (transition_graph->pending == 0) { + xpathObj = + xpath_search(diff, + "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" + XML_LRM_TAG_RESOURCE); + } + + if (xpathObj) { + int updates = xpathObj->nodesetval->nodeNr; + + if (updates > 1) { + /* Updates by, or in response to, TE actions will never contain updates + * for more than one resource at a time + */ + crm_info("Detected LRM refresh - %d resources updated: Skipping all resource events", + updates); + abort_transition(INFINITY, tg_restart, "LRM Refresh", diff); + goto bail; + } + xmlXPathFreeObject(xpathObj); + } + + /* Process operation updates */ + xpathObj = + xpath_search(diff, + "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_LRM_TAG_RSC_OP); + if (xpathObj) { + process_resource_updates(xpathObj); + xmlXPathFreeObject(xpathObj); + } + + /* Detect deleted (as opposed to replaced or added) actions - eg. crm_resource -C */ + xpathObj = xpath_search(diff, "//" XML_TAG_DIFF_REMOVED "//" XML_LRM_TAG_RSC_OP); + if (xpathObj) { + int lpc = 0, max = xpathObj->nodesetval->nodeNr; + + for (lpc = 0; lpc < max; lpc++) { + int max = 0; + const char *op_id = NULL; + char *rsc_op_xpath = NULL; + xmlXPathObject *op_match = NULL; + xmlNode *match = getXpathResult(xpathObj, lpc); + + CRM_CHECK(match != NULL, continue); + + op_id = ID(match); + + max = strlen(rsc_op_template) + strlen(op_id) + 1; + crm_malloc0(rsc_op_xpath, max); + snprintf(rsc_op_xpath, max, rsc_op_template, op_id); + + op_match = xpath_search(diff, rsc_op_xpath); + if (op_match == NULL || op_match->nodesetval->nodeNr == 0) { + /* Prevent false positives by matching cancelations too */ + const char *node = get_node_id(match); + crm_action_t *cancelled = get_cancel_action(op_id, node); + + if (cancelled == NULL) { + crm_debug("No match for deleted action %s (%s on %s)", rsc_op_xpath, op_id, + node); + abort_transition(INFINITY, tg_restart, "Resource op removal", match); + if (op_match) { + xmlXPathFreeObject(op_match); + } + crm_free(rsc_op_xpath); + goto bail; + + } else { + crm_debug("Deleted lrm_rsc_op %s on %s was for graph event %d", + op_id, node, cancelled->id); + } + } + + if (op_match) { + xmlXPathFreeObject(op_match); + } + crm_free(rsc_op_xpath); + } + } bail: - if(xpathObj) { - xmlXPathFreeObject(xpathObj); - } + if (xpathObj) { + xmlXPathFreeObject(xpathObj); + } } gboolean -process_te_message(xmlNode *msg, xmlNode *xml_data) +process_te_message(xmlNode * msg, xmlNode * xml_data) { - const char *from = crm_element_value(msg, F_ORIG); - const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); - const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM); - const char *ref = crm_element_value(msg, XML_ATTR_REFERENCE); - const char *op = crm_element_value(msg, F_CRM_TASK); - const char *type = crm_element_value(msg, F_CRM_MSG_TYPE); - - crm_debug_2("Processing %s (%s) message", op, ref); - crm_log_xml(LOG_DEBUG_3, "ipc", msg); - - if(op == NULL){ - /* error */ - - } else if(sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_TENGINE) != 0) { - crm_debug_2("Bad sys-to %s", crm_str(sys_to)); - return FALSE; - - } else if(safe_str_eq(op, CRM_OP_INVOKE_LRM) - && safe_str_eq(sys_from, CRM_SYSTEM_LRMD) + const char *from = crm_element_value(msg, F_ORIG); + const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); + const char *sys_from = crm_element_value(msg, F_CRM_SYS_FROM); + const char *ref = crm_element_value(msg, XML_ATTR_REFERENCE); + const char *op = crm_element_value(msg, F_CRM_TASK); + const char *type = crm_element_value(msg, F_CRM_MSG_TYPE); + + crm_debug_2("Processing %s (%s) message", op, ref); + crm_log_xml(LOG_DEBUG_3, "ipc", msg); + + if (op == NULL) { + /* error */ + + } else if (sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_TENGINE) != 0) { + crm_debug_2("Bad sys-to %s", crm_str(sys_to)); + return FALSE; + + } else if (safe_str_eq(op, CRM_OP_INVOKE_LRM) + && safe_str_eq(sys_from, CRM_SYSTEM_LRMD) /* && safe_str_eq(type, XML_ATTR_RESPONSE) */ - ){ - xmlXPathObject *xpathObj = NULL; - crm_log_xml(LOG_DEBUG_2, "Processing (N)ACK", msg); - crm_info("Processing (N)ACK %s from %s", - crm_element_value(msg, XML_ATTR_REFERENCE), from); - - xpathObj = xpath_search(xml_data, "//"XML_LRM_TAG_RSC_OP); - if(xpathObj) { - process_resource_updates(xpathObj); - xmlXPathFreeObject(xpathObj); - xpathObj = NULL; - - } else { - crm_log_xml(LOG_ERR, "Invalid (N)ACK", msg); - return FALSE; - } - - } else { - crm_err("Unknown command: %s::%s from %s", type, op, sys_from); - } - - crm_debug_3("finished processing message"); - - return TRUE; + ) { + xmlXPathObject *xpathObj = NULL; + + crm_log_xml(LOG_DEBUG_2, "Processing (N)ACK", msg); + crm_info("Processing (N)ACK %s from %s", crm_element_value(msg, XML_ATTR_REFERENCE), from); + + xpathObj = xpath_search(xml_data, "//" XML_LRM_TAG_RSC_OP); + if (xpathObj) { + process_resource_updates(xpathObj); + xmlXPathFreeObject(xpathObj); + xpathObj = NULL; + + } else { + crm_log_xml(LOG_ERR, "Invalid (N)ACK", msg); + return FALSE; + } + + } else { + crm_err("Unknown command: %s::%s from %s", type, op, sys_from); + } + + crm_debug_3("finished processing message"); + + return TRUE; } void -tengine_stonith_callback( - stonith_t *stonith, const xmlNode *msg, int call_id, int rc, xmlNode *output, void *userdata) +tengine_stonith_callback(stonith_t * stonith, const xmlNode * msg, int call_id, int rc, + xmlNode * output, void *userdata) { - char *uuid = NULL; - int target_rc = -1; - int stonith_id = -1; - int transition_id = -1; - crm_action_t *action = NULL; - - CRM_CHECK(userdata != NULL, return); - crm_log_xml_info(output, "StonithOp"); - crm_info("Stonith operation %d/%s: %s (%d)", call_id, (char*)userdata, stonith_error2string(rc), rc); - - if(AM_I_DC == FALSE) { - return; - } - /* crm_info("call=%d, optype=%d, node_name=%s, result=%d, node_list=%s, action=%s", */ - /* op->call_id, op->optype, op->node_name, op->op_result, */ - /* (char *)op->node_list, op->private_data); */ - - - /* filter out old STONITH actions */ - CRM_CHECK(decode_transition_key(userdata, &uuid, &transition_id, &stonith_id, &target_rc), - crm_err("Invalid event detected"); - goto bail; - ); - - if(transition_graph->complete - || stonith_id < 0 - || safe_str_neq(uuid, te_uuid) - || transition_graph->id != transition_id) { - crm_info("Ignoring STONITH action initiated outside" - " of the current transition"); - goto bail; - } - - /* this will mark the event complete if a match is found */ - action = get_action(stonith_id, FALSE); - if(action == NULL) { - crm_err("Stonith action not matched"); - goto bail; - } - - stop_te_timer(action->timer); - if(rc == stonith_ok) { - const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); - const char *uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); - crm_info("Stonith of %s passed", target); - if(action->confirmed == FALSE) { - action->confirmed = TRUE; - send_stonith_update(action, target, uuid); - } - - } else { - const char *target = crm_element_value_const(action->xml, XML_LRM_ATTR_TARGET); - const char *allow_fail = crm_meta_value(action->params, XML_ATTR_TE_ALLOWFAIL); - - action->failed = TRUE; - if(crm_is_true(allow_fail) == FALSE) { - crm_err("Stonith of %s failed (%d)... aborting transition.", target, rc); - abort_transition(INFINITY, tg_restart, "Stonith failed", NULL); - } - } - - update_graph(transition_graph, action); - trigger_graph(); + char *uuid = NULL; + int target_rc = -1; + int stonith_id = -1; + int transition_id = -1; + crm_action_t *action = NULL; + + CRM_CHECK(userdata != NULL, return); + crm_log_xml_info(output, "StonithOp"); + crm_info("Stonith operation %d/%s: %s (%d)", call_id, (char *)userdata, + stonith_error2string(rc), rc); + + if (AM_I_DC == FALSE) { + return; + } + /* crm_info("call=%d, optype=%d, node_name=%s, result=%d, node_list=%s, action=%s", */ + /* op->call_id, op->optype, op->node_name, op->op_result, */ + /* (char *)op->node_list, op->private_data); */ + + /* filter out old STONITH actions */ + CRM_CHECK(decode_transition_key(userdata, &uuid, &transition_id, &stonith_id, &target_rc), + crm_err("Invalid event detected"); + goto bail; + ); + + if (transition_graph->complete || stonith_id < 0 || safe_str_neq(uuid, te_uuid) + || transition_graph->id != transition_id) { + crm_info("Ignoring STONITH action initiated outside" " of the current transition"); + goto bail; + } + + /* this will mark the event complete if a match is found */ + action = get_action(stonith_id, FALSE); + if (action == NULL) { + crm_err("Stonith action not matched"); + goto bail; + } + + stop_te_timer(action->timer); + if (rc == stonith_ok) { + const char *target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); + const char *uuid = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); + + crm_info("Stonith of %s passed", target); + if (action->confirmed == FALSE) { + action->confirmed = TRUE; + send_stonith_update(action, target, uuid); + } + + } else { + const char *target = crm_element_value_const(action->xml, XML_LRM_ATTR_TARGET); + const char *allow_fail = crm_meta_value(action->params, XML_ATTR_TE_ALLOWFAIL); + + action->failed = TRUE; + if (crm_is_true(allow_fail) == FALSE) { + crm_err("Stonith of %s failed (%d)... aborting transition.", target, rc); + abort_transition(INFINITY, tg_restart, "Stonith failed", NULL); + } + } + + update_graph(transition_graph, action); + trigger_graph(); bail: - crm_free(userdata); - crm_free(uuid); - return; + crm_free(userdata); + crm_free(uuid); + return; } void -cib_fencing_updated(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +cib_fencing_updated(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - if(rc < cib_ok) { - crm_err("Fencing update %d for %s: failed - %s (%d)", - call_id, (char*)user_data, cib_error2string(rc), rc); - crm_log_xml_warn(msg, "Failed update"); - abort_transition(INFINITY, tg_shutdown, "CIB update failed", NULL); - + if (rc < cib_ok) { + crm_err("Fencing update %d for %s: failed - %s (%d)", + call_id, (char *)user_data, cib_error2string(rc), rc); + crm_log_xml_warn(msg, "Failed update"); + abort_transition(INFINITY, tg_shutdown, "CIB update failed", NULL); + } else { - crm_info("Fencing update %d for %s: complete", call_id, (char*)user_data); + crm_info("Fencing update %d for %s: complete", call_id, (char *)user_data); } crm_free(user_data); } void -cib_action_updated(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +cib_action_updated(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - if(rc < cib_ok) { - crm_err("Update %d FAILED: %s", call_id, cib_error2string(rc)); - } + if (rc < cib_ok) { + crm_err("Update %d FAILED: %s", call_id, cib_error2string(rc)); + } } void -cib_failcount_updated(xmlNode *msg, int call_id, int rc, - xmlNode *output, void *user_data) +cib_failcount_updated(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { - if(rc < cib_ok) { - crm_err("Update %d FAILED: %s", call_id, cib_error2string(rc)); - } + if (rc < cib_ok) { + crm_err("Update %d FAILED: %s", call_id, cib_error2string(rc)); + } } gboolean action_timer_callback(gpointer data) { - crm_action_timer_t *timer = NULL; - - CRM_CHECK(data != NULL, return FALSE); - - timer = (crm_action_timer_t*)data; - stop_te_timer(timer); - - crm_warn("Timer popped (timeout=%d, abort_level=%d, complete=%s)", - timer->timeout, - transition_graph->abort_priority, - transition_graph->complete?"true":"false"); - - CRM_CHECK(timer->action != NULL, return FALSE); - - if(transition_graph->complete) { - crm_warn("Ignoring timeout while not in transition"); - - } else if(timer->reason == timeout_action_warn) { - print_action( - LOG_WARNING,"Action missed its timeout: ", timer->action); - - /* Don't check the FSA state - * - * We might also be in S_INTEGRATION or some other state waiting for this - * action so we can close the transition and continue - */ - - } else { - /* fail the action */ - gboolean send_update = TRUE; - const char *task = crm_element_value(timer->action->xml, XML_LRM_ATTR_TASK); - print_action(LOG_ERR, "Aborting transition, action lost: ", timer->action); - - timer->action->failed = TRUE; - timer->action->confirmed = TRUE; - abort_transition(INFINITY, tg_restart, "Action lost", NULL); - - update_graph(transition_graph, timer->action); - trigger_graph(); - - if(timer->action->type != action_type_rsc) { - send_update = FALSE; - } else if(safe_str_eq(task, "cancel")) { - /* we dont need to update the CIB with these */ - send_update = FALSE; - } - - if(send_update) { - /* cib_action_update(timer->action, LRM_OP_PENDING, EXECRA_STATUS_UNKNOWN); */ - cib_action_update(timer->action, LRM_OP_TIMEOUT, EXECRA_UNKNOWN_ERROR); - } - } - - return FALSE; -} + crm_action_timer_t *timer = NULL; + CRM_CHECK(data != NULL, return FALSE); + timer = (crm_action_timer_t *) data; + stop_te_timer(timer); + crm_warn("Timer popped (timeout=%d, abort_level=%d, complete=%s)", + timer->timeout, + transition_graph->abort_priority, transition_graph->complete ? "true" : "false"); + + CRM_CHECK(timer->action != NULL, return FALSE); + + if (transition_graph->complete) { + crm_warn("Ignoring timeout while not in transition"); + + } else if (timer->reason == timeout_action_warn) { + print_action(LOG_WARNING, "Action missed its timeout: ", timer->action); + + /* Don't check the FSA state + * + * We might also be in S_INTEGRATION or some other state waiting for this + * action so we can close the transition and continue + */ + + } else { + /* fail the action */ + gboolean send_update = TRUE; + const char *task = crm_element_value(timer->action->xml, XML_LRM_ATTR_TASK); + + print_action(LOG_ERR, "Aborting transition, action lost: ", timer->action); + + timer->action->failed = TRUE; + timer->action->confirmed = TRUE; + abort_transition(INFINITY, tg_restart, "Action lost", NULL); + + update_graph(transition_graph, timer->action); + trigger_graph(); + + if (timer->action->type != action_type_rsc) { + send_update = FALSE; + } else if (safe_str_eq(task, "cancel")) { + /* we dont need to update the CIB with these */ + send_update = FALSE; + } + + if (send_update) { + /* cib_action_update(timer->action, LRM_OP_PENDING, EXECRA_STATUS_UNKNOWN); */ + cib_action_update(timer->action, LRM_OP_TIMEOUT, EXECRA_UNKNOWN_ERROR); + } + } + + return FALSE; +} diff --git a/crmd/te_events.c b/crmd/te_events.c index 0ad983cd4e..8e2b957f5f 100644 --- a/crmd/te_events.c +++ b/crmd/te_events.c @@ -1,513 +1,502 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include char *failed_stop_offset = NULL; char *failed_start_offset = NULL; -int match_graph_event(int action_id, xmlNode *event, const char *event_node, - int op_status, int op_rc, int target_rc); +int match_graph_event(int action_id, xmlNode * event, const char *event_node, + int op_status, int op_rc, int target_rc); gboolean -fail_incompletable_actions(crm_graph_t *graph, const char *down_node) +fail_incompletable_actions(crm_graph_t * graph, const char *down_node) { const char *target = NULL; xmlNode *last_action = NULL; GListPtr gIter = NULL; GListPtr gIter2 = NULL; - if(graph == NULL || graph->complete) { - return FALSE; + if (graph == NULL || graph->complete) { + return FALSE; } - + gIter = graph->synapses; - for(; gIter != NULL; gIter = gIter->next) { - synapse_t *synapse = (synapse_t*)gIter->data; - - if (synapse->confirmed) { - continue; - } - - gIter2 = synapse->actions; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - crm_action_t *action = (crm_action_t*)gIter2->data; - - if(action->type == action_type_pseudo || action->confirmed) { - continue; - } else if(action->type == action_type_crm) { - const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); - if(safe_str_eq(task, CRM_OP_FENCE)) { - continue; - } - } - - target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); - if(safe_str_eq(target, down_node)) { - action->failed = TRUE; - synapse->failed = TRUE; - last_action = action->xml; - stop_te_timer(action->timer); - update_graph(graph, action); - - if(synapse->executed) { - crm_notice("Action %d (%s) was pending on %s (offline)", - action->id, ID(action->xml), down_node); - } else { - crm_notice("Action %d (%s) is scheduled for %s (offline)", - action->id, ID(action->xml), down_node); - } - } - } + for (; gIter != NULL; gIter = gIter->next) { + synapse_t *synapse = (synapse_t *) gIter->data; + + if (synapse->confirmed) { + continue; + } + + gIter2 = synapse->actions; + for (; gIter2 != NULL; gIter2 = gIter2->next) { + crm_action_t *action = (crm_action_t *) gIter2->data; + + if (action->type == action_type_pseudo || action->confirmed) { + continue; + } else if (action->type == action_type_crm) { + const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); + + if (safe_str_eq(task, CRM_OP_FENCE)) { + continue; + } + } + + target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); + if (safe_str_eq(target, down_node)) { + action->failed = TRUE; + synapse->failed = TRUE; + last_action = action->xml; + stop_te_timer(action->timer); + update_graph(graph, action); + + if (synapse->executed) { + crm_notice("Action %d (%s) was pending on %s (offline)", + action->id, ID(action->xml), down_node); + } else { + crm_notice("Action %d (%s) is scheduled for %s (offline)", + action->id, ID(action->xml), down_node); + } + } + } } - if(last_action != NULL) { - crm_warn("Node %s shutdown resulted in un-runnable actions", down_node); - abort_transition(INFINITY, tg_restart, "Node failure", last_action); - return TRUE; + if (last_action != NULL) { + crm_warn("Node %s shutdown resulted in un-runnable actions", down_node); + abort_transition(INFINITY, tg_restart, "Node failure", last_action); + return TRUE; } - + return FALSE; } static gboolean -update_failcount(xmlNode *event, const char *event_node, int rc, int target_rc, gboolean do_update) +update_failcount(xmlNode * event, const char *event_node, int rc, int target_rc, gboolean do_update) { int interval = 0; char *task = NULL; char *rsc_id = NULL; char *attr_name = NULL; const char *value = NULL; - const char *id = crm_element_value(event, XML_LRM_ATTR_TASK_KEY); - const char *on_uname = get_uname(event_node); + const char *id = crm_element_value(event, XML_LRM_ATTR_TASK_KEY); + const char *on_uname = get_uname(event_node); - if(rc == 99) { - /* this is an internal code for "we're busy, try again" */ - return FALSE; + if (rc == 99) { + /* this is an internal code for "we're busy, try again" */ + return FALSE; - } else if(rc == target_rc) { - return FALSE; + } else if (rc == target_rc) { + return FALSE; } - if(failed_stop_offset == NULL) { - failed_stop_offset = crm_strdup(INFINITY_S); + if (failed_stop_offset == NULL) { + failed_stop_offset = crm_strdup(INFINITY_S); } - if(failed_start_offset == NULL) { - failed_start_offset = crm_strdup(INFINITY_S); + if (failed_start_offset == NULL) { + failed_start_offset = crm_strdup(INFINITY_S); } - + CRM_CHECK(on_uname != NULL, return TRUE); - CRM_CHECK(parse_op_key(id, &rsc_id, &task, &interval), - crm_err("Couldn't parse: %s", ID(event)); - goto bail); + CRM_CHECK(parse_op_key(id, &rsc_id, &task, &interval), crm_err("Couldn't parse: %s", ID(event)); + goto bail); CRM_CHECK(task != NULL, goto bail); CRM_CHECK(rsc_id != NULL, goto bail); - if(do_update || interval > 0) { - do_update = TRUE; + if (do_update || interval > 0) { + do_update = TRUE; - } else if(safe_str_eq(task, CRMD_ACTION_START)) { - do_update = TRUE; - value = failed_start_offset; + } else if (safe_str_eq(task, CRMD_ACTION_START)) { + do_update = TRUE; + value = failed_start_offset; - } else if(safe_str_eq(task, CRMD_ACTION_STOP)) { - do_update = TRUE; - value = failed_stop_offset; + } else if (safe_str_eq(task, CRMD_ACTION_STOP)) { + do_update = TRUE; + value = failed_stop_offset; - } else if(safe_str_eq(task, CRMD_ACTION_STOP)) { - do_update = TRUE; - value = failed_stop_offset; + } else if (safe_str_eq(task, CRMD_ACTION_STOP)) { + do_update = TRUE; + value = failed_stop_offset; - } else if(safe_str_eq(task, CRMD_ACTION_PROMOTE)) { - do_update = TRUE; + } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) { + do_update = TRUE; - } else if(safe_str_eq(task, CRMD_ACTION_DEMOTE)) { - do_update = TRUE; + } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) { + do_update = TRUE; } - if(value == NULL || safe_str_neq(value, INFINITY_S)) { - value = XML_NVPAIR_ATTR_VALUE"++"; + if (value == NULL || safe_str_neq(value, INFINITY_S)) { + value = XML_NVPAIR_ATTR_VALUE "++"; } - if(do_update) { - char *now = crm_itoa(time(NULL)); - - crm_warn("Updating failcount for %s on %s after failed %s:" - " rc=%d (update=%s, time=%s)", rsc_id, on_uname, task, rc, value, now); + if (do_update) { + char *now = crm_itoa(time(NULL)); - attr_name = crm_concat("fail-count", rsc_id, '-'); - update_attrd(on_uname, attr_name, value, NULL); - crm_free(attr_name); + crm_warn("Updating failcount for %s on %s after failed %s:" + " rc=%d (update=%s, time=%s)", rsc_id, on_uname, task, rc, value, now); - attr_name = crm_concat("last-failure", rsc_id, '-'); - update_attrd(on_uname, attr_name, now, NULL); - crm_free(attr_name); + attr_name = crm_concat("fail-count", rsc_id, '-'); + update_attrd(on_uname, attr_name, value, NULL); + crm_free(attr_name); - crm_free(now); + attr_name = crm_concat("last-failure", rsc_id, '-'); + update_attrd(on_uname, attr_name, now, NULL); + crm_free(attr_name); + + crm_free(now); } bail: crm_free(rsc_id); crm_free(task); return TRUE; } static int -status_from_rc(crm_action_t *action, int orig_status, int rc, int target_rc) +status_from_rc(crm_action_t * action, int orig_status, int rc, int target_rc) { int status = orig_status; - if(target_rc == rc) { - crm_debug_2("Target rc: == %d", rc); - if(status != LRM_OP_DONE) { - crm_debug_2("Re-mapping op status to" - " LRM_OP_DONE for rc=%d", rc); - status = LRM_OP_DONE; - } + + if (target_rc == rc) { + crm_debug_2("Target rc: == %d", rc); + if (status != LRM_OP_DONE) { + crm_debug_2("Re-mapping op status to" " LRM_OP_DONE for rc=%d", rc); + status = LRM_OP_DONE; + } } else { - status = LRM_OP_ERROR; + status = LRM_OP_ERROR; } - + /* 99 is the code we use for direct nack's */ - if(rc != 99 && status != LRM_OP_DONE) { - const char *task, *uname; - task = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY); - uname = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); - crm_warn("Action %d (%s) on %s failed (target: %d vs. rc: %d): %s", - action->id, task, uname, target_rc, rc, op_status2text(status)); + if (rc != 99 && status != LRM_OP_DONE) { + const char *task, *uname; + + task = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY); + uname = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); + crm_warn("Action %d (%s) on %s failed (target: %d vs. rc: %d): %s", + action->id, task, uname, target_rc, rc, op_status2text(status)); } return status; } /* * returns the ID of the action if a match is found * returns -1 if a match was not found * returns -2 if a match was found but the action failed (and was * not allowed to) */ int -match_graph_event(int action_id, xmlNode *event, const char *event_node, - int op_status, int op_rc, int target_rc) +match_graph_event(int action_id, xmlNode * event, const char *event_node, + int op_status, int op_rc, int target_rc) { const char *target = NULL; const char *allow_fail = NULL; const char *this_event = NULL; crm_action_t *action = NULL; action = get_action(action_id, FALSE); - if(action == NULL) { - return -1; + if (action == NULL) { + return -1; } - + op_status = status_from_rc(action, op_status, op_rc, target_rc); - if(op_status != LRM_OP_DONE) { - update_failcount(event, event_node, op_rc, target_rc, FALSE); + if (op_status != LRM_OP_DONE) { + update_failcount(event, event_node, op_rc, target_rc, FALSE); } - + /* Process OP status */ - switch(op_status) { - case LRM_OP_PENDING: - crm_debug("Ignoring pending operation"); - return action->id; - break; - case LRM_OP_DONE: - break; - case LRM_OP_ERROR: - case LRM_OP_TIMEOUT: - case LRM_OP_NOTSUPPORTED: - action->failed = TRUE; - break; - case LRM_OP_CANCELLED: - /* do nothing?? */ - crm_err("Dont know what to do for cancelled ops yet"); - break; - default: - action->failed = TRUE; - crm_err("Unsupported action result: %d", op_status); + switch (op_status) { + case LRM_OP_PENDING: + crm_debug("Ignoring pending operation"); + return action->id; + break; + case LRM_OP_DONE: + break; + case LRM_OP_ERROR: + case LRM_OP_TIMEOUT: + case LRM_OP_NOTSUPPORTED: + action->failed = TRUE; + break; + case LRM_OP_CANCELLED: + /* do nothing?? */ + crm_err("Dont know what to do for cancelled ops yet"); + break; + default: + action->failed = TRUE; + crm_err("Unsupported action result: %d", op_status); } /* stop this event's timer if it had one */ stop_te_timer(action->timer); action->confirmed = TRUE; - + update_graph(transition_graph, action); trigger_graph(); - - if(action->failed) { - allow_fail = crm_meta_value(action->params, XML_ATTR_TE_ALLOWFAIL); - if(crm_is_true(allow_fail)) { - action->failed = FALSE; - } + + if (action->failed) { + allow_fail = crm_meta_value(action->params, XML_ATTR_TE_ALLOWFAIL); + if (crm_is_true(allow_fail)) { + action->failed = FALSE; + } } - if(action->failed) { - abort_transition(action->synapse->priority+1, - tg_restart, "Event failed", event); + if (action->failed) { + abort_transition(action->synapse->priority + 1, tg_restart, "Event failed", event); } this_event = crm_element_value(event, XML_LRM_ATTR_TASK_KEY); target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET); te_log_action(LOG_INFO, "Action %s (%d) confirmed on %s (rc=%d)", - crm_str(this_event), action->id, crm_str(target), - op_status); + crm_str(this_event), action->id, crm_str(target), op_status); return action->id; } crm_action_t * get_action(int id, gboolean confirmed) { GListPtr gIter = NULL; GListPtr gIter2 = NULL; gIter = transition_graph->synapses; - for(; gIter != NULL; gIter = gIter->next) { - synapse_t *synapse = (synapse_t*) gIter->data; - - gIter2 = synapse->actions; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - crm_action_t *action = (crm_action_t*)gIter2->data; - - if(action->id == id) { - if(confirmed) { - stop_te_timer(action->timer); - action->confirmed = TRUE; - } - return action; - } - } + for (; gIter != NULL; gIter = gIter->next) { + synapse_t *synapse = (synapse_t *) gIter->data; + + gIter2 = synapse->actions; + for (; gIter2 != NULL; gIter2 = gIter2->next) { + crm_action_t *action = (crm_action_t *) gIter2->data; + + if (action->id == id) { + if (confirmed) { + stop_te_timer(action->timer); + action->confirmed = TRUE; + } + return action; + } + } } - + return NULL; } crm_action_t * get_cancel_action(const char *id, const char *node) { const char *task = NULL; const char *target = NULL; GListPtr gIter = NULL; GListPtr gIter2 = NULL; gIter = transition_graph->synapses; - for(; gIter != NULL; gIter = gIter->next) { - synapse_t *synapse = (synapse_t*) gIter->data; - - gIter2 = synapse->actions; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - crm_action_t *action = (crm_action_t*)gIter2->data; - - task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); - if(safe_str_neq(CRMD_ACTION_CANCEL, task)) { - continue; - } - - task = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY); - if(safe_str_neq(task, id)) { - continue; - } - - target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); - if(safe_str_neq(target, node)) { - continue; - } - - return action; - } + for (; gIter != NULL; gIter = gIter->next) { + synapse_t *synapse = (synapse_t *) gIter->data; + + gIter2 = synapse->actions; + for (; gIter2 != NULL; gIter2 = gIter2->next) { + crm_action_t *action = (crm_action_t *) gIter2->data; + + task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); + if (safe_str_neq(CRMD_ACTION_CANCEL, task)) { + continue; + } + + task = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY); + if (safe_str_neq(task, id)) { + continue; + } + + target = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); + if (safe_str_neq(target, node)) { + continue; + } + + return action; + } } - + return NULL; } crm_action_t * match_down_event(int id, const char *target, const char *filter) { const char *this_action = NULL; - const char *this_node = NULL; + const char *this_node = NULL; crm_action_t *match = NULL; - + GListPtr gIter = NULL; GListPtr gIter2 = NULL; + gIter = transition_graph->synapses; - for(; gIter != NULL; gIter = gIter->next) { - synapse_t *synapse = (synapse_t*)gIter->data; - - /* lookup event */ - gIter2 = synapse->actions; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - crm_action_t *action = (crm_action_t*)gIter2->data; - - if(id > 0 && action->id == id) { - match = action; - break; - } - - this_action = crm_element_value( - action->xml, XML_LRM_ATTR_TASK); - - if(action->type != action_type_crm) { - continue; - - } else if(safe_str_eq(this_action, CRM_OP_LRM_REFRESH)){ - continue; - - } else if(filter != NULL - && safe_str_neq(this_action, filter)) { - continue; - } - - this_node = crm_element_value( - action->xml, XML_LRM_ATTR_TARGET_UUID); - - if(this_node == NULL) { - crm_log_xml_err(action->xml, "No node uuid"); - } - - if(safe_str_neq(this_node, target)) { - crm_debug("Action %d : Node mismatch: %s", - action->id, this_node); - continue; - } - - match = action; - id = action->id; - break; - } - - if(match != NULL) { - /* stop this event's timer if it had one */ - break; - } + for (; gIter != NULL; gIter = gIter->next) { + synapse_t *synapse = (synapse_t *) gIter->data; + + /* lookup event */ + gIter2 = synapse->actions; + for (; gIter2 != NULL; gIter2 = gIter2->next) { + crm_action_t *action = (crm_action_t *) gIter2->data; + + if (id > 0 && action->id == id) { + match = action; + break; + } + + this_action = crm_element_value(action->xml, XML_LRM_ATTR_TASK); + + if (action->type != action_type_crm) { + continue; + + } else if (safe_str_eq(this_action, CRM_OP_LRM_REFRESH)) { + continue; + + } else if (filter != NULL && safe_str_neq(this_action, filter)) { + continue; + } + + this_node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET_UUID); + + if (this_node == NULL) { + crm_log_xml_err(action->xml, "No node uuid"); + } + + if (safe_str_neq(this_node, target)) { + crm_debug("Action %d : Node mismatch: %s", action->id, this_node); + continue; + } + + match = action; + id = action->id; + break; + } + + if (match != NULL) { + /* stop this event's timer if it had one */ + break; + } } - - if(match != NULL) { - /* stop this event's timer if it had one */ - crm_debug("Match found for action %d: %s on %s", id, - crm_element_value(match->xml, XML_LRM_ATTR_TASK_KEY), - target); - } else if(id > 0) { - crm_err("No match for action %d", id); + if (match != NULL) { + /* stop this event's timer if it had one */ + crm_debug("Match found for action %d: %s on %s", id, + crm_element_value(match->xml, XML_LRM_ATTR_TASK_KEY), target); + + } else if (id > 0) { + crm_err("No match for action %d", id); } else { - crm_warn("No match for shutdown action on %s", target); + crm_warn("No match for shutdown action on %s", target); } return match; } - gboolean -process_graph_event(xmlNode *event, const char *event_node) +process_graph_event(xmlNode * event, const char *event_node) { int rc = -1; int status = -1; int action = -1; int target_rc = -1; int transition_num = -1; char *update_te_uuid = NULL; gboolean stop_early = FALSE; gboolean passed = FALSE; const char *id = NULL; const char *magic = NULL; - + CRM_ASSERT(event != NULL); id = crm_element_value(event, XML_LRM_ATTR_TASK_KEY); magic = crm_element_value(event, XML_ATTR_TRANSITION_MAGIC); - if(magic == NULL) { - /* non-change */ - return FALSE; + if (magic == NULL) { + /* non-change */ + return FALSE; } - - CRM_CHECK(decode_transition_magic( - magic, &update_te_uuid, &transition_num, &action, - &status, &rc, &target_rc), - crm_err("Invalid event %s detected", id); - abort_transition(INFINITY, tg_restart,"Bad event", event); - return FALSE; - ); - - if(status == LRM_OP_PENDING) { - goto bail; + + CRM_CHECK(decode_transition_magic(magic, &update_te_uuid, &transition_num, &action, + &status, &rc, &target_rc), + crm_err("Invalid event %s detected", id); + abort_transition(INFINITY, tg_restart, "Bad event", event); + return FALSE; + ); + + if (status == LRM_OP_PENDING) { + goto bail; } - - if(transition_num == -1) { - crm_err("Action %s (%s) initiated outside of a transition", - id, magic); - abort_transition(INFINITY, tg_restart,"Unexpected event",event); - - } else if(action < 0 || crm_str_eq(update_te_uuid, te_uuid, TRUE) == FALSE) { - crm_info("Action %s/%d (%s) initiated by a different transitioner", - id, action, magic); - abort_transition(INFINITY, tg_restart,"Foreign event", event); - stop_early = TRUE; /* This could be an lrm status refresh */ - - } else if(transition_graph->id != transition_num) { - crm_info("Detected action %s from a different transition:" - " %d vs. %d", id, transition_num, transition_graph->id); - abort_transition(INFINITY, tg_restart,"Old event", event); - stop_early = TRUE; /* This could be an lrm status refresh */ - - } else if(transition_graph->complete) { - crm_info("Action %s arrived after a completed transition", id); - abort_transition(INFINITY, tg_restart, "Inactive graph", event); - - } else if(match_graph_event( - action, event, event_node, status, rc, target_rc) < 0) { - crm_err("Unknown graph action %s", id); - abort_transition(INFINITY, tg_restart, "Unknown event", event); + + if (transition_num == -1) { + crm_err("Action %s (%s) initiated outside of a transition", id, magic); + abort_transition(INFINITY, tg_restart, "Unexpected event", event); + + } else if (action < 0 || crm_str_eq(update_te_uuid, te_uuid, TRUE) == FALSE) { + crm_info("Action %s/%d (%s) initiated by a different transitioner", id, action, magic); + abort_transition(INFINITY, tg_restart, "Foreign event", event); + stop_early = TRUE; /* This could be an lrm status refresh */ + + } else if (transition_graph->id != transition_num) { + crm_info("Detected action %s from a different transition:" + " %d vs. %d", id, transition_num, transition_graph->id); + abort_transition(INFINITY, tg_restart, "Old event", event); + stop_early = TRUE; /* This could be an lrm status refresh */ + + } else if (transition_graph->complete) { + crm_info("Action %s arrived after a completed transition", id); + abort_transition(INFINITY, tg_restart, "Inactive graph", event); + + } else if (match_graph_event(action, event, event_node, status, rc, target_rc) < 0) { + crm_err("Unknown graph action %s", id); + abort_transition(INFINITY, tg_restart, "Unknown event", event); } else { - passed = TRUE; - crm_debug_2("Processed update to %s: %s", id, magic); + passed = TRUE; + crm_debug_2("Processed update to %s: %s", id, magic); } - if(passed == FALSE) { - if(update_failcount(event, event_node, rc, target_rc, transition_num == -1)) { - /* Turns out this wasn't an lrm status refresh update aferall */ - stop_early = FALSE; - } + if (passed == FALSE) { + if (update_failcount(event, event_node, rc, target_rc, transition_num == -1)) { + /* Turns out this wasn't an lrm status refresh update aferall */ + stop_early = FALSE; + } } bail: crm_free(update_te_uuid); return stop_early; } - diff --git a/crmd/te_utils.c b/crmd/te_utils.c index da59a2e979..50372e8bb9 100644 --- a/crmd/te_utils.c +++ b/crmd/te_utils.c @@ -1,418 +1,417 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include GCHSource *stonith_src = NULL; crm_trigger_t *stonith_reconnect = NULL; GListPtr stonith_cleanup_list = NULL; static gboolean -fail_incompletable_stonith(crm_graph_t *graph) +fail_incompletable_stonith(crm_graph_t * graph) { GListPtr lpc = NULL; const char *task = NULL; xmlNode *last_action = NULL; - if(graph == NULL) { - return FALSE; + if (graph == NULL) { + return FALSE; } - - for(lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { - GListPtr lpc2 = NULL; - synapse_t *synapse = (synapse_t*)lpc->data; - if (synapse->confirmed) { - continue; - } - - for(lpc2 = synapse->actions; lpc2 != NULL; lpc2 = lpc2->next) { - crm_action_t *action = (crm_action_t*)lpc2->data; - - - if(action->type != action_type_crm || action->confirmed) { - continue; - } - - task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); - if(task && safe_str_eq(task, CRM_OP_FENCE)) { - action->failed = TRUE; - last_action = action->xml; - update_graph(graph, action); - crm_notice("Failing action %d (%s): STONITHd terminated", - action->id, ID(action->xml)); - } - } + + for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) { + GListPtr lpc2 = NULL; + synapse_t *synapse = (synapse_t *) lpc->data; + + if (synapse->confirmed) { + continue; + } + + for (lpc2 = synapse->actions; lpc2 != NULL; lpc2 = lpc2->next) { + crm_action_t *action = (crm_action_t *) lpc2->data; + + if (action->type != action_type_crm || action->confirmed) { + continue; + } + + task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); + if (task && safe_str_eq(task, CRM_OP_FENCE)) { + action->failed = TRUE; + last_action = action->xml; + update_graph(graph, action); + crm_notice("Failing action %d (%s): STONITHd terminated", + action->id, ID(action->xml)); + } + } } - - if(last_action != NULL) { - crm_warn("STONITHd failure resulted in un-runnable actions"); - abort_transition(INFINITY, tg_restart, "Stonith failure", last_action); - return TRUE; + + if (last_action != NULL) { + crm_warn("STONITHd failure resulted in un-runnable actions"); + abort_transition(INFINITY, tg_restart, "Stonith failure", last_action); + return TRUE; } - + return FALSE; } static void -tengine_stonith_connection_destroy(stonith_t *st, const char *event, xmlNode *msg) +tengine_stonith_connection_destroy(stonith_t * st, const char *event, xmlNode * msg) { - if(is_set(fsa_input_register, R_ST_REQUIRED)) { - crm_crit("Fencing daemon connection failed"); - mainloop_set_trigger(stonith_reconnect); + if (is_set(fsa_input_register, R_ST_REQUIRED)) { + crm_crit("Fencing daemon connection failed"); + mainloop_set_trigger(stonith_reconnect); } else { - crm_info("Fencing daemon disconnected"); + crm_info("Fencing daemon disconnected"); } /* cbchan will be garbage at this point, arrange for it to be reset */ stonith_api->state = stonith_disconnected; - if(AM_I_DC) { - fail_incompletable_stonith(transition_graph); - trigger_graph(); + if (AM_I_DC) { + fail_incompletable_stonith(transition_graph); + trigger_graph(); } } /* */ #ifdef SUPPORT_CMAN # include # include "../lib/common/stack.h" #endif static void -tengine_stonith_notify(stonith_t *st, const char *event, xmlNode *msg) +tengine_stonith_notify(stonith_t * st, const char *event, xmlNode * msg) { int rc = -99; const char *origin = NULL; const char *target = NULL; const char *executioner = NULL; xmlNode *action = get_xpath_object("//st-data", msg, LOG_ERR); - if(action == NULL) { - crm_log_xml(LOG_ERR, "Notify data not found", msg); - return; + if (action == NULL) { + crm_log_xml(LOG_ERR, "Notify data not found", msg); + return; } - + crm_log_xml(LOG_DEBUG, "stonith_notify", msg); crm_element_value_int(msg, F_STONITH_RC, &rc); origin = crm_element_value(action, F_STONITH_ORIGIN); target = crm_element_value(action, F_STONITH_TARGET); executioner = crm_element_value(action, F_STONITH_DELEGATE); - - if(rc == stonith_ok && crm_str_eq(target, fsa_our_uname, TRUE)) { - crm_err("We were alegedly just fenced by %s for %s!", executioner, origin); - register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__); - - } else if(rc == stonith_ok) { - crm_info("Peer %s was terminated (%s) by %s for %s (ref=%s): %s", - target, - crm_element_value(action, F_STONITH_OPERATION), - executioner, origin, - crm_element_value(action, F_STONITH_REMOTE), - stonith_error2string(rc)); + + if (rc == stonith_ok && crm_str_eq(target, fsa_our_uname, TRUE)) { + crm_err("We were alegedly just fenced by %s for %s!", executioner, origin); + register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__); + + } else if (rc == stonith_ok) { + crm_info("Peer %s was terminated (%s) by %s for %s (ref=%s): %s", + target, + crm_element_value(action, F_STONITH_OPERATION), + executioner, origin, + crm_element_value(action, F_STONITH_REMOTE), stonith_error2string(rc)); } else { - crm_err("Peer %s could not be terminated (%s) by %s for %s (ref=%s): %s", - target, - crm_element_value(action, F_STONITH_OPERATION), - executioner?executioner:"", origin, - crm_element_value(action, F_STONITH_REMOTE), - stonith_error2string(rc)); + crm_err("Peer %s could not be terminated (%s) by %s for %s (ref=%s): %s", + target, + crm_element_value(action, F_STONITH_OPERATION), + executioner ? executioner : "", origin, + crm_element_value(action, F_STONITH_REMOTE), stonith_error2string(rc)); } #ifdef SUPPORT_CMAN - if(rc == stonith_ok && is_cman_cluster()) { - int local_rc = 0; - FILE *confirm = NULL; - char *target_copy = crm_strdup(target); - - /* In case fenced hasn't noticed yet */ + if (rc == stonith_ok && is_cman_cluster()) { + int local_rc = 0; + FILE *confirm = NULL; + char *target_copy = crm_strdup(target); + + /* In case fenced hasn't noticed yet */ local_rc = fenced_external(target_copy); - if(local_rc != 0) { - crm_err("Could not notify CMAN that '%s' is now fenced: %d", target, local_rc); + if (local_rc != 0) { + crm_err("Could not notify CMAN that '%s' is now fenced: %d", target, local_rc); } else { - crm_notice("Notified CMAN that '%s' is now fenced", target); - } - - /* In case fenced is already trying to shoot it */ - confirm = fopen("/var/run/cluster/fenced_override", "w"); - if(confirm) { - local_rc = fprintf(confirm, "%s\n", target_copy); - if(local_rc < strlen(target_copy)) { - crm_err("Confirmation of CMAN fencing event for '%s' failed: %d", target, local_rc); - } else { - crm_notice("Confirmed CMAN fencing event for '%s'", target); - } - fflush(confirm); - fclose(confirm); - } + crm_notice("Notified CMAN that '%s' is now fenced", target); + } + + /* In case fenced is already trying to shoot it */ + confirm = fopen("/var/run/cluster/fenced_override", "w"); + if (confirm) { + local_rc = fprintf(confirm, "%s\n", target_copy); + if (local_rc < strlen(target_copy)) { + crm_err("Confirmation of CMAN fencing event for '%s' failed: %d", target, local_rc); + } else { + crm_notice("Confirmed CMAN fencing event for '%s'", target); + } + fflush(confirm); + fclose(confirm); + } } #endif - - if(rc == stonith_ok && safe_str_eq(target, origin)) { - if(fsa_our_dc == NULL || safe_str_eq(fsa_our_dc, target)) { - crm_notice("Target was our leader %s (recorded: %s)", - target, fsa_our_dc?fsa_our_dc:""); - /* Given the CIB resyncing that occurs around elections, - * have one node update the CIB now and, if the new DC is different, - * have them do so too after the election - */ - if(safe_str_eq(executioner, fsa_our_uname)) { - const char *uuid = get_uuid(target); - send_stonith_update(NULL, target, uuid); - } else { - stonith_cleanup_list = g_list_append(stonith_cleanup_list, crm_strdup(target)); - } - } + + if (rc == stonith_ok && safe_str_eq(target, origin)) { + if (fsa_our_dc == NULL || safe_str_eq(fsa_our_dc, target)) { + crm_notice("Target was our leader %s (recorded: %s)", + target, fsa_our_dc ? fsa_our_dc : ""); + /* Given the CIB resyncing that occurs around elections, + * have one node update the CIB now and, if the new DC is different, + * have them do so too after the election + */ + if (safe_str_eq(executioner, fsa_our_uname)) { + const char *uuid = get_uuid(target); + + send_stonith_update(NULL, target, uuid); + } else { + stonith_cleanup_list = g_list_append(stonith_cleanup_list, crm_strdup(target)); + } + } } } gboolean te_connect_stonith(gpointer user_data) { - int lpc = 0; - int rc = stonith_ok; - - if(stonith_api == NULL) { - stonith_api = stonith_api_new(); - } - - if(stonith_api->state != stonith_disconnected) { - crm_debug_2("Still connected"); - return TRUE; - } - - for(lpc = 0; lpc < 30; lpc++) { - crm_info("Attempting connection to fencing daemon..."); - - sleep(1); - rc = stonith_api->cmds->connect(stonith_api, crm_system_name, NULL); - - if(rc == stonith_ok) { - break; - } - - if(user_data != NULL) { - crm_err("Sign-in failed: triggered a retry"); - mainloop_set_trigger(stonith_reconnect); - return TRUE; - } - - crm_err("Sign-in failed: pausing and trying again in 2s..."); - sleep(1); - } - - CRM_CHECK(rc == stonith_ok, return TRUE); /* If not, we failed 30 times... just get out */ - stonith_api->cmds->register_notification( - stonith_api, T_STONITH_NOTIFY_DISCONNECT, tengine_stonith_connection_destroy); - - stonith_api->cmds->register_notification( - stonith_api, STONITH_OP_FENCE, tengine_stonith_notify); - - crm_info("Connected"); - return TRUE; + int lpc = 0; + int rc = stonith_ok; + + if (stonith_api == NULL) { + stonith_api = stonith_api_new(); + } + + if (stonith_api->state != stonith_disconnected) { + crm_debug_2("Still connected"); + return TRUE; + } + + for (lpc = 0; lpc < 30; lpc++) { + crm_info("Attempting connection to fencing daemon..."); + + sleep(1); + rc = stonith_api->cmds->connect(stonith_api, crm_system_name, NULL); + + if (rc == stonith_ok) { + break; + } + + if (user_data != NULL) { + crm_err("Sign-in failed: triggered a retry"); + mainloop_set_trigger(stonith_reconnect); + return TRUE; + } + + crm_err("Sign-in failed: pausing and trying again in 2s..."); + sleep(1); + } + + CRM_CHECK(rc == stonith_ok, return TRUE); /* If not, we failed 30 times... just get out */ + stonith_api->cmds->register_notification(stonith_api, T_STONITH_NOTIFY_DISCONNECT, + tengine_stonith_connection_destroy); + + stonith_api->cmds->register_notification(stonith_api, STONITH_OP_FENCE, tengine_stonith_notify); + + crm_info("Connected"); + return TRUE; } gboolean -stop_te_timer(crm_action_timer_t *timer) +stop_te_timer(crm_action_timer_t * timer) { - const char *timer_desc = "action timer"; - - if(timer == NULL) { - return FALSE; - } - if(timer->reason == timeout_abort) { - timer_desc = "global timer"; - crm_debug_2("Stopping %s", timer_desc); - } - - if(timer->source_id != 0) { - crm_debug_2("Stopping %s", timer_desc); - g_source_remove(timer->source_id); - timer->source_id = 0; - - } else { - crm_debug_2("%s was already stopped", timer_desc); - return FALSE; - } - - return TRUE; + const char *timer_desc = "action timer"; + + if (timer == NULL) { + return FALSE; + } + if (timer->reason == timeout_abort) { + timer_desc = "global timer"; + crm_debug_2("Stopping %s", timer_desc); + } + + if (timer->source_id != 0) { + crm_debug_2("Stopping %s", timer_desc); + g_source_remove(timer->source_id); + timer->source_id = 0; + + } else { + crm_debug_2("%s was already stopped", timer_desc); + return FALSE; + } + + return TRUE; } gboolean -te_graph_trigger(gpointer user_data) +te_graph_trigger(gpointer user_data) { enum transition_status graph_rc = -1; - if(transition_graph == NULL) { - crm_debug("Nothing to do"); - return TRUE; + + if (transition_graph == NULL) { + crm_debug("Nothing to do"); + return TRUE; } - - crm_debug_2("Invoking graph %d in state %s", - transition_graph->id, fsa_state2string(fsa_state)); - - switch(fsa_state) { - case S_STARTING: - case S_PENDING: - case S_NOT_DC: - case S_HALT: - case S_ILLEGAL: - case S_STOPPING: - case S_TERMINATE: - return TRUE; - break; - default: - break; + + crm_debug_2("Invoking graph %d in state %s", transition_graph->id, fsa_state2string(fsa_state)); + + switch (fsa_state) { + case S_STARTING: + case S_PENDING: + case S_NOT_DC: + case S_HALT: + case S_ILLEGAL: + case S_STOPPING: + case S_TERMINATE: + return TRUE; + break; + default: + break; } - - if(transition_graph->complete == FALSE) { - graph_rc = run_graph(transition_graph); - print_graph(LOG_DEBUG_3, transition_graph); - - if(graph_rc == transition_active) { - crm_debug_3("Transition not yet complete"); - return TRUE; - - } else if(graph_rc == transition_pending) { - crm_debug_3("Transition not yet complete - no actions fired"); - return TRUE; - } - - if(graph_rc != transition_complete) { - crm_err("Transition failed: %s", transition_status(graph_rc)); - print_graph(LOG_WARNING, transition_graph); - } + + if (transition_graph->complete == FALSE) { + graph_rc = run_graph(transition_graph); + print_graph(LOG_DEBUG_3, transition_graph); + + if (graph_rc == transition_active) { + crm_debug_3("Transition not yet complete"); + return TRUE; + + } else if (graph_rc == transition_pending) { + crm_debug_3("Transition not yet complete - no actions fired"); + return TRUE; + } + + if (graph_rc != transition_complete) { + crm_err("Transition failed: %s", transition_status(graph_rc)); + print_graph(LOG_WARNING, transition_graph); + } } - + crm_info("Transition %d is now complete", transition_graph->id); transition_graph->complete = TRUE; notify_crmd(transition_graph); - - return TRUE; + + return TRUE; } void -trigger_graph_processing(const char *fn, int line) +trigger_graph_processing(const char *fn, int line) { - mainloop_set_trigger(transition_trigger); - crm_debug_2("%s:%d - Triggered graph processing", fn, line); + mainloop_set_trigger(transition_trigger); + crm_debug_2("%s:%d - Triggered graph processing", fn, line); } void -abort_transition_graph( - int abort_priority, enum transition_action abort_action, - const char *abort_text, xmlNode *reason, const char *fn, int line) +abort_transition_graph(int abort_priority, enum transition_action abort_action, + const char *abort_text, xmlNode * reason, const char *fn, int line) { - int log_level = LOG_INFO; - const char *magic = NULL; - CRM_CHECK(transition_graph != NULL, return); - - if(reason) { - int diff_add_updates = 0; - int diff_add_epoch = 0; - int diff_add_admin_epoch = 0; - - int diff_del_updates = 0; - int diff_del_epoch = 0; - int diff_del_admin_epoch = 0; - xmlNode *diff = get_xpath_object("//"F_CIB_UPDATE_RESULT"//diff", reason, LOG_DEBUG_2); - magic = crm_element_value(reason, XML_ATTR_TRANSITION_MAGIC); - - if(diff) { - cib_diff_version_details( - diff, - &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, - &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); - if(crm_str_eq(TYPE(reason), XML_CIB_TAG_NVPAIR , TRUE)) { - do_crm_log(log_level, - "%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, name=%s, value=%s, magic=%s, cib=%d.%d.%d) : %s", - fn, line, transition_graph->complete, TYPE(reason), ID(reason), NAME(reason), VALUE(reason), magic?magic:"NA", - diff_add_admin_epoch,diff_add_epoch,diff_add_updates, abort_text); - } else { - do_crm_log(log_level, - "%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, magic=%s, cib=%d.%d.%d) : %s", - fn, line, transition_graph->complete, TYPE(reason), ID(reason), magic?magic:"NA", - diff_add_admin_epoch,diff_add_epoch,diff_add_updates, abort_text); - } - - } else { - do_crm_log(log_level, - "%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, magic=%s) : %s", - fn, line, transition_graph->complete, TYPE(reason), ID(reason), magic?magic:"NA", abort_text); - } - - } else { - do_crm_log(log_level, - "%s:%d - Triggered transition abort (complete=%d) : %s", - fn, line, transition_graph->complete, abort_text); - } - - switch(fsa_state) { - case S_STARTING: - case S_PENDING: - case S_NOT_DC: - case S_HALT: - case S_ILLEGAL: - case S_STOPPING: - case S_TERMINATE: - do_crm_log(log_level, - "Abort suppressed: state=%s (complete=%d)", - fsa_state2string(fsa_state), transition_graph->complete); - return; - default: - break; - } - - if(magic == NULL && reason != NULL) { - crm_log_xml(log_level+1, "Cause", reason); - } - - /* Make sure any queued calculations are discarded ASAP */ - crm_free(fsa_pe_ref); - fsa_pe_ref = NULL; - - if(transition_graph->complete) { - if(transition_timer->period_ms > 0) { - crm_timer_start(transition_timer); - } else { - register_fsa_input(C_FSA_INTERNAL, I_PE_CALC, NULL); - } - return; - } - - update_abort_priority( - transition_graph, abort_priority, abort_action, abort_text); - - mainloop_set_trigger(transition_trigger); -} + int log_level = LOG_INFO; + const char *magic = NULL; + + CRM_CHECK(transition_graph != NULL, return); + + if (reason) { + int diff_add_updates = 0; + int diff_add_epoch = 0; + int diff_add_admin_epoch = 0; + + int diff_del_updates = 0; + int diff_del_epoch = 0; + int diff_del_admin_epoch = 0; + xmlNode *diff = get_xpath_object("//" F_CIB_UPDATE_RESULT "//diff", reason, LOG_DEBUG_2); + + magic = crm_element_value(reason, XML_ATTR_TRANSITION_MAGIC); + + if (diff) { + cib_diff_version_details(diff, + &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, + &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); + if (crm_str_eq(TYPE(reason), XML_CIB_TAG_NVPAIR, TRUE)) { + do_crm_log(log_level, + "%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, name=%s, value=%s, magic=%s, cib=%d.%d.%d) : %s", + fn, line, transition_graph->complete, TYPE(reason), ID(reason), + NAME(reason), VALUE(reason), magic ? magic : "NA", diff_add_admin_epoch, + diff_add_epoch, diff_add_updates, abort_text); + } else { + do_crm_log(log_level, + "%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, magic=%s, cib=%d.%d.%d) : %s", + fn, line, transition_graph->complete, TYPE(reason), ID(reason), + magic ? magic : "NA", diff_add_admin_epoch, diff_add_epoch, + diff_add_updates, abort_text); + } + + } else { + do_crm_log(log_level, + "%s:%d - Triggered transition abort (complete=%d, tag=%s, id=%s, magic=%s) : %s", + fn, line, transition_graph->complete, TYPE(reason), ID(reason), + magic ? magic : "NA", abort_text); + } + } else { + do_crm_log(log_level, + "%s:%d - Triggered transition abort (complete=%d) : %s", + fn, line, transition_graph->complete, abort_text); + } + + switch (fsa_state) { + case S_STARTING: + case S_PENDING: + case S_NOT_DC: + case S_HALT: + case S_ILLEGAL: + case S_STOPPING: + case S_TERMINATE: + do_crm_log(log_level, + "Abort suppressed: state=%s (complete=%d)", + fsa_state2string(fsa_state), transition_graph->complete); + return; + default: + break; + } + + if (magic == NULL && reason != NULL) { + crm_log_xml(log_level + 1, "Cause", reason); + } + + /* Make sure any queued calculations are discarded ASAP */ + crm_free(fsa_pe_ref); + fsa_pe_ref = NULL; + + if (transition_graph->complete) { + if (transition_timer->period_ms > 0) { + crm_timer_start(transition_timer); + } else { + register_fsa_input(C_FSA_INTERNAL, I_PE_CALC, NULL); + } + return; + } + + update_abort_priority(transition_graph, abort_priority, abort_action, abort_text); + + mainloop_set_trigger(transition_trigger); +} diff --git a/crmd/tengine.c b/crmd/tengine.c index 81776be73e..de3501b37f 100644 --- a/crmd/tengine.c +++ b/crmd/tengine.c @@ -1,240 +1,235 @@ /* * 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 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 #include #include #include #include #include -#include /* for access */ +#include /* for access */ +#include /* for calls to open */ +#include /* for calls to open */ +#include /* for calls to open */ +#include /* for getpwuid */ +#include /* for initgroups */ -#include /* for calls to open */ -#include /* for calls to open */ -#include /* for calls to open */ -#include /* for getpwuid */ -#include /* for initgroups */ - -#include /* for getrlimit */ -#include /* for getrlimit */ +#include /* for getrlimit */ +#include /* for getrlimit */ #include #include #include #include #include #include #include #include #include - extern crm_graph_functions_t te_graph_fns; -struct crm_subsystem_s *te_subsystem = NULL; +struct crm_subsystem_s *te_subsystem = NULL; stonith_t *stonith_api = NULL; - -static void global_cib_callback(const xmlNode *msg, int callid ,int rc, xmlNode *output) +static void +global_cib_callback(const xmlNode * msg, int callid, int rc, xmlNode * output) { } -static crm_graph_t *create_blank_graph(void) +static crm_graph_t * +create_blank_graph(void) { crm_graph_t *a_graph = unpack_graph(NULL, NULL); + a_graph->complete = TRUE; a_graph->abort_reason = "DC Takeover"; a_graph->completion_action = tg_restart; - return a_graph; + return a_graph; } /* A_TE_START, A_TE_STOP, A_TE_RESTART */ void do_te_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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { gboolean init_ok = TRUE; - + cl_uuid_t new_uuid; char uuid_str[UU_UNPARSE_SIZEOF]; - - if(action & A_TE_STOP) { - if(transition_graph) { - destroy_graph(transition_graph); - transition_graph = NULL; - } - - if(fsa_cib_conn && cib_ok != fsa_cib_conn->cmds->del_notify_callback( - fsa_cib_conn, T_CIB_DIFF_NOTIFY, te_update_diff)) { - crm_err("Could not unset CIB notification callback"); - } - - clear_bit_inplace(fsa_input_register, te_subsystem->flag_connected); - crm_info("Transitioner is now inactive"); + + if (action & A_TE_STOP) { + if (transition_graph) { + destroy_graph(transition_graph); + transition_graph = NULL; + } + + if (fsa_cib_conn + && cib_ok != fsa_cib_conn->cmds->del_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY, + te_update_diff)) { + crm_err("Could not unset CIB notification callback"); + } + + clear_bit_inplace(fsa_input_register, te_subsystem->flag_connected); + crm_info("Transitioner is now inactive"); } - if((action & A_TE_START) == 0) { - return; + if ((action & A_TE_START) == 0) { + return; - } else if(is_set(fsa_input_register, te_subsystem->flag_connected)) { - crm_debug("The transitioner is already active"); - return; + } else if (is_set(fsa_input_register, te_subsystem->flag_connected)) { + crm_debug("The transitioner is already active"); + return; - } else if((action & A_TE_START) && cur_state == S_STOPPING) { - crm_info("Ignoring request to start %s while shutting down", - te_subsystem->name); - return; - } + } else if ((action & A_TE_START) && cur_state == S_STOPPING) { + crm_info("Ignoring request to start %s while shutting down", te_subsystem->name); + return; + } cl_uuid_generate(&new_uuid); cl_uuid_unparse(&new_uuid, uuid_str); te_uuid = crm_strdup(uuid_str); crm_info("Registering TE UUID: %s", te_uuid); - - if(transition_trigger == NULL) { - transition_trigger = mainloop_add_trigger( - G_PRIORITY_LOW, te_graph_trigger, NULL); + + if (transition_trigger == NULL) { + transition_trigger = mainloop_add_trigger(G_PRIORITY_LOW, te_graph_trigger, NULL); } - - if(cib_ok != fsa_cib_conn->cmds->add_notify_callback( - fsa_cib_conn, T_CIB_DIFF_NOTIFY, te_update_diff)) { - crm_err("Could not set CIB notification callback"); - init_ok = FALSE; + + if (cib_ok != + fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY, te_update_diff)) { + crm_err("Could not set CIB notification callback"); + init_ok = FALSE; } - if(cib_ok != fsa_cib_conn->cmds->set_op_callback(fsa_cib_conn, global_cib_callback)) { - crm_err("Could not set CIB global callback"); - init_ok = FALSE; + if (cib_ok != fsa_cib_conn->cmds->set_op_callback(fsa_cib_conn, global_cib_callback)) { + crm_err("Could not set CIB global callback"); + init_ok = FALSE; } - - if(init_ok) { - set_graph_functions(&te_graph_fns); - - if(transition_graph) { - destroy_graph(transition_graph); - } - - /* create a blank one */ - crm_debug("Transitioner is now active"); - transition_graph = create_blank_graph(); - set_bit_inplace(fsa_input_register, te_subsystem->flag_connected); + + if (init_ok) { + set_graph_functions(&te_graph_fns); + + if (transition_graph) { + destroy_graph(transition_graph); + } + + /* create a blank one */ + crm_debug("Transitioner is now active"); + transition_graph = create_blank_graph(); + set_bit_inplace(fsa_input_register, te_subsystem->flag_connected); } } /* A_TE_INVOKE, A_TE_CANCEL */ void do_te_invoke(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) + enum crmd_fsa_cause cause, + enum crmd_fsa_state cur_state, + enum crmd_fsa_input current_input, fsa_data_t * msg_data) { - - if(AM_I_DC == FALSE - || (fsa_state != S_TRANSITION_ENGINE && (action & A_TE_INVOKE))) { - crm_notice("No need to invoke the TE (%s) in state %s", - fsa_action2string(action), - fsa_state2string(fsa_state)); - return; - } - - if(action & A_TE_CANCEL) { - crm_debug("Cancelling the transition: %s", - transition_graph->complete?"inactive":"active"); - abort_transition(INFINITY, tg_restart, "Peer Cancelled", NULL); - if(transition_graph->complete == FALSE) { - crmd_fsa_stall(NULL); - } - - } else if(action & A_TE_HALT) { - crm_debug("Halting the transition: %s", - transition_graph->complete?"inactive":"active"); - abort_transition(INFINITY, tg_stop, "Peer Halt", NULL); - if(transition_graph->complete == FALSE) { - crmd_fsa_stall(NULL); - } - - } else if(action & A_TE_INVOKE) { - const char *value = NULL; - xmlNode *graph_data = NULL; - ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg); - const char *ref = crm_element_value(input->msg, XML_ATTR_REFERENCE); - const char *graph_file = crm_element_value(input->msg, F_CRM_TGRAPH); - const char *graph_input = crm_element_value(input->msg, F_CRM_TGRAPH_INPUT); - - if(graph_file == NULL && input->xml == NULL) { - crm_log_xml_err(input->msg, "Bad command"); - register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); - return; - } - - if(transition_graph->complete == FALSE) { - crm_info("Another transition is already active"); - abort_transition(INFINITY, tg_restart, "Transition Active", NULL); - return; - } - - if(fsa_pe_ref == NULL || safe_str_neq(fsa_pe_ref, ref)) { - crm_info("Transition is redundant: %s vs. %s", crm_str(fsa_pe_ref), crm_str(ref)); - abort_transition(INFINITY, tg_restart, "Transition Redundant", NULL); - } - - graph_data = input->xml; - - if(graph_data == NULL && graph_file != NULL) { - graph_data = filename2xml(graph_file); - } - - CRM_CHECK(graph_data != NULL, - crm_err("Input raised by %s is invalid", msg_data->origin); - crm_log_xml_err(input->msg, "Bad command"); - return); - - destroy_graph(transition_graph); - transition_graph = unpack_graph(graph_data, graph_input); - CRM_CHECK(transition_graph != NULL, transition_graph = create_blank_graph(); return); - crm_info("Processing graph %d (ref=%s) derived from %s", transition_graph->id, ref, graph_input); - - value = crm_element_value(graph_data, "failed-stop-offset"); - if(value) { - crm_free(failed_stop_offset); - failed_stop_offset = crm_strdup(value); - } - - value = crm_element_value(graph_data, "failed-start-offset"); - if(value) { - crm_free(failed_start_offset); - failed_start_offset = crm_strdup(value); - } - - trigger_graph(); - print_graph(LOG_DEBUG_2, transition_graph); - - if(graph_data != input->xml) { - free_xml(graph_data); - } - } + + if (AM_I_DC == FALSE || (fsa_state != S_TRANSITION_ENGINE && (action & A_TE_INVOKE))) { + crm_notice("No need to invoke the TE (%s) in state %s", + fsa_action2string(action), fsa_state2string(fsa_state)); + return; + } + + if (action & A_TE_CANCEL) { + crm_debug("Cancelling the transition: %s", + transition_graph->complete ? "inactive" : "active"); + abort_transition(INFINITY, tg_restart, "Peer Cancelled", NULL); + if (transition_graph->complete == FALSE) { + crmd_fsa_stall(NULL); + } + + } else if (action & A_TE_HALT) { + crm_debug("Halting the transition: %s", transition_graph->complete ? "inactive" : "active"); + abort_transition(INFINITY, tg_stop, "Peer Halt", NULL); + if (transition_graph->complete == FALSE) { + crmd_fsa_stall(NULL); + } + + } else if (action & A_TE_INVOKE) { + const char *value = NULL; + xmlNode *graph_data = NULL; + ha_msg_input_t *input = fsa_typed_data(fsa_dt_ha_msg); + const char *ref = crm_element_value(input->msg, XML_ATTR_REFERENCE); + const char *graph_file = crm_element_value(input->msg, F_CRM_TGRAPH); + const char *graph_input = crm_element_value(input->msg, F_CRM_TGRAPH_INPUT); + + if (graph_file == NULL && input->xml == NULL) { + crm_log_xml_err(input->msg, "Bad command"); + register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL); + return; + } + + if (transition_graph->complete == FALSE) { + crm_info("Another transition is already active"); + abort_transition(INFINITY, tg_restart, "Transition Active", NULL); + return; + } + + if (fsa_pe_ref == NULL || safe_str_neq(fsa_pe_ref, ref)) { + crm_info("Transition is redundant: %s vs. %s", crm_str(fsa_pe_ref), crm_str(ref)); + abort_transition(INFINITY, tg_restart, "Transition Redundant", NULL); + } + + graph_data = input->xml; + + if (graph_data == NULL && graph_file != NULL) { + graph_data = filename2xml(graph_file); + } + + CRM_CHECK(graph_data != NULL, + crm_err("Input raised by %s is invalid", msg_data->origin); + crm_log_xml_err(input->msg, "Bad command"); + return); + + destroy_graph(transition_graph); + transition_graph = unpack_graph(graph_data, graph_input); + CRM_CHECK(transition_graph != NULL, transition_graph = create_blank_graph(); return); + crm_info("Processing graph %d (ref=%s) derived from %s", transition_graph->id, ref, + graph_input); + + value = crm_element_value(graph_data, "failed-stop-offset"); + if (value) { + crm_free(failed_stop_offset); + failed_stop_offset = crm_strdup(value); + } + + value = crm_element_value(graph_data, "failed-start-offset"); + if (value) { + crm_free(failed_start_offset); + failed_start_offset = crm_strdup(value); + } + + trigger_graph(); + print_graph(LOG_DEBUG_2, transition_graph); + + if (graph_data != input->xml) { + free_xml(graph_data); + } + } } diff --git a/crmd/utils.c b/crmd/utils.c index b8e7cc252e..da7cc745a5 100644 --- a/crmd/utils.c +++ b/crmd/utils.c @@ -1,1302 +1,1197 @@ /* * 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 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include <../tools/attrd.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) + 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); + 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_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_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); + } + + /* 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) +get_timer_desc(fsa_timer_t * timer) { - if(timer == election_trigger) { - return "Election Trigger"; + 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 == 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 == integration_timer) { - return "Integration Timer"; + } else if (timer == finalization_timer) { + return "Finalization Timer"; - } else if(timer == finalization_timer) { - return "Finalization Timer"; + } else if (timer == transition_timer) { + return "New Transition Timer"; - } else if(timer == transition_timer) { - return "New Transition Timer"; + } else if (timer == wait_timer) { + return "Wait Timer"; - } else if(timer == wait_timer) { - return "Wait Timer"; + } else if (timer == recheck_timer) { + return "PEngine Recheck Timer"; - } else if(timer == recheck_timer) { - return "PEngine Recheck Timer"; - - } - return "Unknown 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); - - } 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->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_debug_3("Triggering FSA: %s", __FUNCTION__); - mainloop_set_trigger(fsa_source); - - return TRUE; + 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); + + } 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->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_debug_3("Triggering FSA: %s", __FUNCTION__); + mainloop_set_trigger(fsa_source); + + return TRUE; } gboolean -crm_timer_start(fsa_timer_t *timer) +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; -} + 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) +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_debug_2("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_debug_2("%s (%s:%dms) already stopped", - timer_desc, fsa_input2string(timer->fsa_input), - timer->period_ms); - return FALSE; - } - return TRUE; + 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_debug_2("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_debug_2("%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 = ""; - } - - return inputAsText; + 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 = ""; + } + + 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 = ""; - } - - return stateAsText; + 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 = ""; + } + + 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 = ""; - } - - return causeAsText; + 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 = ""; + } + + 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 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 = ""; - } - - return actionAsText; -} + 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 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 = ""; + } + 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)) { - do_crm_log_unlikely(log_level, - "%s %.16llx (R_THE_DC)", text, R_THE_DC); - } - if(is_set(input_register, R_STARTING)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_STARTING)", - text, R_STARTING); - } - if(is_set(input_register, R_SHUTDOWN)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_SHUTDOWN)", - text, R_SHUTDOWN); - } - if(is_set(input_register, R_STAYDOWN)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_STAYDOWN)", - text, R_STAYDOWN); - } - if(is_set(input_register, R_JOIN_OK)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_JOIN_OK)", - text, R_JOIN_OK); - } - if(is_set(input_register, R_READ_CONFIG)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_READ_CONFIG)", - text, R_READ_CONFIG); - } - if(is_set(input_register, R_INVOKE_PE)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_INVOKE_PE)", - text, R_INVOKE_PE); - } - if(is_set(input_register, R_CIB_CONNECTED)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_CIB_CONNECTED)", - text, R_CIB_CONNECTED); - } - if(is_set(input_register, R_PE_CONNECTED)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_PE_CONNECTED)", - text, R_PE_CONNECTED); - } - if(is_set(input_register, R_TE_CONNECTED)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_TE_CONNECTED)", - text, R_TE_CONNECTED); - } - if(is_set(input_register, R_LRM_CONNECTED)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_LRM_CONNECTED)", - text, R_LRM_CONNECTED); - } - if(is_set(input_register, R_CIB_REQUIRED)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_CIB_REQUIRED)", - text, R_CIB_REQUIRED); - } - if(is_set(input_register, R_PE_REQUIRED)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_PE_REQUIRED)", - text, R_PE_REQUIRED); - } - if(is_set(input_register, R_TE_REQUIRED)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_TE_REQUIRED)", - text, R_TE_REQUIRED); - } - if(is_set(input_register, R_REQ_PEND)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_REQ_PEND)", - text, R_REQ_PEND); - } - if(is_set(input_register, R_PE_PEND)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_PE_PEND)", - text, R_PE_PEND); - } - if(is_set(input_register, R_TE_PEND)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_TE_PEND)", - text, R_TE_PEND); - } - if(is_set(input_register, R_RESP_PEND)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_RESP_PEND)", - text, R_RESP_PEND); - } - if(is_set(input_register, R_CIB_DONE)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_CIB_DONE)", - text, R_CIB_DONE); - } - if(is_set(input_register, R_HAVE_CIB)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_HAVE_CIB)", - text, R_HAVE_CIB); - } - if(is_set(input_register, R_CIB_ASKED)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_CIB_ASKED)", - text, R_CIB_ASKED); - } - if(is_set(input_register, R_CCM_DATA)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_CCM_DATA)", - text, R_CCM_DATA); - } - if(is_set(input_register, R_PEER_DATA)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_PEER_DATA)", - text, R_PEER_DATA); - } - if(is_set(input_register, R_IN_RECOVERY)) { - do_crm_log_unlikely(log_level, "%s %.16llx (R_IN_RECOVERY)", - text, R_IN_RECOVERY); - } + if (input_register == A_NOTHING) { + return; + } + if (text == NULL) { + text = "Input register contents:"; + } + + if (is_set(input_register, R_THE_DC)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_THE_DC)", text, R_THE_DC); + } + if (is_set(input_register, R_STARTING)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_STARTING)", text, R_STARTING); + } + if (is_set(input_register, R_SHUTDOWN)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_SHUTDOWN)", text, R_SHUTDOWN); + } + if (is_set(input_register, R_STAYDOWN)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_STAYDOWN)", text, R_STAYDOWN); + } + if (is_set(input_register, R_JOIN_OK)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_JOIN_OK)", text, R_JOIN_OK); + } + if (is_set(input_register, R_READ_CONFIG)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_READ_CONFIG)", text, R_READ_CONFIG); + } + if (is_set(input_register, R_INVOKE_PE)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_INVOKE_PE)", text, R_INVOKE_PE); + } + if (is_set(input_register, R_CIB_CONNECTED)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_CIB_CONNECTED)", text, R_CIB_CONNECTED); + } + if (is_set(input_register, R_PE_CONNECTED)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_PE_CONNECTED)", text, R_PE_CONNECTED); + } + if (is_set(input_register, R_TE_CONNECTED)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_TE_CONNECTED)", text, R_TE_CONNECTED); + } + if (is_set(input_register, R_LRM_CONNECTED)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_LRM_CONNECTED)", text, R_LRM_CONNECTED); + } + if (is_set(input_register, R_CIB_REQUIRED)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_CIB_REQUIRED)", text, R_CIB_REQUIRED); + } + if (is_set(input_register, R_PE_REQUIRED)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_PE_REQUIRED)", text, R_PE_REQUIRED); + } + if (is_set(input_register, R_TE_REQUIRED)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_TE_REQUIRED)", text, R_TE_REQUIRED); + } + if (is_set(input_register, R_REQ_PEND)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_REQ_PEND)", text, R_REQ_PEND); + } + if (is_set(input_register, R_PE_PEND)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_PE_PEND)", text, R_PE_PEND); + } + if (is_set(input_register, R_TE_PEND)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_TE_PEND)", text, R_TE_PEND); + } + if (is_set(input_register, R_RESP_PEND)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_RESP_PEND)", text, R_RESP_PEND); + } + if (is_set(input_register, R_CIB_DONE)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_CIB_DONE)", text, R_CIB_DONE); + } + if (is_set(input_register, R_HAVE_CIB)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_HAVE_CIB)", text, R_HAVE_CIB); + } + if (is_set(input_register, R_CIB_ASKED)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_CIB_ASKED)", text, R_CIB_ASKED); + } + if (is_set(input_register, R_CCM_DATA)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_CCM_DATA)", text, R_CCM_DATA); + } + if (is_set(input_register, R_PEER_DATA)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_PEER_DATA)", text, R_PEER_DATA); + } + if (is_set(input_register, R_IN_RECOVERY)) { + do_crm_log_unlikely(log_level, "%s %.16llx (R_IN_RECOVERY)", text, R_IN_RECOVERY); + } } void fsa_dump_actions(long long action, const char *text) { - int log_level = LOG_DEBUG_3; - - if(is_set(action, A_READCONFIG)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_READCONFIG) %s", A_READCONFIG, text); - } - if(is_set(action, A_STARTUP)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_STARTUP) %s", A_STARTUP, text); - } - if(is_set(action, A_STARTED)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_STARTED) %s", A_STARTED, text); - } - if(is_set(action, A_HA_CONNECT)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_CONNECT) %s", A_HA_CONNECT, text); - } - if(is_set(action, A_HA_DISCONNECT)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DISCONNECT) %s", - A_HA_DISCONNECT, text); - } - if(is_set(action, A_LRM_CONNECT)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_LRM_CONNECT) %s", - A_LRM_CONNECT, text); - } - if(is_set(action, A_LRM_EVENT)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_LRM_EVENT) %s", - A_LRM_EVENT, text); - } - if(is_set(action, A_LRM_INVOKE)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_LRM_INVOKE) %s", - A_LRM_INVOKE, text); - } - if(is_set(action, A_LRM_DISCONNECT)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_LRM_DISCONNECT) %s", - A_LRM_DISCONNECT, text); - } - if(is_set(action, A_DC_TIMER_STOP)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_TIMER_STOP) %s", - A_DC_TIMER_STOP, text); - } - if(is_set(action, A_DC_TIMER_START)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_TIMER_START) %s", - A_DC_TIMER_START, text); - } - if(is_set(action, A_INTEGRATE_TIMER_START)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_INTEGRATE_TIMER_START) %s", - A_INTEGRATE_TIMER_START, text); - } - if(is_set(action, A_INTEGRATE_TIMER_STOP)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_INTEGRATE_TIMER_STOP) %s", - A_INTEGRATE_TIMER_STOP, text); - } - if(is_set(action, A_FINALIZE_TIMER_START)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_FINALIZE_TIMER_START) %s", - A_FINALIZE_TIMER_START, text); - } - if(is_set(action, A_FINALIZE_TIMER_STOP)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_FINALIZE_TIMER_STOP) %s", - A_FINALIZE_TIMER_STOP, text); - } - if(is_set(action, A_ELECTION_COUNT)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_ELECTION_COUNT) %s", - A_ELECTION_COUNT, text); - } - if(is_set(action, A_ELECTION_VOTE)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_ELECTION_VOTE) %s", - A_ELECTION_VOTE, text); - } - if(is_set(action, A_ELECTION_CHECK)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_ELECTION_CHECK) %s", - A_ELECTION_CHECK, text); - } - if(is_set(action, A_CL_JOIN_ANNOUNCE)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_CL_JOIN_ANNOUNCE) %s", - A_CL_JOIN_ANNOUNCE, text); - } - if(is_set(action, A_CL_JOIN_REQUEST)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_CL_JOIN_REQUEST) %s", - A_CL_JOIN_REQUEST, text); - } - if(is_set(action, A_CL_JOIN_RESULT)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_CL_JOIN_RESULT) %s", - A_CL_JOIN_RESULT, text); - } - if(is_set(action, A_DC_JOIN_OFFER_ALL)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_JOIN_OFFER_ALL) %s", - A_DC_JOIN_OFFER_ALL, text); - } - if(is_set(action, A_DC_JOIN_OFFER_ONE)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_JOIN_OFFER_ONE) %s", - A_DC_JOIN_OFFER_ONE, text); - } - if(is_set(action, A_DC_JOIN_PROCESS_REQ)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_JOIN_PROCESS_REQ) %s", - A_DC_JOIN_PROCESS_REQ, text); - } - if(is_set(action, A_DC_JOIN_PROCESS_ACK)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_JOIN_PROCESS_ACK) %s", - A_DC_JOIN_PROCESS_ACK, text); - } - if(is_set(action, A_DC_JOIN_FINALIZE)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_JOIN_FINALIZE) %s", - A_DC_JOIN_FINALIZE, text); - } - if(is_set(action, A_MSG_PROCESS)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_MSG_PROCESS) %s", - A_MSG_PROCESS, text); - } - if(is_set(action, A_MSG_ROUTE)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_MSG_ROUTE) %s", - A_MSG_ROUTE, text); - } - if(is_set(action, A_RECOVER)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_RECOVER) %s", - A_RECOVER, text); - } - if(is_set(action, A_DC_RELEASE)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_RELEASE) %s", - A_DC_RELEASE, text); - } - if(is_set(action, A_DC_RELEASED)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_RELEASED) %s", - A_DC_RELEASED, text); - } - if(is_set(action, A_DC_TAKEOVER)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_DC_TAKEOVER) %s", - A_DC_TAKEOVER, text); - } - if(is_set(action, A_SHUTDOWN)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_SHUTDOWN) %s", A_SHUTDOWN, text); - } - if(is_set(action, A_SHUTDOWN_REQ)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_SHUTDOWN_REQ) %s", - A_SHUTDOWN_REQ, text); - } - if(is_set(action, A_STOP)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_STOP ) %s", A_STOP , text); - } - if(is_set(action, A_EXIT_0)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_EXIT_0) %s", A_EXIT_0, text); - } - if(is_set(action, A_EXIT_1)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_EXIT_1) %s", A_EXIT_1, text); - } - if(is_set(action, A_CCM_CONNECT)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_CCM_CONNECT) %s", - A_CCM_CONNECT, text); - } - if(is_set(action, A_CCM_DISCONNECT)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_CCM_DISCONNECT) %s", - A_CCM_DISCONNECT, text); - } - if(is_set(action, A_CIB_START)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_CIB_START) %s", - A_CIB_START, text); - } - if(is_set(action, A_CIB_STOP)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_CIB_STOP) %s", A_CIB_STOP, text); - } - if(is_set(action, A_TE_INVOKE)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_TE_INVOKE) %s", A_TE_INVOKE, text); - } - if(is_set(action, A_TE_START)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_TE_START) %s", - A_TE_START, text); - } - if(is_set(action, A_TE_STOP)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_TE_STOP) %s", A_TE_STOP, text); - } - if(is_set(action, A_TE_CANCEL)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_TE_CANCEL) %s", - A_TE_CANCEL, text); - } - if(is_set(action, A_PE_INVOKE)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_PE_INVOKE) %s", - A_PE_INVOKE, text); - } - if(is_set(action, A_PE_START)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_PE_START) %s", A_PE_START, text); - } - if(is_set(action, A_PE_STOP)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_PE_STOP) %s", A_PE_STOP, text); - } - if(is_set(action, A_NODE_BLOCK)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_NODE_BLOCK) %s", - A_NODE_BLOCK, text); - } - if(is_set(action, A_UPDATE_NODESTATUS)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_UPDATE_NODESTATUS) %s", - A_UPDATE_NODESTATUS, text); - } - if(is_set(action, A_LOG)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_LOG ) %s", A_LOG, text); - } - if(is_set(action, A_ERROR)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_ERROR ) %s", A_ERROR, text); - } - if(is_set(action, A_WARN)) { - do_crm_log_unlikely(log_level, - "Action %.16llx (A_WARN ) %s", A_WARN, text); - } -} + int log_level = LOG_DEBUG_3; + if (is_set(action, A_READCONFIG)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_READCONFIG) %s", A_READCONFIG, text); + } + if (is_set(action, A_STARTUP)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_STARTUP) %s", A_STARTUP, text); + } + if (is_set(action, A_STARTED)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_STARTED) %s", A_STARTED, text); + } + if (is_set(action, A_HA_CONNECT)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_CONNECT) %s", A_HA_CONNECT, text); + } + if (is_set(action, A_HA_DISCONNECT)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_DISCONNECT) %s", A_HA_DISCONNECT, text); + } + if (is_set(action, A_LRM_CONNECT)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_LRM_CONNECT) %s", A_LRM_CONNECT, text); + } + if (is_set(action, A_LRM_EVENT)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_LRM_EVENT) %s", A_LRM_EVENT, text); + } + if (is_set(action, A_LRM_INVOKE)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_LRM_INVOKE) %s", A_LRM_INVOKE, text); + } + if (is_set(action, A_LRM_DISCONNECT)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_LRM_DISCONNECT) %s", A_LRM_DISCONNECT, text); + } + if (is_set(action, A_DC_TIMER_STOP)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_DC_TIMER_STOP) %s", A_DC_TIMER_STOP, text); + } + if (is_set(action, A_DC_TIMER_START)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_DC_TIMER_START) %s", A_DC_TIMER_START, text); + } + if (is_set(action, A_INTEGRATE_TIMER_START)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_INTEGRATE_TIMER_START) %s", + A_INTEGRATE_TIMER_START, text); + } + if (is_set(action, A_INTEGRATE_TIMER_STOP)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_INTEGRATE_TIMER_STOP) %s", + A_INTEGRATE_TIMER_STOP, text); + } + if (is_set(action, A_FINALIZE_TIMER_START)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_FINALIZE_TIMER_START) %s", + A_FINALIZE_TIMER_START, text); + } + if (is_set(action, A_FINALIZE_TIMER_STOP)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_FINALIZE_TIMER_STOP) %s", + A_FINALIZE_TIMER_STOP, text); + } + if (is_set(action, A_ELECTION_COUNT)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_ELECTION_COUNT) %s", A_ELECTION_COUNT, text); + } + if (is_set(action, A_ELECTION_VOTE)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_ELECTION_VOTE) %s", A_ELECTION_VOTE, text); + } + if (is_set(action, A_ELECTION_CHECK)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_ELECTION_CHECK) %s", A_ELECTION_CHECK, text); + } + if (is_set(action, A_CL_JOIN_ANNOUNCE)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_CL_JOIN_ANNOUNCE) %s", A_CL_JOIN_ANNOUNCE, text); + } + if (is_set(action, A_CL_JOIN_REQUEST)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_CL_JOIN_REQUEST) %s", A_CL_JOIN_REQUEST, text); + } + if (is_set(action, A_CL_JOIN_RESULT)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_CL_JOIN_RESULT) %s", A_CL_JOIN_RESULT, text); + } + if (is_set(action, A_DC_JOIN_OFFER_ALL)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_DC_JOIN_OFFER_ALL) %s", A_DC_JOIN_OFFER_ALL, text); + } + if (is_set(action, A_DC_JOIN_OFFER_ONE)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_DC_JOIN_OFFER_ONE) %s", A_DC_JOIN_OFFER_ONE, text); + } + if (is_set(action, A_DC_JOIN_PROCESS_REQ)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_DC_JOIN_PROCESS_REQ) %s", + A_DC_JOIN_PROCESS_REQ, text); + } + if (is_set(action, A_DC_JOIN_PROCESS_ACK)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_DC_JOIN_PROCESS_ACK) %s", + A_DC_JOIN_PROCESS_ACK, text); + } + if (is_set(action, A_DC_JOIN_FINALIZE)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_DC_JOIN_FINALIZE) %s", A_DC_JOIN_FINALIZE, text); + } + if (is_set(action, A_MSG_PROCESS)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_MSG_PROCESS) %s", A_MSG_PROCESS, text); + } + if (is_set(action, A_MSG_ROUTE)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_MSG_ROUTE) %s", A_MSG_ROUTE, text); + } + if (is_set(action, A_RECOVER)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_RECOVER) %s", A_RECOVER, text); + } + if (is_set(action, A_DC_RELEASE)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_DC_RELEASE) %s", A_DC_RELEASE, text); + } + if (is_set(action, A_DC_RELEASED)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_DC_RELEASED) %s", A_DC_RELEASED, text); + } + if (is_set(action, A_DC_TAKEOVER)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_DC_TAKEOVER) %s", A_DC_TAKEOVER, text); + } + if (is_set(action, A_SHUTDOWN)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_SHUTDOWN) %s", A_SHUTDOWN, text); + } + if (is_set(action, A_SHUTDOWN_REQ)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_SHUTDOWN_REQ) %s", A_SHUTDOWN_REQ, text); + } + if (is_set(action, A_STOP)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_STOP ) %s", A_STOP, text); + } + if (is_set(action, A_EXIT_0)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_EXIT_0) %s", A_EXIT_0, text); + } + if (is_set(action, A_EXIT_1)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_EXIT_1) %s", A_EXIT_1, text); + } + if (is_set(action, A_CCM_CONNECT)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_CCM_CONNECT) %s", A_CCM_CONNECT, text); + } + if (is_set(action, A_CCM_DISCONNECT)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_CCM_DISCONNECT) %s", A_CCM_DISCONNECT, text); + } + if (is_set(action, A_CIB_START)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_CIB_START) %s", A_CIB_START, text); + } + if (is_set(action, A_CIB_STOP)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_CIB_STOP) %s", A_CIB_STOP, text); + } + if (is_set(action, A_TE_INVOKE)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_TE_INVOKE) %s", A_TE_INVOKE, text); + } + if (is_set(action, A_TE_START)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_TE_START) %s", A_TE_START, text); + } + if (is_set(action, A_TE_STOP)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_TE_STOP) %s", A_TE_STOP, text); + } + if (is_set(action, A_TE_CANCEL)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_TE_CANCEL) %s", A_TE_CANCEL, text); + } + if (is_set(action, A_PE_INVOKE)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_PE_INVOKE) %s", A_PE_INVOKE, text); + } + if (is_set(action, A_PE_START)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_PE_START) %s", A_PE_START, text); + } + if (is_set(action, A_PE_STOP)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_PE_STOP) %s", A_PE_STOP, text); + } + if (is_set(action, A_NODE_BLOCK)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_NODE_BLOCK) %s", A_NODE_BLOCK, text); + } + if (is_set(action, A_UPDATE_NODESTATUS)) { + do_crm_log_unlikely(log_level, + "Action %.16llx (A_UPDATE_NODESTATUS) %s", A_UPDATE_NODESTATUS, text); + } + if (is_set(action, A_LOG)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_LOG ) %s", A_LOG, text); + } + if (is_set(action, A_ERROR)) { + do_crm_log_unlikely(log_level, "Action %.16llx (A_ERROR ) %s", A_ERROR, text); + } + if (is_set(action, A_WARN)) { + do_crm_log_unlikely(log_level, "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_debug_3("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); - + + /* 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_debug_3("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 *ha_state, const char *ccm_state, - const char *crmd_state, const char *join_state, const char *exp_state, - gboolean clear_shutdown, const char *src) +xmlNode * +create_node_state(const char *uname, const char *ha_state, const char *ccm_state, + const char *crmd_state, 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_debug_2("%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_CIB_ATTR_HASTATE, ha_state); - crm_xml_add(node_state, XML_CIB_ATTR_INCCM, ccm_state); - crm_xml_add(node_state, XML_CIB_ATTR_CRMDSTATE, crmd_state); - crm_xml_add(node_state, XML_CIB_ATTR_JOINSTATE, join_state); - crm_xml_add(node_state, XML_CIB_ATTR_EXPSTATE, 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_debug_3(node_state, "created"); - - return node_state; + xmlNode *node_state = create_xml_node(NULL, XML_CIB_TAG_STATE); + + crm_debug_2("%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_CIB_ATTR_HASTATE, ha_state); + crm_xml_add(node_state, XML_CIB_ATTR_INCCM, ccm_state); + crm_xml_add(node_state, XML_CIB_ATTR_CRMDSTATE, crmd_state); + crm_xml_add(node_state, XML_CIB_ATTR_JOINSTATE, join_state); + crm_xml_add(node_state, XML_CIB_ATTR_EXPSTATE, 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_debug_3(node_state, "created"); + + return node_state; } -extern GHashTable *ipc_clients; +extern GHashTable *ipc_clients; void -process_client_disconnect(crmd_client_t *curr_client) +process_client_disconnect(crmd_client_t * curr_client) { - struct crm_subsystem_s *the_subsystem = NULL; - - CRM_CHECK(curr_client != NULL, return); - crm_debug_2("received HUP from %s", curr_client->table_key); - - if (curr_client->sub_sys == NULL) { - crm_debug_2("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->ipc = 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_debug_2("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); - } + struct crm_subsystem_s *the_subsystem = NULL; + + CRM_CHECK(curr_client != NULL, return); + crm_debug_2("received HUP from %s", curr_client->table_key); + + if (curr_client->sub_sys == NULL) { + crm_debug_2("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->ipc = 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_debug_2("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) +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; - } - } - - crm_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 = crm_strdup(welcome_from); - } - if(dc_version != NULL) { - fsa_our_dc_version = crm_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_info("Unset DC %s", crm_str(last_dc)); - } - - crm_free(last_dc); - return TRUE; + 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; + } + } + + crm_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 = crm_strdup(welcome_from); + } + if (dc_version != NULL) { + fsa_our_dc_version = crm_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_info("Unset DC %s", crm_str(last_dc)); + } + + crm_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) +erase_xpath_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data) { char *xpath = user_data; - do_crm_log(rc==0?LOG_INFO:LOG_NOTICE, - "Deletion of \"%s\": %s (rc=%d)", xpath, cib_error2string(rc), rc); + + do_crm_log(rc == 0 ? LOG_INFO : LOG_NOTICE, + "Deletion of \"%s\": %s (rc=%d)", xpath, cib_error2string(rc), rc); crm_free(xpath); } -void erase_status_tag(const char *uname, const char *tag, int options) +void +erase_status_tag(const char *uname, const char *tag, int options) { int rc = cib_ok; char xpath[STATUS_PATH_MAX]; - int cib_opts = cib_quorum_override|cib_xpath|options; + 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); - rc = fsa_cib_conn->cmds->delete(fsa_cib_conn, xpath, NULL, cib_opts); - add_cib_op_callback(fsa_cib_conn, rc, FALSE, crm_strdup(xpath), erase_xpath_callback); + if (fsa_cib_conn && uname) { + snprintf(xpath, STATUS_PATH_MAX, "//node_state[@uname='%s']/%s", uname, tag); + rc = fsa_cib_conn->cmds->delete(fsa_cib_conn, xpath, NULL, cib_opts); + add_cib_op_callback(fsa_cib_conn, rc, FALSE, crm_strdup(xpath), erase_xpath_callback); } } static IPC_Channel *attrd = NULL; static gboolean -attrd_dispatch(IPC_Channel *client, gpointer user_data) +attrd_dispatch(IPC_Channel * client, gpointer user_data) { xmlNode *msg = NULL; gboolean stay_connected = TRUE; - - while(IPC_ISRCONN(client)) { - if(client->ops->is_message_pending(client) == 0) { - break; - } - - msg = xmlfromIPC(client, MAX_IPC_DELAY); - if (msg != NULL) { - crm_log_xml_err(msg, "attrd:msg"); - free_xml(msg); - } - } - + + while (IPC_ISRCONN(client)) { + if (client->ops->is_message_pending(client) == 0) { + break; + } + + msg = xmlfromIPC(client, MAX_IPC_DELAY); + if (msg != NULL) { + crm_log_xml_err(msg, "attrd:msg"); + free_xml(msg); + } + } + if (client->ch_status != IPC_CONNECT) { - stay_connected = FALSE; + stay_connected = FALSE; } return stay_connected; } static void attrd_connection_destroy(gpointer user_data) { crm_err("Lost connection to attrd"); attrd = NULL; return; } void update_attrd(const char *host, const char *name, const char *value, const char *user_name) -{ +{ int retries = 5; gboolean rc = FALSE; retry: - if(attrd == NULL) { - crm_info("Connecting to attrd..."); - attrd = init_client_ipc_comms_nodispatch(T_ATTRD); - if(attrd) { - G_main_add_IPC_Channel( - G_PRIORITY_LOW, attrd, FALSE, attrd_dispatch, NULL, attrd_connection_destroy); - } - } - - if(attrd != NULL) { - rc = attrd_update_delegate(attrd, 'U', host, name, value, XML_CIB_TAG_STATUS, NULL, NULL, user_name); - + if (attrd == NULL) { + crm_info("Connecting to attrd..."); + attrd = init_client_ipc_comms_nodispatch(T_ATTRD); + if (attrd) { + G_main_add_IPC_Channel(G_PRIORITY_LOW, attrd, FALSE, attrd_dispatch, NULL, + attrd_connection_destroy); + } + } + + if (attrd != NULL) { + rc = attrd_update_delegate(attrd, 'U', host, name, value, XML_CIB_TAG_STATUS, NULL, NULL, + user_name); + } else { - crm_warn("Could not connect to %s", T_ATTRD); + crm_warn("Could not connect to %s", T_ATTRD); } - if(rc == FALSE) { - crm_err("Could not send %s %s", T_ATTRD, name?"update":"refresh"); - attrd = NULL; - - if(retries > 0) { - retries--; - sleep(1); - goto retry; - } + if (rc == FALSE) { + crm_err("Could not send %s %s", T_ATTRD, name ? "update" : "refresh"); + attrd = NULL; + + if (retries > 0) { + retries--; + sleep(1); + goto retry; + } } - + }