diff --git a/crm/crmd/callbacks.c b/crm/crmd/callbacks.c index 8ef5bb9ab3..3f54dcb2ec 100644 --- a/crm/crmd/callbacks.c +++ b/crm/crmd/callbacks.c @@ -1,553 +1,553 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include FILE *msg_in_strm = NULL; FILE *msg_ipc_strm = NULL; xmlNodePtr find_xml_in_hamessage(const struct ha_msg* msg); void crmd_ha_connection_destroy(gpointer user_data); void crmd_ha_msg_callback(const struct ha_msg* msg, void* private_data) { const char *to = NULL; char *xml_text = NULL; xmlNodePtr root_xml_node = NULL; const char *from = ha_msg_value(msg, F_ORIG); const char *seq = ha_msg_value(msg, F_SEQ); const char *type = ha_msg_value(msg, F_TYPE); #ifdef MSG_LOG if(msg_in_strm == NULL) { msg_in_strm = fopen(DEVEL_DIR"/inbound.log", "w"); } #endif if(from == NULL) { crm_err("Value of %s was NULL", F_ORIG); } else if(safe_str_eq(from, fsa_our_uname)) { if(safe_str_eq(type, T_CRM)) { #ifdef MSG_LOG fprintf(msg_in_strm, "Discarded %s message [F_SEQ=%s] from ourselves.\n", T_CRM, seq); fflush(msg_in_strm); #endif return; } } root_xml_node = find_xml_in_hamessage(msg); to = xmlGetProp(root_xml_node, XML_ATTR_HOSTTO); #ifdef MSG_LOG xml_text = dump_xml_formatted(root_xml_node); fprintf(msg_in_strm, "[%s (%s:%s)]\t%s\n", crm_str(from), seq, ha_msg_value(msg, F_TYPE), xml_text ); fflush(msg_in_strm); crm_free(xml_text); #endif if(to != NULL && strlen(to) > 0 && strcmp(to, fsa_our_uname) != 0) { #ifdef MSG_LOG fprintf(msg_in_strm, "Discarding message [F_SEQ=%s] for someone else", seq); #endif return; } set_xml_property_copy(root_xml_node, XML_ATTR_HOSTFROM, from); set_xml_property_copy(root_xml_node, "F_SEQ", seq); register_fsa_input(C_HA_MESSAGE, I_ROUTER, root_xml_node); s_crmd_fsa(C_HA_MESSAGE); free_xml(root_xml_node); return; } /* * Apparently returning TRUE means "stay connected, keep doing stuff". * Returning FALSE means "we're all done, close the connection" */ gboolean crmd_ipc_msg_callback(IPC_Channel *client, gpointer user_data) { int lpc = 0; char *buffer = NULL; IPC_Message *msg = NULL; gboolean hack_return_good = TRUE; xmlNodePtr root_xml_node; crmd_client_t *curr_client = (crmd_client_t*)user_data; crm_verbose("Processing IPC message from %s", curr_client->table_key); #ifdef MSG_LOG if(msg_ipc_strm == NULL) { msg_ipc_strm = fopen(DEVEL_DIR"/inbound.ipc.log", "w"); } #endif while(client->ops->is_message_pending(client)) { if (client->ch_status == IPC_DISCONNECT) { /* The message which was pending for us is that * the IPC status is now IPC_DISCONNECT */ break; } if (client->ops->recv(client, &msg) != IPC_OK) { perror("Receive failure:"); #ifdef MSG_LOG fprintf(msg_ipc_strm, "[%s] [receive failure]\n", curr_client->table_key); fflush(msg_in_strm); #endif return !hack_return_good; } if (msg == NULL) { #ifdef MSG_LOG fprintf(msg_ipc_strm, "[%s] [__nothing__]\n", curr_client->table_key); fflush(msg_in_strm); #endif crm_err("No message this time"); continue; } lpc++; buffer = (char*)msg->msg_body; crm_verbose("Processing xml from %s [text=%s]\n", curr_client->table_key, buffer); #ifdef MSG_LOG fprintf(msg_ipc_strm, "[%s] [text=%s]\n", curr_client->table_key, buffer); fflush(msg_in_strm); #endif root_xml_node = find_xml_in_ipcmessage(msg, FALSE); if (root_xml_node != NULL) { crmd_authorize_message( root_xml_node, msg, curr_client); } else { crm_info("IPC Message was not valid... discarding."); } free_xml(root_xml_node); msg->msg_done(msg); msg = NULL; buffer = NULL; root_xml_node = NULL; } crm_verbose("Processed %d messages", lpc); if (client->ch_status == IPC_DISCONNECT) { crm_info("received HUP from %s", curr_client->table_key); if (curr_client != NULL) { struct crm_subsystem_s *the_subsystem = NULL; if (curr_client->sub_sys == NULL) { crm_warn("Client hadn't registered with us yet"); } else if (strcmp(CRM_SYSTEM_PENGINE, curr_client->sub_sys) == 0) { the_subsystem = pe_subsystem; } else if (strcmp(CRM_SYSTEM_TENGINE, curr_client->sub_sys) == 0) { the_subsystem = te_subsystem; } else if (strcmp(CRM_SYSTEM_CIB, curr_client->sub_sys) == 0){ the_subsystem = cib_subsystem; } if(the_subsystem != NULL) { cleanup_subsystem(the_subsystem); } /* else that was a transient client */ if (curr_client->table_key != NULL) { /* * Key is destroyed below: * curr_client->table_key * Value is cleaned up by: * G_main_del_IPC_Channel */ g_hash_table_remove( ipc_clients, curr_client->table_key); } if(curr_client->client_source != NULL) { gboolean det = G_main_del_IPC_Channel( curr_client->client_source); crm_verbose("crm_client was %s detached", det?"successfully":"not"); } crm_free(curr_client->table_key); crm_free(curr_client->sub_sys); crm_free(curr_client->uuid); crm_free(curr_client); } return !hack_return_good; } return hack_return_good; } void lrm_op_callback (lrm_op_t* op) { /* todo: free op->rsc */ crm_debug("received callback"); register_fsa_input(C_LRM_OP_CALLBACK, I_LRM_EVENT, op); s_crmd_fsa(C_LRM_OP_CALLBACK); } void crmd_ha_status_callback( const char *node, const char * status, void* private_data) { xmlNodePtr update = NULL; xmlNodePtr fragment = NULL; xmlNodePtr msg_options = NULL; xmlNodePtr request = NULL; crm_debug("received callback"); crm_notice("Status update: Node %s now has status [%s]\n",node,status); if(AM_I_DC == FALSE) { crm_debug("Got nstatus callback in non-DC mode"); return; } else if(safe_str_neq(status, DEADSTATUS)) { crm_debug("nstatus callback was not for a dead node"); return; } /* this node is taost */ update = create_node_state( node, node, status, NULL, NULL, NULL, NULL); set_xml_property_copy( update, XML_CIB_ATTR_CLEAR_SHUTDOWN, XML_BOOLEAN_TRUE); fragment = create_cib_fragment(update, NULL); msg_options = set_xml_attr( NULL, XML_TAG_OPTIONS, XML_ATTR_OP, CRM_OP_UPDATE, TRUE); request = create_request( msg_options, fragment, NULL, CRM_SYSTEM_DCIB, CRM_SYSTEM_DC, NULL, NULL); crm_xml_debug(fragment, "Node status update"); free_xml(fragment); free_xml(update); register_fsa_input(C_CRMD_STATUS_CALLBACK, I_CIB_OP, request); s_crmd_fsa(C_CRMD_STATUS_CALLBACK); } void crmd_client_status_callback(const char * node, const char * client, const char * status, void * private) { const char *join = NULL; const char *extra = NULL; xmlNodePtr update = NULL; xmlNodePtr fragment = NULL; xmlNodePtr msg_options = NULL; xmlNodePtr request = NULL; crm_debug("received callback"); set_bit_inplace(fsa_input_register, R_PEER_DATA); if(safe_str_eq(status, JOINSTATUS)){ status = ONLINESTATUS; extra = XML_CIB_ATTR_CLEAR_SHUTDOWN; } else if(safe_str_eq(status, LEAVESTATUS)){ status = OFFLINESTATUS; join = CRMD_JOINSTATE_DOWN; extra = XML_CIB_ATTR_CLEAR_SHUTDOWN; } crm_notice("Status update: Client %s/%s now has status [%s]\n", node, client, status); if(AM_I_DC == FALSE) { crm_debug("Got client status callback in non-DC mode"); return; } update = create_node_state( node, node, NULL, NULL, status, join, NULL); set_xml_property_copy(update, extra, XML_BOOLEAN_TRUE); fragment = create_cib_fragment(update, NULL); msg_options = set_xml_attr( NULL, XML_TAG_OPTIONS, XML_ATTR_OP, CRM_OP_UPDATE, TRUE); request = create_request( msg_options, fragment, NULL, CRM_SYSTEM_DCIB, CRM_SYSTEM_DC, NULL, NULL); crm_xml_debug(fragment, "Client status update"); free_xml(fragment); free_xml(update); register_fsa_input(C_CRMD_STATUS_CALLBACK, I_CIB_OP, request); s_crmd_fsa(C_CRMD_STATUS_CALLBACK); } xmlNodePtr find_xml_in_hamessage(const struct ha_msg* msg) { const char *xml; xmlDocPtr doc; xmlNodePtr root; if (msg == NULL) { crm_info("**** ha_crm_msg_callback called on a NULL message"); return NULL; } #if 0 crm_debug("[F_TYPE=%s]", ha_msg_value(msg, F_TYPE)); crm_debug("[F_ORIG=%s]", ha_msg_value(msg, F_ORIG)); crm_debug("[F_TO=%s]", ha_msg_value(msg, F_TO)); crm_debug("[F_COMMENT=%s]", ha_msg_value(msg, F_COMMENT)); crm_debug("[F_XML=%s]", ha_msg_value(msg, "xml")); /* crm_debug("[F_=%s]", ha_msg_value(ha_msg, F_)); */ #endif if (strcmp(T_CRM, ha_msg_value(msg, F_TYPE)) != 0) { crm_info("Received a (%s) message by mistake.", ha_msg_value(msg, F_TYPE)); return NULL; } xml = ha_msg_value(msg, "xml"); if (xml == NULL) { crm_info("No XML attached to this message."); return NULL; } doc = xmlParseMemory(xml, strlen(xml)); if (doc == NULL) { crm_info("XML Buffer was not valid."); return NULL; } root = xmlDocGetRootElement(doc); if (root == NULL) { crm_info("Root node was NULL."); return NULL; } return root; } gboolean lrm_dispatch(int fd, gpointer user_data) { ll_lrm_t *lrm = (ll_lrm_t*)user_data; crm_debug("received callback"); lrm->lrm_ops->rcvmsg(lrm, FALSE); return TRUE; } /* #define MAX_EMPTY_CALLBACKS 20 */ /* int empty_callbacks = 0; */ gboolean crmd_ha_msg_dispatch(IPC_Channel *channel, gpointer user_data) { int lpc = 0; ll_cluster_t *hb_cluster = (ll_cluster_t*)user_data; #if 1 while(hb_cluster->llc_ops->msgready(hb_cluster)) { lpc++; /* invoke the callbacks but dont block */ hb_cluster->llc_ops->rcvmsg(hb_cluster, 0); /* empty_callbacks = 0; */ } #else while(hb_cluster->llc_ops->rcvmsg(hb_cluster, 0)) { lpc++; } #endif crm_trace("%d HA messages dispatched", lpc); if (channel && (channel->ch_status == IPC_DISCONNECT)) { crm_crit("Lost connection to heartbeat service."); return FALSE; } #if 0 if(lpc == 0) { /* hey what happened?? */ crm_warn("We were called but no message was ready." " Likely the connection to Heartbeat failed," " check the logs."); if(empty_callbacks++ > MAX_EMPTY_CALLBACKS) { crm_err("%d empty callbacks received..." " considering heartbeat dead", MAX_EMPTY_CALLBACKS); return FALSE; } } #endif return TRUE; } void crmd_ha_connection_destroy(gpointer user_data) { crm_crit("Heartbeat has left us"); /* this is always an error */ /* feed this back into the FSA */ register_fsa_input(C_HA_DISCONNECT, I_ERROR, NULL); s_crmd_fsa(C_HA_DISCONNECT); } gboolean crmd_client_connect(IPC_Channel *client_channel, gpointer user_data) { if (client_channel == NULL) { crm_err("Channel was NULL"); } else if (client_channel->ch_status == IPC_DISCONNECT) { crm_err("Channel was disconnected"); } else { - crm_debug("Channel connected"); crmd_client_t *blank_client = NULL; + crm_debug("Channel connected"); crm_malloc(blank_client, sizeof(crmd_client_t)); if (blank_client == NULL) { return FALSE; } client_channel->ops->set_recv_qlen(client_channel, 100); client_channel->ops->set_send_qlen(client_channel, 100); 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, default_ipc_connection_destroy); } return TRUE; } gboolean ccm_dispatch(int fd, gpointer user_data) { oc_ev_t *ccm_token = (oc_ev_t*)user_data; crm_debug("received callback"); oc_ev_handle_event(ccm_token); return TRUE; } void crmd_ccm_msg_callback( oc_ed_t event, void *cookie, size_t size, const void *data) { struct crmd_ccm_data_s *event_data = NULL; crm_debug("received callback"); if(data != NULL) { set_bit_inplace(fsa_input_register, R_CCM_DATA); crm_malloc(event_data, sizeof(struct crmd_ccm_data_s)); if(event_data != NULL) { event_data->event = &event; event_data->oc = copy_ccm_oc_data( (const oc_ev_membership_t *)data); register_fsa_input( C_CCM_CALLBACK, I_CCM_EVENT, (void*)event_data); s_crmd_fsa(C_CCM_CALLBACK); event_data->event = NULL; event_data->oc = NULL; crm_free(event_data); } } else { crm_info("CCM Callback with NULL data... " "I dont /think/ this is bad"); } oc_ev_callback_done(cookie); return; } diff --git a/crm/crmd/utils.c b/crm/crmd/utils.c index 63c206d155..9400eb6136 100644 --- a/crm/crmd/utils.c +++ b/crm/crmd/utils.c @@ -1,1148 +1,1148 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void copy_ccm_node(oc_node_t a_node, oc_node_t *a_node_copy); /* A_DC_TIMER_STOP, A_DC_TIMER_START, * A_FINALIZE_TIMER_STOP, A_FINALIZE_TIMER_START * A_INTEGRATE_TIMER_STOP, A_INTEGRATE_TIMER_START */ enum crmd_fsa_input do_timer_control(long long action, enum crmd_fsa_cause cause, enum crmd_fsa_state cur_state, enum crmd_fsa_input current_input, fsa_data_t *msg_data) { gboolean timer_op_ok = TRUE; if(action & A_DC_TIMER_STOP) { timer_op_ok = stopTimer(election_trigger); } else if(action & A_FINALIZE_TIMER_STOP) { timer_op_ok = stopTimer(finalization_timer); } else if(action & A_INTEGRATE_TIMER_STOP) { timer_op_ok = stopTimer(integration_timer); /* } else if(action & A_ELECTION_TIMEOUT_STOP) { */ /* timer_op_ok = stopTimer(election_timeout); */ } /* dont start a timer that wasnt already running */ if(action & A_DC_TIMER_START && timer_op_ok) { startTimer(election_trigger); } else if(action & A_FINALIZE_TIMER_START) { startTimer(finalization_timer); } else if(action & A_INTEGRATE_TIMER_START) { startTimer(integration_timer); /* } else if(action & A_ELECTION_TIMEOUT_START) { */ /* startTimer(election_timeout); */ } return I_NULL; } gboolean timer_popped(gpointer data) { fsa_timer_t *timer = (fsa_timer_t *)data; crm_info("Timer %s just popped!", fsa_input2string(timer->fsa_input)); stopTimer(timer); /* make it _not_ go off again */ if(timer->fsa_input != I_NULL) { register_fsa_input(C_TIMER_POPPED, timer->fsa_input, NULL); } s_crmd_fsa(C_TIMER_POPPED); return TRUE; } gboolean startTimer(fsa_timer_t *timer) { if((timer->source_id == (guint)-1 || timer->source_id == (guint)-2) && timer->period_ms > 0) { timer->source_id = Gmain_timeout_add(timer->period_ms, timer->callback, (void*)timer); crm_debug("Started %s timer (%d)", fsa_input2string(timer->fsa_input), timer->source_id); } else if(timer->period_ms < 0) { crm_err("Tried to start timer %s with -ve period", fsa_input2string(timer->fsa_input)); } else { crm_debug("Timer %s already running (%d)", fsa_input2string(timer->fsa_input), timer->source_id); return FALSE; } return TRUE; } gboolean stopTimer(fsa_timer_t *timer) { if(timer->source_id != (guint)-1 && timer->source_id != (guint)-2) { crm_devel("Stopping %s timer (%d)", fsa_input2string(timer->fsa_input), timer->source_id); g_source_remove(timer->source_id); timer->source_id = -2; } else { timer->source_id = -2; crm_debug("Timer %s already stopped (%d)", fsa_input2string(timer->fsa_input), timer->source_id); return FALSE; } return TRUE; } long long toggle_bit(long long action_list, long long action) { crm_trace("Toggling bit %.16llx", action); action_list ^= action; crm_trace("Result %.16llx", action_list & action); return action_list; } long long clear_bit(long long action_list, long long action) { crm_trace("Clearing bit\t%.16llx", action); /* ensure its set */ action_list |= action; /* then toggle */ action_list = action_list ^ action; return action_list; } long long set_bit(long long action_list, long long action) { crm_trace("Setting bit\t%.16llx", action); action_list |= action; return action_list; } gboolean is_set(long long action_list, long long action) { /* crm_verbose("Checking bit\t%.16llx", action); */ return ((action_list & action) == action); } gboolean is_set_any(long long action_list, long long action) { /* crm_verbose("Checking bit\t%.16llx", action); */ return ((action_list & action) != 0); } const char * fsa_input2string(enum crmd_fsa_input input) { const char *inputAsText = NULL; switch(input){ case I_NULL: inputAsText = "I_NULL"; break; case I_CCM_EVENT: inputAsText = "I_CCM_EVENT"; break; case I_CIB_OP: inputAsText = "I_CIB_OP"; break; case I_CIB_UPDATE: inputAsText = "I_CIB_UPDATE"; break; case I_DC_TIMEOUT: inputAsText = "I_DC_TIMEOUT"; break; case I_ELECTION: inputAsText = "I_ELECTION"; break; case I_PE_CALC: inputAsText = "I_PE_CALC"; break; case I_RELEASE_DC: inputAsText = "I_RELEASE_DC"; break; case I_ELECTION_DC: inputAsText = "I_ELECTION_DC"; break; case I_ERROR: inputAsText = "I_ERROR"; break; case I_FAIL: inputAsText = "I_FAIL"; break; case I_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_TERMINATE: inputAsText = "I_TERMINATE"; 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_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_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 * fsa_action2string(long long action) { const char *actionAsText = NULL; switch(action){ case A_NOTHING: actionAsText = "A_NOTHING"; break; case A_READCONFIG: actionAsText = "A_READCONFIG"; break; case O_SHUTDOWN: actionAsText = "O_SHUTDOWN"; break; case O_RELEASE: actionAsText = "O_RELEASE"; break; case A_STARTUP: actionAsText = "A_STARTUP"; break; case A_STARTED: actionAsText = "A_STARTED"; break; case A_HA_CONNECT: actionAsText = "A_HA_CONNECT"; break; case A_HA_DISCONNECT: actionAsText = "A_HA_DISCONNECT"; break; case A_LRM_CONNECT: actionAsText = "A_LRM_CONNECT"; break; case A_LRM_EVENT: actionAsText = "A_LRM_EVENT"; break; case A_LRM_INVOKE: actionAsText = "A_LRM_INVOKE"; break; case A_LRM_DISCONNECT: actionAsText = "A_LRM_DISCONNECT"; break; case O_DC_TIMER_RESTART: actionAsText = "O_DC_TIMER_RESTART"; break; case A_DC_TIMER_STOP: actionAsText = "A_DC_TIMER_STOP"; break; case A_DC_TIMER_START: actionAsText = "A_DC_TIMER_START"; break; case A_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_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_MSG_STORE: actionAsText = "A_MSG_STORE"; break; case A_RECOVER: actionAsText = "A_RECOVER"; break; case A_DC_RELEASE: actionAsText = "A_DC_RELEASE"; break; case A_DC_RELEASED: actionAsText = "A_DC_RELEASED"; break; case A_DC_TAKEOVER: actionAsText = "A_DC_TAKEOVER"; break; case A_SHUTDOWN: actionAsText = "A_SHUTDOWN"; break; case A_SHUTDOWN_REQ: actionAsText = "A_SHUTDOWN_REQ"; break; case A_STOP: actionAsText = "A_STOP "; break; case A_EXIT_0: actionAsText = "A_EXIT_0"; break; case A_EXIT_1: actionAsText = "A_EXIT_1"; break; case A_CCM_CONNECT: actionAsText = "A_CCM_CONNECT"; break; case A_CCM_DISCONNECT: actionAsText = "A_CCM_DISCONNECT"; break; case A_CCM_EVENT: actionAsText = "A_CCM_EVENT"; break; case A_CCM_UPDATE_CACHE: actionAsText = "A_CCM_UPDATE_CACHE"; break; case A_CIB_BUMPGEN: actionAsText = "A_CIB_BUMPGEN"; break; case A_CIB_INVOKE: actionAsText = "A_CIB_INVOKE"; break; case O_CIB_RESTART: actionAsText = "O_CIB_RESTART"; break; case A_CIB_START: actionAsText = "A_CIB_START"; break; case A_CIB_STOP: actionAsText = "A_CIB_STOP"; break; case A_TE_INVOKE: actionAsText = "A_TE_INVOKE"; break; case O_TE_RESTART: actionAsText = "O_TE_RESTART"; break; case A_TE_START: actionAsText = "A_TE_START"; break; case A_TE_STOP: actionAsText = "A_TE_STOP"; break; case A_TE_CANCEL: actionAsText = "A_TE_CANCEL"; break; case A_TE_COPYTO: actionAsText = "A_TE_COPYTO"; break; case A_PE_INVOKE: actionAsText = "A_PE_INVOKE"; break; case O_PE_RESTART: actionAsText = "O_PE_RESTART"; break; case A_PE_START: actionAsText = "A_PE_START"; break; case A_PE_STOP: actionAsText = "A_PE_STOP"; break; case A_NODE_BLOCK: actionAsText = "A_NODE_BLOCK"; break; case A_UPDATE_NODESTATUS: actionAsText = "A_UPDATE_NODESTATUS"; break; case A_LOG: actionAsText = "A_LOG "; break; case A_ERROR: actionAsText = "A_ERROR "; break; case A_WARN: actionAsText = "A_WARN "; break; } if(actionAsText == NULL) { crm_err("Action %.16llx is unknown", action); actionAsText = ""; } return actionAsText; } void fsa_dump_actions(long long action, const char *text) { if(is_set(action, A_READCONFIG)) { crm_debug("Action %.16llx (A_READCONFIG) %s", A_READCONFIG, text); } if(is_set(action, A_STARTUP)) { crm_debug("Action %.16llx (A_STARTUP) %s", A_STARTUP, text); } if(is_set(action, A_STARTED)) { crm_debug("Action %.16llx (A_STARTED) %s", A_STARTED, text); } if(is_set(action, A_HA_CONNECT)) { crm_debug("Action %.16llx (A_CONNECT) %s", A_HA_CONNECT, text); } if(is_set(action, A_HA_DISCONNECT)) { crm_debug("Action %.16llx (A_DISCONNECT) %s", A_HA_DISCONNECT, text); } if(is_set(action, A_LRM_CONNECT)) { crm_debug("Action %.16llx (A_LRM_CONNECT) %s", A_LRM_CONNECT, text); } if(is_set(action, A_LRM_EVENT)) { crm_debug("Action %.16llx (A_LRM_EVENT) %s", A_LRM_EVENT, text); } if(is_set(action, A_LRM_INVOKE)) { crm_debug("Action %.16llx (A_LRM_INVOKE) %s", A_LRM_INVOKE, text); } if(is_set(action, A_LRM_DISCONNECT)) { crm_debug("Action %.16llx (A_LRM_DISCONNECT) %s", A_LRM_DISCONNECT, text); } if(is_set(action, A_DC_TIMER_STOP)) { crm_debug("Action %.16llx (A_DC_TIMER_STOP) %s", A_DC_TIMER_STOP, text); } if(is_set(action, A_DC_TIMER_START)) { crm_debug("Action %.16llx (A_DC_TIMER_START) %s", A_DC_TIMER_START, text); } if(is_set(action, A_INTEGRATE_TIMER_START)) { crm_debug("Action %.16llx (A_INTEGRATE_TIMER_START) %s", A_INTEGRATE_TIMER_START, text); } if(is_set(action, A_INTEGRATE_TIMER_STOP)) { crm_debug("Action %.16llx (A_INTEGRATE_TIMER_STOP) %s", A_INTEGRATE_TIMER_STOP, text); } if(is_set(action, A_FINALIZE_TIMER_START)) { crm_debug("Action %.16llx (A_FINALIZE_TIMER_START) %s", A_FINALIZE_TIMER_START, text); } if(is_set(action, A_FINALIZE_TIMER_STOP)) { crm_debug("Action %.16llx (A_FINALIZE_TIMER_STOP) %s", A_FINALIZE_TIMER_STOP, text); } if(is_set(action, A_ELECTION_COUNT)) { crm_debug("Action %.16llx (A_ELECTION_COUNT) %s", A_ELECTION_COUNT, text); } if(is_set(action, A_ELECTION_VOTE)) { crm_debug("Action %.16llx (A_ELECTION_VOTE) %s", A_ELECTION_VOTE, text); } if(is_set(action, A_CL_JOIN_ANNOUNCE)) { crm_debug("Action %.16llx (A_CL_JOIN_ANNOUNCE) %s", A_CL_JOIN_ANNOUNCE, text); } if(is_set(action, A_CL_JOIN_REQUEST)) { crm_debug("Action %.16llx (A_CL_JOIN_REQUEST) %s", A_CL_JOIN_REQUEST, text); } if(is_set(action, A_CL_JOIN_RESULT)) { crm_debug("Action %.16llx (A_CL_JOIN_RESULT) %s", A_CL_JOIN_RESULT, text); } if(is_set(action, A_DC_JOIN_OFFER_ALL)) { crm_debug("Action %.16llx (A_DC_JOIN_OFFER_ALL) %s", A_DC_JOIN_OFFER_ALL, text); } if(is_set(action, A_DC_JOIN_OFFER_ONE)) { crm_debug("Action %.16llx (A_DC_JOIN_OFFER_ONE) %s", A_DC_JOIN_OFFER_ONE, text); } if(is_set(action, A_DC_JOIN_PROCESS_REQ)) { crm_debug("Action %.16llx (A_DC_JOIN_PROCESS_REQ) %s", A_DC_JOIN_PROCESS_REQ, text); } if(is_set(action, A_DC_JOIN_PROCESS_ACK)) { crm_debug("Action %.16llx (A_DC_JOIN_PROCESS_ACK) %s", A_DC_JOIN_PROCESS_ACK, text); } if(is_set(action, A_DC_JOIN_FINALIZE)) { crm_debug("Action %.16llx (A_DC_JOIN_FINALIZE) %s", A_DC_JOIN_FINALIZE, text); } if(is_set(action, A_MSG_PROCESS)) { crm_debug("Action %.16llx (A_MSG_PROCESS) %s", A_MSG_PROCESS, text); } if(is_set(action, A_MSG_ROUTE)) { crm_debug("Action %.16llx (A_MSG_ROUTE) %s", A_MSG_ROUTE, text); } if(is_set(action, A_MSG_STORE)) { crm_debug("Action %.16llx (A_MSG_STORE) %s", A_MSG_STORE, text); } if(is_set(action, A_RECOVER)) { crm_debug("Action %.16llx (A_RECOVER) %s", A_RECOVER, text); } if(is_set(action, A_DC_RELEASE)) { crm_debug("Action %.16llx (A_DC_RELEASE) %s", A_DC_RELEASE, text); } if(is_set(action, A_DC_RELEASED)) { crm_debug("Action %.16llx (A_DC_RELEASED) %s", A_DC_RELEASED, text); } if(is_set(action, A_DC_TAKEOVER)) { crm_debug("Action %.16llx (A_DC_TAKEOVER) %s", A_DC_TAKEOVER, text); } if(is_set(action, A_SHUTDOWN)) { crm_debug("Action %.16llx (A_SHUTDOWN) %s", A_SHUTDOWN, text); } if(is_set(action, A_SHUTDOWN_REQ)) { crm_debug("Action %.16llx (A_SHUTDOWN_REQ) %s", A_SHUTDOWN_REQ, text); } if(is_set(action, A_STOP)) { crm_debug("Action %.16llx (A_STOP ) %s", A_STOP , text); } if(is_set(action, A_EXIT_0)) { crm_debug("Action %.16llx (A_EXIT_0) %s", A_EXIT_0, text); } if(is_set(action, A_EXIT_1)) { crm_debug("Action %.16llx (A_EXIT_1) %s", A_EXIT_1, text); } if(is_set(action, A_CCM_CONNECT)) { crm_debug("Action %.16llx (A_CCM_CONNECT) %s", A_CCM_CONNECT, text); } if(is_set(action, A_CCM_DISCONNECT)) { crm_debug("Action %.16llx (A_CCM_DISCONNECT) %s", A_CCM_DISCONNECT, text); } if(is_set(action, A_CCM_EVENT)) { crm_debug("Action %.16llx (A_CCM_EVENT) %s", A_CCM_EVENT, text); } if(is_set(action, A_CCM_UPDATE_CACHE)) { crm_debug("Action %.16llx (A_CCM_UPDATE_CACHE) %s", A_CCM_UPDATE_CACHE, text); } if(is_set(action, A_CIB_BUMPGEN)) { crm_debug("Action %.16llx (A_CIB_BUMPGEN) %s", A_CIB_BUMPGEN, text); } if(is_set(action, A_CIB_INVOKE)) { crm_debug("Action %.16llx (A_CIB_INVOKE) %s", A_CIB_INVOKE, text); } if(is_set(action, A_CIB_START)) { crm_debug("Action %.16llx (A_CIB_START) %s", A_CIB_START, text); } if(is_set(action, A_CIB_STOP)) { crm_debug("Action %.16llx (A_CIB_STOP) %s", A_CIB_STOP, text); } if(is_set(action, A_TE_INVOKE)) { crm_debug("Action %.16llx (A_TE_INVOKE) %s", A_TE_INVOKE, text); } if(is_set(action, A_TE_START)) { crm_debug("Action %.16llx (A_TE_START) %s", A_TE_START, text); } if(is_set(action, A_TE_STOP)) { crm_debug("Action %.16llx (A_TE_STOP) %s", A_TE_STOP, text); } if(is_set(action, A_TE_CANCEL)) { crm_debug("Action %.16llx (A_TE_CANCEL) %s", A_TE_CANCEL, text); } if(is_set(action, A_TE_COPYTO)) { crm_debug("Action %.16llx (A_TE_COPYTO) %s", A_TE_COPYTO, text); } if(is_set(action, A_PE_INVOKE)) { crm_debug("Action %.16llx (A_PE_INVOKE) %s", A_PE_INVOKE, text); } if(is_set(action, A_PE_START)) { crm_debug("Action %.16llx (A_PE_START) %s", A_PE_START, text); } if(is_set(action, A_PE_STOP)) { crm_debug("Action %.16llx (A_PE_STOP) %s", A_PE_STOP, text); } if(is_set(action, A_NODE_BLOCK)) { crm_debug("Action %.16llx (A_NODE_BLOCK) %s", A_NODE_BLOCK, text); } if(is_set(action, A_UPDATE_NODESTATUS)) { crm_debug("Action %.16llx (A_UPDATE_NODESTATUS) %s", A_UPDATE_NODESTATUS, text); } if(is_set(action, A_LOG)) { crm_debug("Action %.16llx (A_LOG ) %s", A_LOG, text); } if(is_set(action, A_ERROR)) { crm_debug("Action %.16llx (A_ERROR ) %s", A_ERROR, text); } if(is_set(action, A_WARN)) { crm_debug("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. */ xmlNodePtr tmp2 = NULL; xmlNodePtr tmp1 = create_xml_node(NULL, XML_CIB_TAG_NODE); crm_debug("Creating node entry for %s", uname); set_uuid(tmp1, XML_ATTR_UUID, uname); set_xml_property_copy(tmp1, XML_ATTR_UNAME, uname); set_xml_property_copy(tmp1, XML_ATTR_TYPE, type); tmp2 = create_cib_fragment(tmp1, NULL); /* do not forward this to the TE */ invoke_local_cib(NULL, tmp2, CRM_OP_UPDATE); free_xml(tmp2); free_xml(tmp1); } xmlNodePtr create_node_state(const char *uuid, const char *uname, const char *ha_state, const char *ccm_state, const char *crmd_state, const char *join_state, const char *exp_state) { xmlNodePtr node_state = create_xml_node(NULL, XML_CIB_TAG_STATE); crm_debug("Creating node state entry for %s", uname); set_uuid(node_state, XML_ATTR_UUID, uname); set_xml_property_copy(node_state, XML_ATTR_UNAME, uname); set_xml_property_copy( node_state, XML_CIB_ATTR_HASTATE, ha_state); set_xml_property_copy( node_state, XML_CIB_ATTR_INCCM, ccm_state); set_xml_property_copy( node_state, XML_CIB_ATTR_CRMDSTATE, crmd_state); set_xml_property_copy( node_state, XML_CIB_ATTR_JOINSTATE, join_state); set_xml_property_copy( node_state, XML_CIB_ATTR_EXPSTATE, exp_state); crm_xml_devel(node_state, "created"); return node_state; } void set_uuid(xmlNodePtr node, const char *attr, const char *uname) { uuid_t uuid_raw; char *uuid_calc = NULL; crm_malloc(uuid_calc, sizeof(char)*50); if(uuid_calc != NULL) { if(fsa_cluster_conn->llc_ops->get_uuid_by_name( fsa_cluster_conn, uname, uuid_raw) == HA_FAIL) { crm_err("Could not calculate UUID for %s", uname); crm_free(uuid_calc); uuid_calc = crm_strdup(uname); } else { uuid_unparse(uuid_raw, uuid_calc); } set_xml_property_copy(node, attr, uuid_calc); } crm_free(uuid_calc); }/*memory leak*/ /* BEAM BUG - this is not a memory leak */ struct crmd_ccm_data_s * copy_ccm_data(const struct crmd_ccm_data_s *ccm_input) { const oc_ev_membership_t *oc_in = (const oc_ev_membership_t *)ccm_input->oc; struct crmd_ccm_data_s *ccm_input_copy = NULL; crm_malloc(ccm_input_copy, sizeof(struct crmd_ccm_data_s)); ccm_input_copy->oc = copy_ccm_oc_data(oc_in); ccm_input_copy->event = ccm_input->event; return ccm_input_copy; } oc_ev_membership_t * copy_ccm_oc_data(const oc_ev_membership_t *oc_in) { int lpc = 0; int size = 0; int offset = 0; int num_nodes = 0; oc_ev_membership_t *oc_copy = NULL; if(oc_in->m_n_member > 0 && num_nodes < oc_in->m_n_member + oc_in->m_memb_idx) { num_nodes = oc_in->m_n_member + oc_in->m_memb_idx; crm_devel("Updated ccm nodes to %d - 1", num_nodes); } if(oc_in->m_n_in > 0 && num_nodes < oc_in->m_n_in + oc_in->m_in_idx) { num_nodes = oc_in->m_n_in + oc_in->m_in_idx; crm_devel("Updated ccm nodes to %d - 2", num_nodes); } if(oc_in->m_n_out > 0 && num_nodes < oc_in->m_n_out + oc_in->m_out_idx) { num_nodes = oc_in->m_n_out + oc_in->m_out_idx; crm_devel("Updated ccm nodes to %d - 3", num_nodes); } /* why 2*?? * ccm code does it like this so i guess its right... */ size = sizeof(oc_ev_membership_t) + sizeof(int) + 2*num_nodes*sizeof(oc_node_t); crm_devel("Copying %d ccm nodes", num_nodes); crm_malloc(oc_copy, size); oc_copy->m_instance = oc_in->m_instance; oc_copy->m_n_member = oc_in->m_n_member; oc_copy->m_memb_idx = oc_in->m_memb_idx; oc_copy->m_n_out = oc_in->m_n_out; oc_copy->m_out_idx = oc_in->m_out_idx; oc_copy->m_n_in = oc_in->m_n_in; oc_copy->m_in_idx = oc_in->m_in_idx; crm_debug("instance=%d, nodes=%d (idx=%d), new=%d (idx=%d), lost=%d (idx=%d)", oc_in->m_instance, oc_in->m_n_member, oc_in->m_memb_idx, oc_in->m_n_in, oc_in->m_in_idx, oc_in->m_n_out, oc_in->m_out_idx); offset = oc_in->m_memb_idx; for(lpc = 0; lpc < oc_in->m_n_member; lpc++) { - crm_devel("Copying ccm member node %d", lpc); oc_node_t a_node = oc_in->m_array[lpc+offset]; oc_node_t *a_node_copy = &(oc_copy->m_array[lpc+offset]); + crm_devel("Copying ccm member node %d", lpc); copy_ccm_node(a_node, a_node_copy); } offset = oc_in->m_in_idx; for(lpc = 0; lpc < oc_in->m_n_in; lpc++) { - crm_devel("Copying ccm new node %d", lpc); oc_node_t a_node = oc_in->m_array[lpc+offset]; oc_node_t *a_node_copy = &(oc_copy->m_array[lpc+offset]); + crm_devel("Copying ccm new node %d", lpc); copy_ccm_node(a_node, a_node_copy); } offset = oc_in->m_out_idx; for(lpc = 0; lpc < oc_in->m_n_out; lpc++) { - crm_devel("Copying ccm lost node %d", lpc); oc_node_t a_node = oc_in->m_array[lpc+offset]; oc_node_t *a_node_copy = &(oc_copy->m_array[lpc+offset]); + crm_devel("Copying ccm lost node %d", lpc); copy_ccm_node(a_node, a_node_copy); } return oc_copy; } void copy_ccm_node(oc_node_t a_node, oc_node_t *a_node_copy) { crm_devel("Copying ccm node: id=%d, born=%d, uname=%s", a_node.node_id, a_node.node_born_on, a_node.node_uname); a_node_copy->node_id = a_node.node_id; a_node_copy->node_born_on = a_node.node_born_on; a_node_copy->node_uname = NULL; if(a_node.node_uname != NULL) { a_node_copy->node_uname = crm_strdup(a_node.node_uname); } else { crm_err("Node Id %d had a NULL uname!", a_node.node_id); } crm_devel("Copied ccm node: id=%d, born=%d, uname=%s", a_node_copy->node_id, a_node_copy->node_born_on, a_node_copy->node_uname); } lrm_op_t * copy_lrm_op(const lrm_op_t *op) { lrm_op_t *op_copy = NULL; crm_malloc(op_copy, sizeof(lrm_op_t)); op_copy->op_type = crm_strdup(op->op_type); /* input fields */ /* GHashTable* params; */ op_copy->params = NULL; op_copy->timeout = op->timeout; op_copy->interval = op->interval; op_copy->target_rc = op->target_rc; /* in the CRM, this is always an int */ op_copy->user_data = 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; if(op->output!= NULL) { op_copy->output = crm_strdup(op->output); } op_copy->rsc_id = crm_strdup(op->rsc_id); op_copy->app_name = crm_strdup(op->app_name); /*please notice the client needs release the memory of rsc.*/ op_copy->rsc = copy_lrm_rsc(op->rsc); if(op_copy->rsc == NULL) { crm_err("Op callback for %s did not contain a resource", op_copy->rsc_id); } return op_copy; } lrm_rsc_t * copy_lrm_rsc(const lrm_rsc_t *rsc) { lrm_rsc_t *rsc_copy = NULL; if(rsc == NULL) { return NULL; } crm_malloc(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->provider = NULL; if(rsc->class != NULL) { rsc_copy->class = crm_strdup(rsc->class); } if(rsc->provider != NULL) { rsc_copy->provider = crm_strdup(rsc->provider); } /* GHashTable* params; */ rsc_copy->params = NULL; rsc_copy->ops = NULL; return rsc_copy; } diff --git a/crm/pengine/unpack.c b/crm/pengine/unpack.c index b728db5616..222192a69c 100644 --- a/crm/pengine/unpack.c +++ b/crm/pengine/unpack.c @@ -1,1282 +1,1283 @@ -/* $Id: unpack.c,v 1.37 2004/10/21 18:25:43 andrew Exp $ */ +/* $Id: unpack.c,v 1.38 2004/10/24 12:38:33 lge Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include /* for ONLINESTATUS */ #include #include int max_valid_nodes = 0; int order_id = 1; GListPtr agent_defaults = NULL; gboolean stonith_enabled = FALSE; const char* transition_timeout = "60000"; /* 1 minute */ GListPtr match_attrs(const char *attr, const char *op, const char *value, const char *type, GListPtr node_list); gboolean unpack_rsc_to_attr(xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr node_list, GListPtr *node_constraints); gboolean unpack_rsc_to_node(xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr node_list, GListPtr *node_constraints); gboolean unpack_rsc_order( xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr *action_constraints); gboolean unpack_rsc_dependancy( xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr *action_constraints); gboolean unpack_rsc_location( xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr node_list, GListPtr *action_constraints); gboolean unpack_lrm_rsc_state( node_t *node, xmlNodePtr lrm_state, GListPtr rsc_list, GListPtr nodes, GListPtr *actions, GListPtr *node_constraints); gboolean add_node_attrs(xmlNodePtr attrs, node_t *node); gboolean unpack_healthy_resource(GListPtr *node_constraints, GListPtr *actions, xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node); gboolean unpack_failed_resource(GListPtr *node_constraints, GListPtr *actions, xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node); gboolean determine_online_status(xmlNodePtr node_state, node_t *this_node); gboolean unpack_lrm_agents(node_t *node, xmlNodePtr agent_list); gboolean is_node_unclean(xmlNodePtr node_state); gboolean rsc2rsc_new(const char *id, enum con_strength strength, enum rsc_con_type type, resource_t *rsc_lh, resource_t *rsc_rh); gboolean create_ordering( const char *id, enum con_strength strength, resource_t *rsc_lh, resource_t *rsc_rh, GListPtr *action_constraints); rsc_to_node_t *rsc2node_new( const char *id, resource_t *rsc, double weight, gboolean can_run, node_t *node, GListPtr *node_constraints); const char *get_agent_param(resource_t *rsc, const char *param); const char *get_agent_param_rsc(resource_t *rsc, const char *param); const void *get_agent_param_metadata(resource_t *rsc, const char *param); const char *get_agent_param_global(resource_t *rsc, const char *param); const char *param_value(xmlNodePtr parent, const char *name); gboolean unpack_config(xmlNodePtr config) { const char *value = NULL; value = param_value(config, "failed_nodes"); if(safe_str_eq(value, "stonith")) { crm_debug("Enabling STONITH of failed nodes"); stonith_enabled = TRUE; } else { stonith_enabled = FALSE; } value = param_value(config, "transition_timeout"); if(value != NULL) { int tmp = atoi(value); if(tmp > 0) { transition_timeout = value; } else { crm_warn("Invalid value for %s: %s", "transition_timeout", value); } } crm_info("%s set to: %s", "transition_timeout", transition_timeout); return TRUE; } const char * param_value(xmlNodePtr parent, const char *name) { xmlNodePtr a_default = find_entity( parent, XML_CIB_TAG_NVPAIR, name, FALSE); return xmlGetProp(a_default, XML_NVPAIR_ATTR_VALUE); } const char * get_agent_param(resource_t *rsc, const char *param) { const char *value = NULL; if(param == NULL) { return NULL; } value = get_agent_param_rsc(rsc, param); if(value == NULL) { value = get_agent_param_metadata(rsc, param); } if(value == NULL) { value = get_agent_param_global(rsc, param); } return value; } const char * get_agent_param_rsc(resource_t *rsc, const char *param) { xmlNodePtr xml_rsc = rsc->xml; return xmlGetProp(xml_rsc, param); } const void * get_agent_param_metadata(resource_t *rsc, const char *param) { return NULL; } const char * get_agent_param_global(resource_t *rsc, const char *param) { const char * value = NULL;/*g_hashtable_lookup(agent_global_defaults, param); */ if(value == NULL) { crm_err("No global value default for %s", param); } return value; } gboolean unpack_global_defaults(xmlNodePtr defaults) { return TRUE; } gboolean unpack_nodes(xmlNodePtr xml_nodes, GListPtr *nodes) { node_t *new_node = NULL; xmlNodePtr attrs = NULL; const char *id = NULL; const char *uname = NULL; const char *type = NULL; crm_verbose("Begining unpack..."); xml_child_iter( xml_nodes, xml_obj, XML_CIB_TAG_NODE, attrs = xml_obj->children; id = xmlGetProp(xml_obj, XML_ATTR_ID); uname = xmlGetProp(xml_obj, XML_ATTR_UNAME); type = xmlGetProp(xml_obj, XML_ATTR_TYPE); crm_verbose("Processing node %s/%s", uname, id); if(attrs != NULL) { attrs = attrs->children; } if(id == NULL) { crm_err("Must specify id tag in "); continue; } if(type == NULL) { crm_err("Must specify type tag in "); continue; } crm_malloc(new_node, sizeof(node_t)); if(new_node == NULL) { return FALSE; } new_node->weight = 1.0; new_node->fixed = FALSE; crm_malloc(new_node->details, sizeof(struct node_shared_s)); if(new_node->details == NULL) { crm_free(new_node); return FALSE; } crm_verbose("Creaing node for entry %s/%s", uname, id); new_node->details->id = id; new_node->details->uname = uname; new_node->details->type = node_ping; new_node->details->online = FALSE; new_node->details->unclean = FALSE; new_node->details->shutdown = FALSE; new_node->details->running_rsc = NULL; new_node->details->agents = NULL; new_node->details->attrs = g_hash_table_new( g_str_hash, g_str_equal); if(safe_str_eq(type, "member")) { new_node->details->type = node_member; } add_node_attrs(attrs, new_node); *nodes = g_list_append(*nodes, new_node); crm_verbose("Done with node %s", xmlGetProp(xml_obj, "uname")); crm_debug_action(print_node("Added", new_node, FALSE)); ); *nodes = g_list_sort(*nodes, sort_node_weight); return TRUE; } gboolean unpack_resources(xmlNodePtr xml_resources, GListPtr *resources, GListPtr *actions, GListPtr *action_cons, GListPtr all_nodes) { crm_verbose("Begining unpack..."); xml_child_iter( xml_resources, xml_obj, XML_CIB_TAG_RESOURCE, action_t *action_stop = NULL; action_t *action_start = NULL; const char *id = xmlGetProp(xml_obj, XML_ATTR_ID); const char *stopfail = xmlGetProp(xml_obj, "on_stopfail"); const char *restart = xmlGetProp(xml_obj, "restart_type"); const char *timeout = xmlGetProp(xml_obj, "timeout"); const char *max_instances = xmlGetProp( xml_obj, "max_instances"); const char *max_node_instances = xmlGetProp( xml_obj, "max_node_instances"); const char *max_masters = xmlGetProp( xml_obj, "max_masters"); const char *max_node_masters = xmlGetProp( xml_obj, "max_node_masters"); const char *version = xmlGetProp(xml_obj, XML_ATTR_VERSION); resource_t *new_rsc = NULL; const char *priority = xmlGetProp( xml_obj, XML_CIB_ATTR_PRIORITY); crm_verbose("Processing resource..."); if(id == NULL) { crm_err("Must specify id tag in "); continue; } crm_malloc(new_rsc, sizeof(resource_t)); if(new_rsc == NULL) { return FALSE; } new_rsc->id = id; new_rsc->xml = xml_obj; crm_malloc(new_rsc->agent, sizeof(lrm_agent_t)); new_rsc->agent->class = xmlGetProp(xml_obj, "class"); new_rsc->agent->type = xmlGetProp(xml_obj, "type"); new_rsc->agent->version = version?version:"0.0"; new_rsc->priority = atoi(priority?priority:"0"); new_rsc->effective_priority = new_rsc->priority; new_rsc->max_instances = atoi( max_instances?max_instances:"1"); new_rsc->max_node_instances = atoi( max_node_instances?max_node_instances:"1"); new_rsc->max_masters = atoi( max_masters?max_masters:"0"); new_rsc->max_node_masters = atoi( max_node_masters?max_node_masters:"0"); new_rsc->candidate_colors = NULL; new_rsc->actions = NULL; new_rsc->color = NULL; new_rsc->runnable = TRUE; new_rsc->provisional = TRUE; new_rsc->allowed_nodes = NULL; new_rsc->rsc_cons = NULL; new_rsc->node_cons = NULL; new_rsc->cur_node = NULL; if(safe_str_eq(stopfail, "ignore")) { new_rsc->stopfail_type = pesf_ignore; } else if(safe_str_eq(stopfail, "stonith")) { new_rsc->stopfail_type = pesf_stonith; } else { new_rsc->stopfail_type = pesf_block; } if(safe_str_eq(restart, "restart")) { new_rsc->restart_type = pe_restart_restart; } else if(safe_str_eq(restart, "recover")) { new_rsc->restart_type = pe_restart_recover; } else { new_rsc->restart_type = pe_restart_ignore; } action_stop = action_new(new_rsc, stop_rsc); *actions = g_list_append(*actions, action_stop); new_rsc->stop = action_stop; new_rsc->actions = g_list_append(new_rsc->actions, action_stop); action_stop->timeout = timeout; action_start = action_new(new_rsc, start_rsc); *actions = g_list_append(*actions, action_start); new_rsc->start = action_start; new_rsc->actions = g_list_append(new_rsc->actions, action_start); action_start->timeout = timeout; order_new(action_stop,action_start,pecs_startstop,action_cons); *resources = g_list_append(*resources, new_rsc); crm_debug_action(print_resource("Added", new_rsc, FALSE)); ); *resources = g_list_sort(*resources, sort_rsc_priority); return TRUE; } gboolean unpack_constraints(xmlNodePtr xml_constraints, GListPtr nodes, GListPtr resources, GListPtr *node_constraints, GListPtr *action_constraints) { crm_verbose("Begining unpack..."); xml_child_iter( xml_constraints, xml_obj, NULL, const char *id = xmlGetProp(xml_obj, XML_ATTR_ID); if(id == NULL) { crm_err("Constraint <%s...> must have an id", xml_obj->name); continue; } crm_verbose("Processing constraint %s %s", xml_obj->name,id); if(safe_str_eq("rsc_order", xml_obj->name)) { unpack_rsc_order( xml_obj, resources, action_constraints); } else if(safe_str_eq("rsc_dependancy", xml_obj->name)) { unpack_rsc_dependancy( xml_obj, resources, action_constraints); } else if(safe_str_eq("rsc_location", xml_obj->name)) { unpack_rsc_location( xml_obj, resources, nodes, node_constraints); } else { crm_err("Unsupported constraint type: %s", xml_obj->name); } ); return TRUE; } rsc_to_node_t * rsc2node_new(const char *id, resource_t *rsc, double weight, gboolean can, node_t *node, GListPtr *node_constraints) { rsc_to_node_t *new_con = NULL; if(rsc == NULL || id == NULL) { crm_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc); return NULL; } crm_malloc(new_con, sizeof(rsc_to_node_t)); if(new_con != NULL) { new_con->id = id; new_con->rsc_lh = rsc; new_con->node_list_rh = NULL; new_con->can = can; if(can) { new_con->weight = weight; } else { new_con->weight = -1; } if(node != NULL) { new_con->node_list_rh = g_list_append(NULL, node); } *node_constraints = g_list_append(*node_constraints, new_con); } return new_con; } /* remove nodes that are down, stopping */ /* create +ve rsc_to_node constraints between resources and the nodes they are running on */ /* anything else? */ gboolean unpack_status(xmlNodePtr status, GListPtr nodes, GListPtr rsc_list, GListPtr *actions, GListPtr *node_constraints) { const char *uname = NULL; xmlNodePtr lrm_rsc = NULL; xmlNodePtr lrm_agents = NULL; xmlNodePtr attrs = NULL; node_t *this_node = NULL; crm_verbose("Begining unpack"); xml_child_iter( status, node_state, XML_CIB_TAG_STATE, /* id = xmlGetProp(node_state, XML_ATTR_ID); */ uname = xmlGetProp(node_state, XML_ATTR_UNAME); attrs = find_xml_node(node_state, "attributes"); lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM); lrm_agents = find_xml_node(lrm_rsc, "lrm_agents"); lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES); lrm_rsc = find_xml_node(lrm_rsc, "lrm_resource"); crm_verbose("Processing node %s", uname); this_node = pe_find_node(nodes, uname); if(uname == NULL) { /* error */ continue; } else if(this_node == NULL) { crm_err("Node %s in status section no longer exists", uname); continue; } crm_verbose("Adding runtime node attrs"); add_node_attrs(attrs, this_node); crm_verbose("determining node state"); determine_online_status(node_state, this_node); crm_verbose("Processing lrm resource entries"); unpack_lrm_rsc_state(this_node, lrm_rsc, rsc_list, nodes, actions, node_constraints); crm_verbose("Processing lrm agents"); unpack_lrm_agents(this_node, lrm_agents); ); return TRUE; } gboolean determine_online_status(xmlNodePtr node_state, node_t *this_node) { gboolean online = FALSE; const char *uname = xmlGetProp(node_state,XML_ATTR_UNAME); /* const char *state = xmlGetProp(node_state,XML_NODE_ATTR_STATE); */ const char *exp_state = xmlGetProp(node_state,XML_CIB_ATTR_EXPSTATE); const char *join_state = xmlGetProp(node_state,XML_CIB_ATTR_JOINSTATE); const char *crm_state = xmlGetProp(node_state,XML_CIB_ATTR_CRMDSTATE); const char *ccm_state = xmlGetProp(node_state,XML_CIB_ATTR_INCCM); const char *ha_state = xmlGetProp(node_state,XML_CIB_ATTR_HASTATE); const char *shutdown = xmlGetProp(node_state,XML_CIB_ATTR_SHUTDOWN); const char *unclean = NULL;/*xmlGetProp(node_state,XML_CIB_ATTR_STONITH); */ if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER) && safe_str_eq(ccm_state, XML_BOOLEAN_YES) && safe_str_eq(ha_state, ACTIVESTATUS) && safe_str_eq(crm_state, ONLINESTATUS) && shutdown == NULL) { if(this_node != NULL) { this_node->details->online = TRUE; } crm_debug("Node %s is online", uname); online = TRUE; } else if(this_node != NULL) { /* remove node from contention */ this_node->weight = -1; this_node->fixed = TRUE; crm_verbose("join_state=%s, expected=%s, shutdown=%s", crm_str(join_state), crm_str(exp_state), crm_str(shutdown)); if(unclean != NULL) { this_node->details->unclean = TRUE; } else if(is_node_unclean(node_state)) { /* report and or take remedial action */ this_node->details->unclean = TRUE; } if(shutdown != NULL) { this_node->details->shutdown = TRUE; } if(this_node->details->unclean) { crm_warn("Node %s is due for STONITH", uname); } if(this_node->details->shutdown) { crm_info("Node %s is due for shutdown", uname); } } return online; } gboolean is_node_unclean(xmlNodePtr node_state) { /* const char *state = xmlGetProp(node_state,XML_NODE_ATTR_STATE); */ const char *uname = xmlGetProp(node_state,XML_ATTR_UNAME); const char *exp_state = xmlGetProp(node_state,XML_CIB_ATTR_EXPSTATE); const char *join_state = xmlGetProp(node_state,XML_CIB_ATTR_JOINSTATE); const char *crm_state = xmlGetProp(node_state,XML_CIB_ATTR_CRMDSTATE); const char *ha_state = xmlGetProp(node_state,XML_CIB_ATTR_HASTATE); const char *ccm_state = xmlGetProp(node_state,XML_CIB_ATTR_INCCM); if(safe_str_eq(exp_state, CRMD_STATE_INACTIVE)) { crm_debug("Node %s is safely inactive", uname); return FALSE; /* do an actual calculation once STONITH is available */ } else if(safe_str_neq(exp_state, CRMD_JOINSTATE_DOWN)) { if(safe_str_eq(crm_state, OFFLINESTATUS) || safe_str_eq(ha_state, DEADSTATUS) || safe_str_eq(join_state, CRMD_JOINSTATE_DOWN) || safe_str_eq(ccm_state, XML_BOOLEAN_NO)) { crm_warn("Node %s is un-expectedly down", uname); return TRUE; } crm_debug("Node %s: ha=%s, join=%s, crm=%s, ccm=%s", uname, ha_state, join_state, crm_state, ccm_state); } else { crm_debug("Node %s was expected to be down", uname); } return FALSE; } gboolean unpack_lrm_agents(node_t *node, xmlNodePtr agent_list) { /* if the agent is not listed, remove the node from * the resource's list of allowed_nodes */ lrm_agent_t *agent = NULL; const char *version = NULL; if(agent_list == NULL) { return FALSE; } xml_child_iter( agent_list, xml_agent, XML_LRM_TAG_AGENT, crm_malloc(agent, sizeof(lrm_agent_t)); if(agent == NULL) { continue; } agent->class = xmlGetProp(xml_agent, "class"); agent->type = xmlGetProp(xml_agent, "type"); version = xmlGetProp(xml_agent, "version"); agent->version = version?version:"0.0"; crm_trace("Adding agent %s/%s v%s to node %s", agent->class, agent->type, agent->version, node->details->uname); node->details->agents = g_list_append( node->details->agents, agent); ); return TRUE; } gboolean unpack_lrm_rsc_state(node_t *node, xmlNodePtr lrm_rsc, GListPtr rsc_list, GListPtr nodes, GListPtr *actions, GListPtr *node_constraints) { xmlNodePtr rsc_entry = NULL; const char *rsc_id = NULL; const char *node_id = NULL; const char *rsc_state = NULL; const char *op_status = NULL; const char *last_rc = NULL; const char *last_op = NULL; resource_t *rsc_lh = NULL; op_status_t action_status_i = LRM_OP_ERROR; while(lrm_rsc != NULL) { rsc_entry = lrm_rsc; lrm_rsc = lrm_rsc->next; rsc_id = xmlGetProp(rsc_entry, XML_ATTR_ID); node_id = xmlGetProp(rsc_entry, XML_LRM_ATTR_TARGET); rsc_state = xmlGetProp(rsc_entry, XML_LRM_ATTR_RSCSTATE); op_status = xmlGetProp(rsc_entry, XML_LRM_ATTR_OPSTATUS); last_rc = xmlGetProp(rsc_entry, XML_LRM_ATTR_RC); last_op = xmlGetProp(rsc_entry, XML_LRM_ATTR_LASTOP); rsc_lh = pe_find_resource(rsc_list, rsc_id); crm_verbose("[%s] Processing %s on %s (%s)", rsc_entry->name, rsc_id, node_id, rsc_state); if(rsc_lh == NULL) { crm_err("Could not find a match for resource" " %s in %s's status section", rsc_id, node_id); continue; } else if(op_status == NULL) { crm_err("Invalid resource status entry for %s in %s", rsc_id, node_id); continue; } action_status_i = atoi(op_status); if(node->details->unclean) { crm_info("Node %s (where %s is running) is unclean." "Further action depends on the value of on_stopfail", node->details->uname, rsc_lh->id); /* map the status to an error and then handle as a * failed resource. */ action_status_i = LRM_OP_ERROR; } else if(action_status_i == -1) { /* * TODO: this may need some more thought * Some cases: * - PE reinvoked with pending action that will succeed * - PE reinvoked with pending action that will fail * - After DC election * - After startup * * pending start - required start * pending stop - required stop * pending on unavailable node - stonith * * For now this should do */ if(safe_str_eq(last_op, "stop")) { /* map this to a timeout so it is re-issued */ action_status_i = LRM_OP_TIMEOUT; } else { /* map this to a "done" so it is not marked * as failed, then make sure it is re-issued */ action_status_i = LRM_OP_DONE; rsc_lh->start->optional = FALSE; } } switch(action_status_i) { case LRM_OP_DONE: unpack_healthy_resource( node_constraints, actions, rsc_entry, rsc_lh,node); break; case LRM_OP_ERROR: case LRM_OP_TIMEOUT: case LRM_OP_NOTSUPPORTED: unpack_failed_resource( node_constraints, actions, rsc_entry, rsc_lh,node); break; case LRM_OP_CANCELLED: /* do nothing?? */ crm_warn("Dont know what to do for cancelled ops yet"); break; } } return TRUE; } gboolean unpack_failed_resource(GListPtr *node_constraints, GListPtr *actions, xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node) { const char *last_op = xmlGetProp(rsc_entry, "last_op"); crm_debug("Unpacking failed action %s on %s", last_op, rsc_lh->id); /* make sure we dont allocate the resource here again*/ rsc2node_new("dont_run__generated", rsc_lh, -1.0, FALSE, node, node_constraints); if(safe_str_eq(last_op, "start")) { /* the resource is not actually running... nothing more to do*/ return TRUE; } switch(rsc_lh->stopfail_type) { case pesf_stonith: /* treat it as if it is still running * but also mark the node as unclean */ rsc_lh->cur_node = node; node->details->running_rsc = g_list_append( node->details->running_rsc, rsc_lh); if(node->details->online) { node->details->shutdown = TRUE; } node->details->unclean = TRUE; break; case pesf_block: /* let this depend on the stop action which will fail * but make sure the transition continues... */ rsc_lh->cur_node = node; node->details->running_rsc = g_list_append( node->details->running_rsc, rsc_lh); rsc_lh->stop->timeout = NULL; /* wait forever */ break; case pesf_ignore: /* pretend nothing happened */ break; } return TRUE; } gboolean unpack_healthy_resource(GListPtr *node_constraints, GListPtr *actions, xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node) { const char *last_op = xmlGetProp(rsc_entry, "last_op"); crm_debug("Unpacking healthy action %s on %s", last_op, rsc_lh->id); if(safe_str_neq(last_op, "stop")) { if(rsc_lh->cur_node != NULL) { crm_err("Resource %s running on multiple nodes %s, %s", rsc_lh->id, rsc_lh->cur_node->details->uname, node->details->uname); /* TODO: some recovery action!! */ /* like force a stop on the second node? */ return FALSE; } else { /* create the link between this node and the rsc */ crm_verbose("Setting cur_node = %s for rsc = %s", node->details->uname, rsc_lh->id); rsc_lh->cur_node = node; node->details->running_rsc = g_list_append( node->details->running_rsc, rsc_lh); } } return TRUE; } gboolean rsc2rsc_new(const char *id, enum con_strength strength, enum rsc_con_type type, resource_t *rsc_lh, resource_t *rsc_rh) { rsc_to_rsc_t *new_con = NULL; rsc_to_rsc_t *inverted_con = NULL; if(rsc_lh == NULL || rsc_rh == NULL){ /* error */ return FALSE; } crm_malloc(new_con, sizeof(rsc_to_rsc_t)); if(new_con != NULL) { new_con->id = id; new_con->rsc_lh = rsc_lh; new_con->rsc_rh = rsc_rh; new_con->strength = strength; new_con->variant = type; inverted_con = invert_constraint(new_con); rsc_lh->rsc_cons = g_list_insert_sorted( rsc_lh->rsc_cons, new_con, sort_cons_strength); rsc_rh->rsc_cons = g_list_insert_sorted( rsc_rh->rsc_cons, inverted_con, sort_cons_strength); } else { return FALSE; } return TRUE; } gboolean order_new(action_t *before, action_t *after, enum con_strength strength, GListPtr *action_constraints) { order_constraint_t *order = NULL; if(before == NULL || after == NULL || action_constraints == NULL){ crm_err("Invalid inputs b=%p, a=%p l=%p", before, after, action_constraints); return FALSE; } crm_malloc(order, sizeof(order_constraint_t)); if(order != NULL) { order->id = order_id++; order->strength = strength; order->lh_action = before; order->rh_action = after; *action_constraints = g_list_append( *action_constraints, order); } return TRUE; } gboolean unpack_rsc_dependancy(xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr *action_constraints) { enum con_strength strength_e = pecs_ignore; const char *id_lh = xmlGetProp(xml_obj, "from"); const char *id = xmlGetProp(xml_obj, XML_ATTR_ID); const char *id_rh = xmlGetProp(xml_obj, "to"); const char *type = xmlGetProp(xml_obj, XML_ATTR_TYPE); resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh); resource_t *rsc_rh = pe_find_resource(rsc_list, id_rh); if(rsc_lh == NULL) { crm_err("No resource (con=%s, rsc=%s)", id, id_lh); return FALSE; } else if(rsc_rh == NULL) { crm_err("No resource (con=%s, rsc=%s)", id, id_rh); return FALSE; } if(safe_str_eq(type, XML_STRENGTH_VAL_MUST)) { strength_e = pecs_must; } else if(safe_str_eq(type, XML_STRENGTH_VAL_SHOULD)) { crm_err("Type %s is no longer supported", type); strength_e = pecs_must; } else if(safe_str_eq(type, XML_STRENGTH_VAL_SHOULDNOT)) { crm_err("Type %s is no longer supported", type); strength_e = pecs_must_not; } else if(safe_str_eq(type, XML_STRENGTH_VAL_MUSTNOT)) { strength_e = pecs_must_not; } else { crm_err("Unknown value for %s: %s", "type", type); return FALSE; } return rsc2rsc_new(id, strength_e, same_node, rsc_lh, rsc_rh); } gboolean unpack_rsc_order(xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr *action_constraints) { enum con_strength strength_e = pecs_ignore; const char *id = xmlGetProp(xml_obj, XML_ATTR_ID); const char *id_lh = xmlGetProp(xml_obj, "from"); const char *id_rh = xmlGetProp(xml_obj, "to"); const char *type = xmlGetProp(xml_obj, XML_ATTR_TYPE); resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh); resource_t *rsc_rh = pe_find_resource(rsc_list, id_rh); if(xml_obj == NULL) { crm_err("No constraint object to process."); return FALSE; } else if(id == NULL) { crm_err("%s constraint must have an id", xml_obj->name); return FALSE; } else if(rsc_lh == NULL || rsc_rh == NULL) { crm_err("Constraint %s needs two sides lh: %p rh: %p" " (NULL indicates missing side)", id, rsc_lh, rsc_rh); return FALSE; } else if(safe_str_eq(type, "after")) { rsc2rsc_new(id, strength_e, start_after, rsc_lh, rsc_rh); order_new(rsc_rh->stop, rsc_lh->stop, pecs_must, action_constraints); order_new(rsc_lh->start, rsc_rh->start, pecs_must, action_constraints); } else { rsc2rsc_new(id, strength_e, start_before, rsc_lh, rsc_rh); order_new(rsc_lh->stop, rsc_rh->stop, pecs_must, action_constraints); order_new(rsc_rh->start, rsc_lh->start, pecs_must, action_constraints); } return TRUE; } /* do NOT free the nodes returned here */ GListPtr match_attrs(const char *attr, const char *op, const char *value, const char *type, GListPtr node_list) { int lpc = 0, lpc2 = 0; GListPtr result = NULL; if(attr == NULL || op == NULL) { crm_err("Invlaid attribute or operation in expression" " (\'%s\' \'%s\' \'%s\')", crm_str(attr), crm_str(op), crm_str(value)); return NULL; } slist_iter( node, node_t, node_list, lpc, gboolean accept = FALSE; int cmp = 0; const char *h_val = (const char*)g_hash_table_lookup( node->details->attrs, attr); if(value != NULL && h_val != NULL) { if(type == NULL || (safe_str_eq(type, "string"))) { cmp = strcmp(h_val, value); } else if(safe_str_eq(type, "number")) { float h_val_f = atof(h_val); float value_f = atof(value); if(h_val_f < value_f) { cmp = -1; } else if(h_val_f > value_f) { cmp = 1; } else { cmp = 0; } } else if(safe_str_eq(type, "version")) { cmp = compare_version(h_val, value); } } else if(value == NULL && h_val == NULL) { cmp = 0; } else if(value == NULL) { cmp = 1; } else { cmp = -1; } if(safe_str_eq(op, "exists")) { if(h_val != NULL) accept = TRUE; } else if(safe_str_eq(op, "notexists")) { if(h_val == NULL) accept = TRUE; } else if(safe_str_eq(op, "running")) { GListPtr rsc_list = node->details->running_rsc; slist_iter( rsc, resource_t, rsc_list, lpc2, if(safe_str_eq(rsc->id, attr)) { accept = TRUE; } ); } else if(safe_str_eq(op, "not_running")) { GListPtr rsc_list = node->details->running_rsc; accept = TRUE; slist_iter( rsc, resource_t, rsc_list, lpc2, if(safe_str_eq(rsc->id, attr)) { accept = FALSE; break; } ); } else if(safe_str_eq(op, "eq")) { if((h_val == value) || cmp == 0) accept = TRUE; } else if(safe_str_eq(op, "ne")) { if((h_val == NULL && value != NULL) || (h_val != NULL && value == NULL) || cmp != 0) accept = TRUE; } else if(value == NULL || h_val == NULL) { /* the comparision is meaningless from this point on */ accept = FALSE; } else if(safe_str_eq(op, "lt")) { if(cmp < 0) accept = TRUE; } else if(safe_str_eq(op, "lte")) { if(cmp <= 0) accept = TRUE; } else if(safe_str_eq(op, "gt")) { if(cmp > 0) accept = TRUE; } else if(safe_str_eq(op, "gte")) { if(cmp >= 0) accept = TRUE; } if(accept) { crm_trace("node %s matched", node->details->uname); result = g_list_append(result, node); } else { crm_trace("node %s did not match", node->details->uname); } ); return result; } gboolean add_node_attrs(xmlNodePtr attrs, node_t *node) { const char *name = NULL; const char *value = NULL; while(attrs != NULL){ name = xmlGetProp(attrs, XML_NVPAIR_ATTR_NAME); value = xmlGetProp(attrs, XML_NVPAIR_ATTR_VALUE); if(name != NULL && value != NULL && safe_val(NULL, node, details) != NULL) { crm_verbose("Adding %s => %s", name, value); /* this is frustrating... no way to pass in const * keys or values yet docs say: * Note: If keys and/or values are dynamically * allocated, you should free them first. */ g_hash_table_insert(node->details->attrs, crm_strdup(name), crm_strdup(value)); } attrs = attrs->next; } g_hash_table_insert(node->details->attrs, crm_strdup("uname"), crm_strdup(node->details->uname)); g_hash_table_insert(node->details->attrs, crm_strdup("id"), crm_strdup(node->details->id)); return TRUE; } gboolean unpack_rsc_location( xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr node_list, GListPtr *node_constraints) { /* ... Translation: Further translation: */ gboolean were_rules = FALSE; const char *id_lh = xmlGetProp(xml_obj, "rsc"); const char *id = xmlGetProp(xml_obj, XML_ATTR_ID); resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh); if(rsc_lh == NULL) { crm_err("No resource (con=%s, rsc=%s)", id, id_lh); return FALSE; } xml_child_iter( xml_obj, rule, "rule", gboolean first_expr = TRUE; gboolean can_run = FALSE; gboolean do_and = TRUE; + gboolean rule_has_expressions; const char *rule_id = xmlGetProp(rule, XML_ATTR_ID); const char *score = xmlGetProp(rule, "score"); const char *result = xmlGetProp(rule, "result"); const char *boolean = xmlGetProp(rule, "boolean_op"); GListPtr match_L = NULL; GListPtr old_list = NULL; float score_f = atof(score?score:"0.0"); rsc_to_node_t *new_con = NULL; were_rules = TRUE; if(safe_str_eq(boolean, "or")) { do_and = FALSE; } if(result == NULL || (safe_str_eq(result, "can"))) { can_run = TRUE; } new_con = rsc2node_new(rule_id, rsc_lh, score_f, can_run, NULL, node_constraints); if(new_con == NULL) { continue; } - gboolean rule_has_expressions = FALSE; + rule_has_expressions = FALSE; xml_child_iter( rule, expr, "expression", const char *attr = xmlGetProp(expr, "attribute"); const char *op = xmlGetProp(expr, "operation"); const char *value = xmlGetProp(expr, "value"); const char *type = xmlGetProp(expr, "type"); rule_has_expressions = TRUE; crm_trace("processing expression: %s", xmlGetProp(expr, "id")); match_L = match_attrs( attr, op, value, type, node_list); if(first_expr) { new_con->node_list_rh = node_list_dup( match_L, FALSE); first_expr = FALSE; continue; } old_list = new_con->node_list_rh; if(do_and) { crm_trace("do_and"); new_con->node_list_rh = node_list_and( old_list, match_L, FALSE); } else { crm_trace("do_or"); new_con->node_list_rh = node_list_or( old_list, match_L, FALSE); } pe_free_shallow_adv(match_L, FALSE); pe_free_shallow_adv(old_list, TRUE); ); if(rule_has_expressions == FALSE) { /* feels like a hack */ crm_debug("Rule %s had no expressions," " adding all nodes", xmlGetProp(rule, "id")); new_con->node_list_rh = node_list_dup(node_list,FALSE); } if(new_con->node_list_rh == NULL) { crm_warn("No matching nodes for constraint/rule %s/%s", id, xmlGetProp(rule, "id")); } crm_debug_action(print_rsc_to_node("Added", new_con, FALSE)); ); if(were_rules == FALSE) { crm_err("no rules for constraint %s", id); } return TRUE; } diff --git a/crm/tengine/ttest.c b/crm/tengine/ttest.c index 68edec9f7f..3388d97c81 100644 --- a/crm/tengine/ttest.c +++ b/crm/tengine/ttest.c @@ -1,163 +1,164 @@ -/* $Id: ttest.c,v 1.12 2004/10/21 18:25:43 andrew Exp $ */ +/* $Id: ttest.c,v 1.13 2004/10/24 12:38:33 lge Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #define OPTARGS "V?" #include #include #include #include extern gboolean unpack_graph(xmlNodePtr xml_graph); extern gboolean initiate_transition(void); extern gboolean initialize_graph(void); GMainLoop* mainloop = NULL; int main(int argc, char **argv) { int flag; int argerr = 0; xmlNodePtr xml_graph = NULL; + xmlNodePtr options = NULL; + IPC_Channel* channels[2]; cl_log_set_entity("ttest"); cl_log_set_facility(LOG_USER); while (1) { int option_index = 0; static struct option long_options[] = { /* Top-level Options */ {"daemon", 0, 0, 0}, {0, 0, 0, 0} }; flag = getopt_long(argc, argv, OPTARGS, long_options, &option_index); if (flag == -1) break; switch(flag) { case 0: printf("option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; /* a sample test for multiple instance if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); */ case 'V': alter_debug(DEBUG_INC); break; default: printf("?? getopt returned character code 0%o ??\n", flag); ++argerr; break; } } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); printf("\n"); } if (optind > argc) { ++argerr; } if (argerr) { crm_err("%d errors in option parsing", argerr); } crm_debug("=#=#=#=#= Getting XML =#=#=#=#="); #ifdef MTRACE mtrace(); #endif - IPC_Channel* channels[2]; if (ipc_channel_pair(channels) != IPC_OK) { cl_perror("Can't create ipc channel pair"); exit(1); } crm_ch = channels[0]; G_main_add_IPC_Channel(G_PRIORITY_LOW, channels[1], FALSE, subsystem_msg_dispatch, (void*)process_te_message, default_ipc_connection_destroy); crm_trace("Initializing graph..."); initialize_graph(); xml_graph = file2xml(stdin); /* send transition graph over IPC instead */ - xmlNodePtr options = create_xml_node(NULL, XML_TAG_OPTIONS); + options = create_xml_node(NULL, XML_TAG_OPTIONS); set_xml_property_copy(options, XML_ATTR_OP, CRM_OP_TRANSITION); send_ipc_request(channels[0], options, xml_graph, NULL, CRM_SYSTEM_TENGINE, CRM_SYSTEM_TENGINE, NULL, NULL); free_xml(options); free_xml(xml_graph); /* Create the mainloop and run it... */ mainloop = g_main_new(FALSE); crm_debug("Starting mainloop"); g_main_run(mainloop); initialize_graph(); #ifdef MTRACE muntrace(); #endif crm_trace("Transition complete..."); return 0; } diff --git a/crm/tengine/unpack.c b/crm/tengine/unpack.c index 2e4a494c07..5814e3e123 100644 --- a/crm/tengine/unpack.c +++ b/crm/tengine/unpack.c @@ -1,476 +1,477 @@ -/* $Id: unpack.c,v 1.7 2004/10/01 13:23:45 andrew Exp $ */ +/* $Id: unpack.c,v 1.8 2004/10/24 12:38:33 lge Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include gboolean process_te_message(xmlNodePtr msg, IPC_Channel *sender); action_t* unpack_action(xmlNodePtr xml_action); xmlNodePtr create_shutdown_event(const char *node, int op_status); void set_timer_value(te_timer_t *timer, const char *time, int time_default); extern int transition_counter; void set_timer_value(te_timer_t *timer, const char *time, int time_default) { timer->timeout = time_default; if(time != NULL) { int tmp_time = atoi(time); if(tmp_time > 0) { timer->timeout = tmp_time; } } } gboolean unpack_graph(xmlNodePtr xml_graph) { /* timeout; time = xmlGetProp(xml_graph, "transition_fuzz"); set_timer_value(transition_fuzz_timer, time, transition_fuzz_timeout); transition_counter++; crm_info("Beginning transition %d - timeout set to %d", transition_counter, transition_timer->timeout); xml_child_iter( xml_graph, synapse, "synapse", synapse_t *new_synapse = NULL; crm_malloc(new_synapse, sizeof(synapse_t)); new_synapse->id = num_synapses++; new_synapse->complete = FALSE; new_synapse->confirmed = FALSE; new_synapse->actions = NULL; new_synapse->inputs = NULL; graph = g_list_append(graph, new_synapse); xml_child_iter( synapse, actions, "action_set", xml_child_iter( actions, action, NULL, action_t *new_action = unpack_action(action); num_actions++; if(new_action == NULL) { action = action->next; break; } new_synapse->actions = g_list_append( new_synapse->actions, new_action); ); ); xml_child_iter( synapse, inputs, "inputs", xml_child_iter( inputs, trigger, NULL, xml_child_iter( trigger, input, NULL, action_t *new_input = unpack_action(input); if(new_input == NULL) { input = input->next; break; } new_synapse->inputs = g_list_append( new_synapse->inputs, new_input); ); ); ); ); crm_info("Unpacked %d actions in %d synapses", num_actions, num_synapses); if(num_actions > 0) { return TRUE; } else { /* indicate to caller that there's nothing to do */ return FALSE; } } action_t* unpack_action(xmlNodePtr xml_action) { const char *tmp = xmlGetProp(xml_action, "id"); action_t *action = NULL; xmlNodePtr action_copy = NULL; if(tmp == NULL) { crm_err("Actions must have an id!"); crm_xml_devel(xml_action, "Action with missing id"); return NULL; } action_copy = copy_xml_node_recursive(xml_action); crm_malloc(action, sizeof(action_t)); if(action == NULL) { return NULL; } action->id = atoi(tmp); action->timeout = 0; action->timer = NULL; action->invoked = FALSE; action->complete = FALSE; action->can_fail = FALSE; action->type = action_type_rsc; action->xml = action_copy; if(safe_str_eq(action_copy->name, "rsc_op")) { action->type = action_type_rsc; } else if(safe_str_eq(action_copy->name, "pseudo_event")) { action->type = action_type_pseudo; } else if(safe_str_eq(action_copy->name, "crm_event")) { action->type = action_type_crm; } tmp = xmlGetProp(action_copy, "timeout"); if(tmp != NULL) { action->timeout = atoi(tmp); } crm_debug("Action %d has timer set to %d", action->id, action->timeout); crm_malloc(action->timer, sizeof(te_timer_t)); action->timer->timeout = action->timeout; action->timer->source_id = -1; action->timer->reason = timeout_action; action->timer->action = action; tmp = xmlGetProp(action_copy, "can_fail"); if(safe_str_eq(tmp, "true")) { action->can_fail = TRUE; } return action; } gboolean extract_event(xmlNodePtr msg) { gboolean abort = FALSE; xmlNodePtr iter = NULL; xmlNodePtr cib = NULL; const char *section = NULL; const char *event_node = NULL; /* [cib fragment] ... */ crm_trace("Extracting event"); iter = find_xml_node(msg, XML_TAG_FRAGMENT); section = xmlGetProp(iter, XML_ATTR_SECTION); if(safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) { /* ignore - for the moment */ crm_debug("Ignoring changes to the %s section", XML_CIB_TAG_CRMCONFIG); return TRUE; } else if(safe_str_neq(section, XML_CIB_TAG_STATUS)) { /* these too are never expected */ crm_debug("Ignoring changes outside the %s section", XML_CIB_TAG_STATUS); return FALSE; } cib = find_xml_node(iter, XML_TAG_CIB); iter = get_object_root(XML_CIB_TAG_STATUS, cib); if(iter != NULL) { iter = iter->children; } else { crm_xml_warn(cib, XML_CIB_TAG_STATUS " section missing?"); } while(abort == FALSE && iter != NULL) { xmlNodePtr node_state = iter; xmlNodePtr child = iter->children; + xmlNodePtr shutdown = NULL; const char *state = xmlGetProp( node_state, XML_CIB_ATTR_CRMDSTATE); iter = iter->next; crm_xml_devel(node_state,"Processing"); if(xmlGetProp(node_state, XML_CIB_ATTR_SHUTDOWN) != NULL) { crm_trace("Aborting on %s attribute", XML_CIB_ATTR_SHUTDOWN); abort = TRUE; } else if(xmlGetProp(node_state, XML_CIB_ATTR_STONITH) != NULL) { /* node marked for STONITH * possibly by us when a shutdown timmed out */ crm_trace("Checking for STONITH"); event_node = xmlGetProp(node_state, XML_ATTR_UNAME); - xmlNodePtr shutdown = create_shutdown_event( + shutdown = create_shutdown_event( event_node, LRM_OP_TIMEOUT); process_graph_event(shutdown); free_xml(shutdown); } else if(state != NULL && child == NULL) { /* simple node state update... * possibly from a shutdown we requested */ crm_trace("Processing simple state update"); if(safe_str_neq(state, OFFLINESTATUS)) { /* always recompute */ abort = TRUE; continue; } event_node = xmlGetProp(node_state, XML_ATTR_UNAME); - xmlNodePtr shutdown = create_shutdown_event( + shutdown = create_shutdown_event( event_node, LRM_OP_DONE); process_graph_event(shutdown); free_xml(shutdown); } else if(state == NULL && child != NULL) { /* LRM resource update... */ crm_trace("Processing LRM resource update"); child = find_xml_node(node_state, XML_CIB_TAG_LRM); child = find_xml_node(child, XML_LRM_TAG_RESOURCES); if(child != NULL) { child = child->children; } else { abort = TRUE; } event_node = xmlGetProp(node_state, XML_ATTR_UNAME); while(abort == FALSE && child != NULL) { process_graph_event(child); child = child->next; } } else if(state != NULL && child != NULL) { /* this is a complex event and could not be completely * due to any request we made */ crm_trace("Aborting on complex update"); abort = TRUE; } else { /* ignore */ crm_err("Ignoring message"); } } return !abort; } gboolean process_te_message(xmlNodePtr msg, IPC_Channel *sender) { xmlNodePtr graph = NULL; const char *sys_to = xmlGetProp(msg, XML_ATTR_SYSTO); const char *ref = xmlGetProp(msg, XML_ATTR_REFERENCE); const char *op = get_xml_attr( msg, XML_TAG_OPTIONS, XML_ATTR_OP, FALSE); crm_debug("Recieved %s (%s) message", op, ref); - -#ifdef MSG_LOG - struct stat buf; - if(stat(DEVEL_DIR, &buf) != 0) { - cl_perror("Stat of %s failed... exiting", DEVEL_DIR); - exit(100); - } - - if(msg_te_strm == NULL) { - msg_te_strm = fopen(DEVEL_DIR"/te.log", "w"); + if (MSG_LOG) { + struct stat buf; + char *xml; + if(stat(DEVEL_DIR, &buf) != 0) { + cl_perror("Stat of %s failed... exiting", DEVEL_DIR); + exit(100); + } + + if(msg_te_strm == NULL) { + msg_te_strm = fopen(DEVEL_DIR"/te.log", "w"); + } + xml = dump_xml_formatted(msg); + fprintf(msg_te_strm, "[Input %s]\t%s\n", + op, xml); + fflush(msg_te_strm); + crm_free(xml); } - char *xml = dump_xml_formatted(msg); - fprintf(msg_te_strm, "[Input %s]\t%s\n", - op, xml); - fflush(msg_te_strm); - crm_free(xml); -#endif if(safe_str_eq(xmlGetProp(msg, XML_ATTR_MSGTYPE), XML_ATTR_RESPONSE) && safe_str_neq(op, CRM_OP_EVENTCC)) { #ifdef MSG_LOG fprintf(msg_te_strm, "[Result ]\tDiscarded\n"); fflush(msg_te_strm); #endif crm_info("Message was a response not a request. Discarding"); return TRUE; } crm_debug("Processing %s (%s) message", op, ref); if(op == NULL){ /* error */ } else if(strcmp(op, CRM_OP_HELLO) == 0) { /* ignore */ } else if(sys_to == NULL || strcmp(sys_to, CRM_SYSTEM_TENGINE) != 0) { crm_verbose("Bad sys-to %s", crm_str(sys_to)); return FALSE; } else if(strcmp(op, CRM_OP_TRANSITION) == 0) { crm_trace("Initializing graph..."); initialize_graph(); graph = find_xml_node(msg, "transition_graph"); crm_trace("Unpacking graph..."); unpack_graph(graph); crm_trace("Initiating transition..."); in_transition = TRUE; if(initiate_transition() == FALSE) { /* nothing to be done.. means we're done. */ crm_info("No actions to be taken..." " transition compelte."); } crm_trace("Processing complete..."); } else if(strcmp(op, CRM_OP_ABORT) == 0) { initialize_graph(); } else if(strcmp(op, CRM_OP_QUIT) == 0) { crm_err("Received quit message, terminating"); exit(0); } else if(in_transition == FALSE) { crm_info("Received event_cc while not in a transition..." " Poking the Policy Engine"); send_abort("Initiate a transition", NULL); } else if(strcmp(op, CRM_OP_EVENTCC) == 0) { const char *true_op = get_xml_attr (msg, XML_TAG_OPTIONS, XML_ATTR_TRUEOP, TRUE); crm_trace("Processing %s...", CRM_OP_EVENTCC); if(true_op == NULL) { crm_err( "Illegal update," " the original operation must be specified"); send_abort("Illegal update", msg); } else if(strcmp(true_op, CRM_OP_CREATE) == 0 || strcmp(true_op, CRM_OP_DELETE) == 0 || strcmp(true_op, CRM_OP_REPLACE) == 0 || strcmp(true_op, CRM_OP_WELCOME) == 0 || strcmp(true_op, CRM_OP_SHUTDOWN_REQ) == 0 || strcmp(true_op, CRM_OP_ERASE) == 0) { /* these are always unexpected, trigger the PE */ send_abort("Config update", msg); } else if(strcmp(true_op, CRM_OP_UPDATE) == 0) { /* this may not be un-expected */ /* if( */ extract_event(msg); /* == FALSE){ send_abort(msg); } */ } else { crm_err( "Did not expect copy of action %s", op); } } crm_debug("finished processing message"); print_state(FALSE); return TRUE; } xmlNodePtr create_shutdown_event(const char *node, int op_status) { xmlNodePtr event = create_xml_node(NULL, XML_CIB_TAG_STATE); char *code = crm_itoa(op_status); set_xml_property_copy(event, XML_LRM_ATTR_TARGET, node); /* event_rsc = set_xml_property_copy(event, XML_ATTR_ID); */ set_xml_property_copy(event, XML_LRM_ATTR_RC, "0"); set_xml_property_copy( event, XML_LRM_ATTR_LASTOP, XML_CIB_ATTR_SHUTDOWN); set_xml_property_copy( event, XML_LRM_ATTR_RSCSTATE, CRMD_RSCSTATE_GENERIC_OK); set_xml_property_copy(event, XML_LRM_ATTR_OPSTATUS, code); crm_free(code); return event; } diff --git a/include/crm/crm.h b/include/crm/crm.h index 81b753e776..6abe59d62a 100644 --- a/include/crm/crm.h +++ b/include/crm/crm.h @@ -1,191 +1,191 @@ -/* $Id: crm.h,v 1.29 2004/10/18 19:03:57 andrew Exp $ */ +/* $Id: crm.h,v 1.30 2004/10/24 12:38:33 lge Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CRM__H #define CRM__H #include #include #include #include #include #include #ifdef MCHECK #include #endif #include /* Clean these up at some point, some probably should be runtime options */ #define WORKING_DIR HA_VARLIBDIR"/heartbeat/crm" #define BIN_DIR "/usr/lib/heartbeat" #define MAXDATASIZE 65535 /* ipc comms */ #define SOCKET_LEN 1024 #define APPNAME_LEN 256 #define LOG_DIR "/var/log" #define MAX_IPC_FAIL 5 #define CIB_FILENAME WORKING_DIR"/cib.xml" #define CIB_BACKUP WORKING_DIR"/cib_backup.xml" #define DEVEL_CIB_COPY 1 #define DEVEL_DIR "/tmp/crm" #define CRM_VERSION "0.6" #define MSG_LOG 1 #define DOT_FSA_ACTIONS 1 #define DOT_ALL_FSA_INPUTS 1 #define FSA_TRACE 1 /* #define USE_FAKE_LRM 1 */ /* Sub-systems */ #define CRM_SYSTEM_DC "dc" #define CRM_SYSTEM_DCIB "dcib" /* The master CIB */ #define CRM_SYSTEM_CIB "cib" #define CRM_SYSTEM_CRMD "crmd" #define CRM_SYSTEM_LRMD "lrmd" #define CRM_SYSTEM_PENGINE "pengine" #define CRM_SYSTEM_TENGINE "tengine" /* Valid operations */ #define CRM_OP_BUMP "bump" #define CRM_OP_QUERY "query" #define CRM_OP_CREATE "create" #define CRM_OP_UPDATE "update" #define CRM_OP_DELETE "delete" #define CRM_OP_ERASE "erase" #define CRM_OP_REPLACE "replace" #define CRM_OP_RETRIVE_CIB "retrieve_cib" #define CRM_OP_JOINACK "join_ack_nack" #define CRM_OP_WELCOME "welcome" #define CRM_OP_PING "ping" #define CRM_OP_VOTE "vote" #define CRM_OP_HELLO "hello" #define CRM_OP_ANNOUNCE "announce" #define CRM_OP_HBEAT "dc_beat" #define CRM_OP_PECALC "pe_calc" #define CRM_OP_ABORT "abort" #define CRM_OP_QUIT "quit" #define CRM_OP_SHUTDOWN "shutdown_crm" #define CRM_OP_EVENTCC "event_cc" #define CRM_OP_TEABORT "te_abort" #define CRM_OP_TRANSITION "transition" #define CRM_OP_TECOMPLETE "te_complete" #define CRM_OP_SHUTDOWN_REQ "req_shutdown" #define CRMD_STATE_ACTIVE "member" #define CRMD_STATE_INACTIVE "down" #define CRMD_JOINSTATE_DOWN "down" #define CRMD_JOINSTATE_PENDING "pending" #define CRMD_JOINSTATE_MEMBER "member" #define CRMD_RSCSTATE_START "start" #define CRMD_RSCSTATE_START_PENDING "starting" #define CRMD_RSCSTATE_START_OK "running" #define CRMD_RSCSTATE_START_FAIL "start_failed" #define CRMD_RSCSTATE_STOP "stop" #define CRMD_RSCSTATE_STOP_PENDING "stopping" #define CRMD_RSCSTATE_STOP_OK "stopped" #define CRMD_RSCSTATE_STOP_FAIL "stop_failed" #define CRMD_RSCSTATE_MON "status" #define CRMD_RSCSTATE_MON_PENDING CRMD_RSCSTATE_START_OK #define CRMD_RSCSTATE_MON_OK CRMD_RSCSTATE_START_OK #define CRMD_RSCSTATE_MON_FAIL "status_failed" /* #define CRMD_RSCSTATE_GENERIC "pending" */ #define CRMD_RSCSTATE_GENERIC_PENDING "pending" #define CRMD_RSCSTATE_GENERIC_OK "complete" #define CRMD_RSCSTATE_GENERIC_FAIL "pending_failed" typedef GList* GListPtr; #define safe_str_eq(x, y) (x!=NULL && y!=NULL && strcmp(x,y) == 0) #define safe_str_neq(x, y) (x != y && (x==NULL || y==NULL || strcmp(x,y) != 0)) #define slist_iter(w, x, y, z, a) \ { \ GListPtr __crm_iter_head = y; \ x *w = NULL; \ z = 0; \ while(__crm_iter_head != NULL) { \ z++; \ w = __crm_iter_head->data; \ __crm_iter_head = __crm_iter_head->next; \ - a; \ + { a; } \ } \ } \ /* Developmental debug stuff */ #define LOG_VERBOSE LOG_DEBUG+1 #define LOG_DEV LOG_DEBUG+2 #define LOG_TRACE LOG_DEBUG+3 #if 1 # define crm_crit(w...) do_crm_log(LOG_CRIT, __FUNCTION__, w) # define crm_err(w...) do_crm_log(LOG_ERR, __FUNCTION__, w) # define crm_warn(w...) do_crm_log(LOG_WARNING, __FUNCTION__, w) # define crm_notice(w...) do_crm_log(LOG_NOTICE, __FUNCTION__, w) # define crm_info(w...) do_crm_log(LOG_INFO, __FUNCTION__, w) # define crm_debug(w...) do_crm_log(LOG_DEBUG, __FUNCTION__, w) # define crm_devel(w...) do_crm_log(LOG_DEV, __FUNCTION__, w) # define crm_verbose(w...) do_crm_log(LOG_VERBOSE, __FUNCTION__, w) # define crm_trace(w...) do_crm_log(LOG_TRACE, __FUNCTION__, w) #else # define crm_crit(w...) cl_log(LOG_CRIT, w) # define crm_err(w...) cl_log(LOG_ERR, w) # define crm_warn(w...) cl_log(LOG_WARNING, w) # define crm_notice(w...) cl_log(LOG_NOTICE, w) # define crm_info(w...) cl_log(LOG_INFO, w) # define crm_debug(w...) cl_log(LOG_DEBUG, w) # define crm_devel(w...) cl_log(LOG_DEV, w) # define crm_verbose(w...) cl_log(LOG_VERBOSE, w) # define crm_trace(w...) cl_log(LOG_TRACE, w) #endif #define crm_debug_action(x) if(crm_log_level >= LOG_DEBUG) { \ x; \ } #define crm_info_action(x) if(crm_log_level >= LOG_INFO) { \ x; \ } #define crm_xml_crit(x,y) print_xml_formatted(LOG_CRIT, __FUNCTION__, x,y) #define crm_xml_err(x,y) print_xml_formatted(LOG_ERR, __FUNCTION__, x,y) #define crm_xml_warn(x,y) print_xml_formatted(LOG_WARNING,__FUNCTION__, x,y) #define crm_xml_notice(x,y) print_xml_formatted(LOG_NOTICE, __FUNCTION__, x,y) #define crm_xml_info(x,y) print_xml_formatted(LOG_INFO, __FUNCTION__, x,y) #define crm_xml_debug(x,y) print_xml_formatted(LOG_DEBUG, __FUNCTION__, x,y) #define crm_xml_devel(x,y) print_xml_formatted(LOG_DEV, __FUNCTION__, x,y) #define crm_xml_verbose(x,y) print_xml_formatted(LOG_VERBOSE,__FUNCTION__, x,y) #define crm_xml_trace(x,y) print_xml_formatted(LOG_TRACE, __FUNCTION__, x,y) #define crm_malloc(x,y) \ { \ x = cl_malloc(y); \ if(x == NULL) { \ crm_crit("Out of memory... exiting"); \ exit(1); \ } \ } \ #define crm_strdup(x) cl_strdup(x) #define crm_free(x) if(x) { cl_free(x); x=NULL; } #define crm_str(x) (const char*)(x?x:"") #endif