diff --git a/crm/pengine/stages.c b/crm/pengine/stages.c index 5fd963b90d..7e9b17703d 100644 --- a/crm/pengine/stages.c +++ b/crm/pengine/stages.c @@ -1,515 +1,515 @@ -/* $Id: stages.c,v 1.79 2005/10/05 16:33:57 andrew Exp $ */ +/* $Id: stages.c,v 1.80 2005/10/12 18:46:25 andrew 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 node_t *choose_fencer(action_t *stonith, node_t *node, GListPtr resources); void order_actions(action_t *lh, action_t *rh, order_constraint_t *order); /* * Unpack everything * At the end you'll have: * - A list of nodes * - A list of resources (each with any dependencies on other resources) * - A list of constraints between resources and nodes * - A list of constraints between start/stop actions * - A list of nodes that need to be stonith'd * - A list of nodes that need to be shutdown * - A list of the possible stop/start actions (without dependencies) */ gboolean stage0(pe_working_set_t *data_set) { /* int lpc; */ crm_data_t * config = get_object_root( XML_CIB_TAG_CRMCONFIG, data_set->input); crm_data_t * cib_nodes = get_object_root( XML_CIB_TAG_NODES, data_set->input); crm_data_t * cib_resources = get_object_root( XML_CIB_TAG_RESOURCES, data_set->input); crm_data_t * cib_status = get_object_root( XML_CIB_TAG_STATUS, data_set->input); crm_data_t * cib_constraints = get_object_root( XML_CIB_TAG_CONSTRAINTS, data_set->input); const char *value = crm_element_value( data_set->input, XML_ATTR_HAVE_QUORUM); crm_debug_3("Beginning unpack"); /* reset remaining global variables */ if(data_set->input == NULL) { return FALSE; } if(data_set->input != NULL && crm_element_value(data_set->input, XML_ATTR_DC_UUID) != NULL) { /* this should always be present */ data_set->dc_uuid = crm_element_value_copy( data_set->input, XML_ATTR_DC_UUID); } data_set->no_color = create_color(data_set, NULL, NULL); unpack_config(config, data_set); if(value != NULL) { cl_str_to_boolean(value, &data_set->have_quorum); } if(data_set->have_quorum == FALSE && data_set->no_quorum_policy != no_quorum_ignore) { crm_warn("We do not have quorum" " - fencing and resource management disabled"); } unpack_nodes(cib_nodes, data_set); unpack_resources(cib_resources, data_set); unpack_status(cib_status, data_set); unpack_constraints(cib_constraints, data_set); return TRUE; } /* * Count how many valid nodes we have (so we know the maximum number of * colors we can resolve). * * Apply node constraints (ie. filter the "allowed_nodes" part of resources */ gboolean stage1(pe_working_set_t *data_set) { crm_debug_3("Applying placement constraints"); slist_iter( node, node_t, data_set->nodes, lpc, if(node == NULL) { /* error */ } else if(node->weight >= 0.0 /* global weight */ && node->details->online && node->details->type == node_member) { data_set->max_valid_nodes++; } ); apply_placement_constraints(data_set); return TRUE; } /* * Choose a color for all resources from highest priority and XML_STRENGTH_VAL_MUST * dependencies to lowest, creating new colors as necessary (returned * as "colors"). * * Some nodes may be colored as a "no_color" meaning that it was unresolvable * given the current node stati and constraints. */ gboolean stage2(pe_working_set_t *data_set) { crm_debug_3("Coloring resources"); crm_debug_5("create \"no color\""); /* Take (next) highest resource */ slist_iter( lh_resource, resource_t, data_set->resources, lpc, /* if resource.provisional == FALSE, repeat */ if(lh_resource->provisional == FALSE) { /* already processed this resource */ continue; } crm_debug_2("Coloring %s::%d", lh_resource->id, lh_resource->variant); color_resource(lh_resource, data_set); /* next resource */ ); return TRUE; } /* * Check nodes for resources started outside of the LRM */ gboolean stage3(pe_working_set_t *data_set) { action_t *probe_complete = NULL; action_t *probe_node_complete = NULL; slist_iter( node, node_t, data_set->nodes, lpc, const char *probed = g_hash_table_lookup( - node->details->attrs, CRMD_ACTION_PROBED); + node->details->attrs, CRM_OP_PROBED); crm_info("%s probed: %s", node->details->uname, probed); if(crm_is_true(probed)) { continue; } else if(node->details->online == FALSE) { continue; } else if(node->details->unclean) { continue; } else if(probe_complete == NULL) { probe_complete = custom_action( - NULL, crm_strdup(CRMD_ACTION_PROBED), - CRMD_ACTION_PROBED, NULL, FALSE, TRUE, + NULL, crm_strdup(CRM_OP_PROBED), + CRM_OP_PROBED, NULL, FALSE, TRUE, data_set); probe_complete->pseudo = TRUE; } probe_node_complete = custom_action( - NULL, crm_strdup(CRMD_ACTION_PROBED), - CRMD_ACTION_PROBED, node, FALSE, TRUE, data_set); + NULL, crm_strdup(CRM_OP_PROBED), + CRM_OP_PROBED, node, FALSE, TRUE, data_set); add_hash_param(probe_node_complete->extra, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); custom_action_order(NULL, NULL, probe_node_complete, NULL, NULL, probe_complete, pe_ordering_manditory, data_set); slist_iter( rsc, resource_t, data_set->resources, lpc2, if(rsc->fns->create_probe( rsc, node, probe_node_complete, data_set)) { custom_action_order( NULL, NULL, probe_complete, rsc, start_key(rsc), NULL, pe_ordering_manditory, data_set); } ); ); return TRUE; } /* * Choose a node for each (if possible) color */ gboolean stage4(pe_working_set_t *data_set) { node_t *chosen = NULL; crm_debug_3("Assigning nodes to colors"); slist_iter( color, color_t, data_set->colors, lpc, crm_debug_4("assigning node to color %d", color->id); if(color == NULL) { pe_err("NULL color detected"); continue; } else if(color->details->pending == FALSE) { continue; } choose_node_from_list(color); chosen = color->details->chosen_node; slist_iter( rsc, resource_t, color->details->allocated_resources, lpc2, crm_debug_2("Processing colocation constraints for %s" " now that color %d is allocated", rsc->id, color->details->id); if(rsc->next_role != RSC_ROLE_UNKNOWN) { } else if(chosen == NULL) { rsc->next_role = RSC_ROLE_STOPPED; } else { rsc->next_role = RSC_ROLE_STARTED; } slist_iter( constraint, rsc_colocation_t, rsc->rsc_cons, lpc, rsc->fns->rsc_colocation_lh( rsc, constraint->rsc_rh, constraint); ); ); ); crm_debug_3("done"); return TRUE; } /* * Attach nodes to the actions that need to be taken * * Mark actions XML_LRM_ATTR_OPTIONAL if possible (Ie. if the start and stop are * for the same node) * * Mark unrunnable actions */ gboolean stage5(pe_working_set_t *data_set) { crm_debug_3("Creating actions and internal ording constraints"); slist_iter( rsc, resource_t, data_set->resources, lpc, rsc->fns->create_actions(rsc, data_set); rsc->fns->internal_constraints(rsc, data_set); ); return TRUE; } /* * Create dependacies for stonith and shutdown operations */ gboolean stage6(pe_working_set_t *data_set) { action_t *down_op = NULL; action_t *stonith_op = NULL; crm_debug_3("Processing fencing and shutdown cases"); slist_iter( node, node_t, data_set->nodes, lpc, if(node->details->online && node->details->shutdown) { crm_info("Scheduling Node %s for shutdown", node->details->uname); down_op = custom_action( NULL, crm_strdup(CRM_OP_SHUTDOWN), CRM_OP_SHUTDOWN, node, FALSE, TRUE, data_set); down_op->runnable = TRUE; shutdown_constraints( node, down_op, data_set); } if(node->details->unclean && data_set->stonith_enabled == FALSE) { pe_err("Node %s is unclean!", node->details->uname); pe_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED"); pe_warn("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE"); } else if(node->details->unclean && data_set->stonith_enabled && (data_set->have_quorum || data_set->no_quorum_policy == no_quorum_ignore)) { pe_warn("Scheduling Node %s for STONITH", node->details->uname); stonith_op = custom_action( NULL, crm_strdup(CRM_OP_FENCE), CRM_OP_FENCE, node, FALSE, TRUE, data_set); stonith_op->runnable = TRUE; add_hash_param( stonith_op->extra, XML_LRM_ATTR_TARGET, node->details->uname); add_hash_param( stonith_op->extra, XML_LRM_ATTR_TARGET_UUID, node->details->id); if(down_op != NULL) { down_op->failure_is_fatal = FALSE; } } if(node->details->unclean) { stonith_constraints( node, stonith_op, down_op, data_set); } ); return TRUE; } /* * Determin the sets of independant actions and the correct order for the * actions in each set. * * Mark dependencies of un-runnable actions un-runnable * */ gboolean stage7(pe_working_set_t *data_set) { crm_debug_3("Applying ordering constraints"); slist_iter( order, order_constraint_t, data_set->ordering_constraints, lpc, /* try rsc_action-to-rsc_action */ resource_t *rsc = order->lh_rsc; if(rsc == NULL && order->lh_action) { rsc = order->lh_action->rsc; } if(rsc != NULL) { rsc->fns->rsc_order_lh(rsc, order); continue; } /* try action-to-rsc_action */ /* que off the rh resource */ rsc = order->rh_rsc; if(rsc == NULL && order->rh_action) { rsc = order->rh_action->rsc; } if(rsc != NULL) { rsc->fns->rsc_order_rh(order->lh_action, rsc, order); } else { /* fall back to action-to-action */ order_actions( order->lh_action, order->rh_action, order); } ); update_action_states(data_set->actions); return TRUE; } static int transition_id = -1; /* * Create a dependency graph to send to the transitioner (via the CRMd) */ gboolean stage8(pe_working_set_t *data_set) { char *transition_id_s = NULL; transition_id++; transition_id_s = crm_itoa(transition_id); crm_info("Creating transition graph %d.", transition_id); data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH); crm_xml_add(data_set->graph, "global_timeout", data_set->transition_idle_timeout); crm_xml_add(data_set->graph, "transition_id", transition_id_s); crm_free(transition_id_s); /* errors... slist_iter(action, action_t, action_list, lpc, if(action->optional == FALSE && action->runnable == FALSE) { print_action("Ignoring", action, TRUE); } ); */ slist_iter( rsc, resource_t, data_set->resources, lpc, crm_debug_4("processing actions for rsc=%s", rsc->id); rsc->fns->expand(rsc, data_set); ); crm_log_xml_debug_3( data_set->graph, "created resource-driven action list"); /* catch any non-resource specific actions */ crm_debug_4("processing non-resource actions"); slist_iter( action, action_t, data_set->actions, lpc, graph_element_from_action(action, data_set); ); crm_log_xml_debug_3(data_set->graph, "created generic action list"); return TRUE; } gboolean choose_node_from_list(color_t *color) { /* 1. Sort by weight 2. color.chosen_node = the node (of those with the highest wieght) with the fewest resources 3. remove color.chosen_node from all other colors */ GListPtr nodes = color->details->candidate_nodes; node_t *chosen = NULL; crm_debug("Choosing node for color %d", color->id); color->details->candidate_nodes = g_list_sort(nodes, sort_node_weight); chosen = g_list_nth_data(color->details->candidate_nodes, 0); color->details->chosen_node = NULL; color->details->pending = FALSE; if(chosen == NULL) { crm_debug_2("Could not allocate a node for color %d", color->id); return FALSE; } else if(chosen->details->unclean || chosen->details->shutdown) { crm_debug_2("Even highest ranked node for color %d" " is unclean or shutting down", color->id); color->details->chosen_node = NULL; return FALSE; } else if(chosen->weight < 0) { crm_debug_2("Even highest ranked node for color %d, had weight %d", color->id, chosen->weight); color->details->chosen_node = NULL; return FALSE; } /* todo: update the old node for each resource to reflect its * new resource count */ crm_debug_2("assigned %s to color %d",chosen->details->uname,color->id); chosen->details->num_resources += color->details->num_resources; color->details->chosen_node = node_copy(chosen); return TRUE; } diff --git a/crm/tengine/callbacks.c b/crm/tengine/callbacks.c index edfd859095..9258bda579 100644 --- a/crm/tengine/callbacks.c +++ b/crm/tengine/callbacks.c @@ -1,534 +1,534 @@ -/* $Id: callbacks.c,v 1.49 2005/09/27 13:22:02 andrew Exp $ */ +/* $Id: callbacks.c,v 1.50 2005/10/12 18:46:25 andrew 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 void te_update_confirm(const char *event, HA_Message *msg); void te_update_diff(const char *event, HA_Message *msg); crm_data_t *need_abort(crm_data_t *update); void cib_fencing_updated(const HA_Message *msg, int call_id, int rc, crm_data_t *output, void *user_data); void te_update_diff(const char *event, HA_Message *msg) { int rc = -1; const char *op = NULL; crm_data_t *diff = NULL; crm_data_t *aborted = NULL; const char *set_name = 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; if(msg == NULL) { crm_err("NULL update"); return; } ha_msg_value_int(msg, F_CIB_RC, &rc); op = cl_get_string(msg, F_CIB_OPERATION); if(rc < cib_ok) { crm_debug_2("Ignoring failed %s operation: %s", op, cib_error2string(rc)); return; } 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", op, diff_del_admin_epoch,diff_del_epoch,diff_del_updates, diff_add_admin_epoch,diff_add_epoch,diff_add_updates); log_cib_diff(LOG_DEBUG_2, diff, op); set_name = "diff-added"; if(diff != NULL && aborted == NULL) { crm_data_t *section = NULL; crm_data_t *change_set = find_xml_node(diff, set_name, FALSE); change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE); if(change_set != NULL) { crm_debug_2("Checking status changes"); section=get_object_root(XML_CIB_TAG_STATUS,change_set); } if(section != NULL && extract_event(section) == FALSE) { send_complete("Unexpected status update", section, te_update, i_cancel); free_xml(diff); return; } crm_debug_2("Checking change set: %s", set_name); aborted = need_abort(change_set); } set_name = "diff-removed"; if(diff != NULL && aborted == NULL) { crm_data_t *change_set = find_xml_node(diff, set_name, FALSE); change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE); crm_debug_2("Checking change set: %s", set_name); aborted = need_abort(change_set); } if(aborted != NULL) { send_complete("Non-status change", diff, te_update, i_cancel); free_xml(diff); return; } free_xml(diff); return; } crm_data_t * need_abort(crm_data_t *update) { crm_data_t *section_xml = NULL; const char *section = NULL; if(update == NULL) { return NULL; } section = XML_CIB_TAG_NODES; section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, NULL, return section_xml; ); section = XML_CIB_TAG_RESOURCES; section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, NULL, return section_xml; ); section = XML_CIB_TAG_CONSTRAINTS; section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, NULL, return section_xml; ); section = XML_CIB_TAG_CRMCONFIG; section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, NULL, return section_xml; ); return NULL; } void te_update_confirm(const char *event, HA_Message *msg) { int rc = -1; gboolean done = FALSE; const char *op = cl_get_string(msg, F_CIB_OPERATION); const char *type = cl_get_string(msg, F_CIB_OBJTYPE); crm_data_t *update = get_message_xml(msg, F_CIB_UPDATE); ha_msg_value_int(msg, F_CIB_RC, &rc); crm_debug("Processing %s...", event); crm_log_xml_debug_2(update, "Processing update"); if(op == NULL) { crm_err("Illegal CIB update, the operation must be specified"); send_complete("Illegal update", update, te_update, i_cancel); done = TRUE; } else if(te_fsa_state == s_abort_pending) { /* take no further actions if an abort is pending */ crm_debug("Ignoring CIB update while waiting for an abort"); done = TRUE; } else if(strcmp(op, CIB_OP_ERASE) == 0) { /* these are always unexpected, trigger the PE */ crm_err("Need to trigger an election here so that" " the current state of all nodes is obtained"); send_complete("Erase event", update, te_update, i_cancel); done = TRUE; } else if(strcmp(op, CIB_OP_CREATE) == 0 || strcmp(op, CIB_OP_DELETE) == 0 || strcmp(op, CIB_OP_REPLACE) == 0 || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) { /* these are always unexpected, trigger the PE */ send_complete("Non-update change", update, te_update, i_cancel); done = TRUE; } else if(strcmp(op, CIB_OP_UPDATE) != 0) { crm_debug_2("Ignoring %s op confirmation", op); done = TRUE; } if(done) { free_xml(update); return; } if(safe_str_eq(type, XML_CIB_TAG_CRMCONFIG)) { /* ignore - for the moment */ crm_debug("Ignoring changes to the %s section", type); } else if(safe_str_eq(type, XML_CIB_TAG_NODES)) { /* ignore new nodes until they sign up */ crm_debug("Ignoring changes to the %s section", type); } else if(safe_str_eq(type, XML_CIB_TAG_STATUS)) { /* this _may_ not be un-expected */ if(extract_event(update) == FALSE) { send_complete("Unexpected status update", update, te_update, i_cancel); } } else if(safe_str_eq(type, XML_CIB_TAG_NODES) || safe_str_eq(type, XML_CIB_TAG_RESOURCES) || safe_str_eq(type, XML_CIB_TAG_CONSTRAINTS)) { /* these are never expected */ crm_debug("Aborting on changes to the %s section", type); send_complete("Non-status update", update, te_update, i_cancel); } else if(safe_str_eq(type, XML_TAG_CIB)) { crm_data_t *section_xml = NULL; const char *section = NULL; gboolean abort = FALSE; section = XML_CIB_TAG_NODES; if(abort == FALSE) { section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, NULL, abort = TRUE; break; ); } section = XML_CIB_TAG_RESOURCES; if(abort == FALSE) { section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, NULL, abort = TRUE; break; ); } section = XML_CIB_TAG_CONSTRAINTS; if(abort == FALSE) { section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, NULL, abort = TRUE; break; ); } section = XML_CIB_TAG_CRMCONFIG; if(abort == FALSE) { section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, NULL, abort = TRUE; break; ); } if(abort) { send_complete("Non-status update", update, te_update, i_cancel); } section = XML_CIB_TAG_STATUS; if(abort == FALSE) { section_xml = get_object_root(section, update); if(extract_event(section_xml) == FALSE) { send_complete("Unexpected global status update", section_xml, te_update, i_cancel); } } } else { crm_err("Ignoring update confirmation for %s object", type); crm_log_xml_debug(update, "Ignored update"); } free_xml(update); } gboolean process_te_message(HA_Message *msg, crm_data_t *xml_data, IPC_Channel *sender) { crm_data_t *xml_obj = NULL; const char *sys_to = cl_get_string(msg, F_CRM_SYS_TO); const char *sys_from = cl_get_string(msg, F_CRM_SYS_FROM); const char *ref = cl_get_string(msg, XML_ATTR_REFERENCE); const char *op = cl_get_string(msg, F_CRM_TASK); const char *type = cl_get_string(msg, F_CRM_MSG_TYPE); crm_log_message(LOG_DEBUG_3, msg); 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_debug_2("Bad sys-to %s", crm_str(sys_to)); return FALSE; #ifdef TESTING } else if(strcmp(op, CRM_OP_EVENTCC) == 0) { crm_debug_4("Processing %s...", op); xml_obj = find_xml_node(xml_data, XML_TAG_CIB, TRUE); CRM_DEV_ASSERT(xml_obj != NULL); if(xml_obj != NULL) { xml_obj = get_object_root(XML_CIB_TAG_STATUS, xml_obj); CRM_DEV_ASSERT(xml_obj != NULL); } if(xml_obj != NULL) { crm_log_message_adv(LOG_DEBUG, "Processing Loopbacked Action", msg); extract_event(xml_obj); } else { crm_log_message_adv(LOG_ERR, "Invalid Loopbacked Action", msg); } #endif } 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) */ ){ crm_debug("Processing %s reply...", op); xml_obj = find_xml_node(xml_data, XML_TAG_CIB, TRUE); CRM_DEV_ASSERT(xml_obj != NULL); if(xml_obj != NULL) { xml_obj = get_object_root(XML_CIB_TAG_STATUS, xml_obj); CRM_DEV_ASSERT(xml_obj != NULL); } if(xml_obj != NULL) { crm_log_message_adv(LOG_DEBUG, "Processing NACK Reply", msg); extract_event(xml_obj); } else { crm_log_message_adv(LOG_ERR, "Invalid NACK Reply", msg); } } else if(safe_str_eq(type, XML_ATTR_RESPONSE)) { crm_info("Message was a response not a request. Discarding"); return TRUE; } else if(strcmp(op, CRM_OP_TRANSITION) == 0) { if(te_fsa_state != s_idle) { crm_debug("Attempt to start another transition"); send_complete("Attempt to start another transition", NULL, te_abort, i_cancel); } else { te_fsa_state = te_state_matrix[i_transition][te_fsa_state]; CRM_DEV_ASSERT(te_fsa_state == s_in_transition); initialize_graph(); unpack_graph(xml_data); crm_debug("Initiating transition..."); if(initiate_transition() == FALSE) { /* nothing to be done.. means we're done. */ crm_info("No actions to be taken..." " transition compelte."); } } } else if(strcmp(op, CRM_OP_TE_HALT) == 0) { send_complete(CRM_OP_TE_HALT, NULL, te_halt, i_cancel); } else if(strcmp(op, CRM_OP_TEABORT) == 0) { send_complete(CRM_OP_TEABORTED, NULL, te_abort, i_cancel); } else if(strcmp(op, CRM_OP_QUIT) == 0) { crm_info("Received quit message, terminating"); /* wait for pending actions to complete? */ exit(0); } 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_ops_t * op, void * private_data) { int *action_id = NULL; const char *fail_text = "Fencing op failed"; int fail_code = te_failed; void *fail_data = NULL; crm_data_t *update = NULL; if(op == NULL) { crm_err("Called with a NULL op!"); return; } crm_info("optype=%d, node_name=%s, result=%d, node_list=%s", op->optype, op->node_name, op->op_result, (char *)op->node_list); /* this will mark the event complete if a match is found */ crm_malloc0(action_id, sizeof(int)); *action_id = match_down_event( op->node_uuid, CRM_OP_FENCE, op->op_result); if(*action_id == -1) { crm_err("Stonith action not matched"); } if(op->op_result == STONITH_SUCCEEDED) { enum cib_errors rc = cib_ok; const char *target = op->node_name; const char *uuid = op->node_uuid; /* zero out the node-status & remove all LRM status info */ crm_data_t *node_state = create_xml_node( NULL, XML_CIB_TAG_STATE); CRM_DEV_ASSERT(op->node_name != NULL); CRM_DEV_ASSERT(op->node_uuid != NULL); 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_CIB_ATTR_REPLACE, XML_CIB_TAG_LRM); create_xml_node(node_state, XML_CIB_TAG_LRM); update = create_cib_fragment(node_state, XML_CIB_TAG_STATUS); free_xml(node_state); - rc = te_cib_conn->cmds->modify( + rc = te_cib_conn->cmds->update( te_cib_conn, XML_CIB_TAG_STATUS, update, NULL, cib_quorum_override); if(*action_id < 0) { fail_text = "Stonith not matched"; fail_data = update; fail_code = te_update; } else if(rc < cib_ok) { crm_err("CIB update failed: %s", cib_error2string(rc)); fail_text = "Couldnt update CIB after stonith"; fail_data = update; fail_code = te_failed; } else { add_cib_op_callback( rc, FALSE, action_id, cib_fencing_updated); free_xml(update); return; } } send_complete(fail_text, fail_data, fail_code, i_cancel); process_trigger(*action_id); free_xml(update); return; } void cib_fencing_updated(const HA_Message *msg, int call_id, int rc, crm_data_t *output, void *user_data) { int *action_id = user_data; CRM_ASSERT(action_id != NULL); if(rc < cib_ok) { HA_Message *msg_copy = ha_msg_copy(msg); const char *fail_text = "Couldnt update CIB after stonith"; crm_err("CIB update failed: %s", cib_error2string(rc)); send_complete(fail_text, msg_copy, te_failed, i_cancel); ha_msg_del(msg_copy); } else { process_trigger(*action_id); check_for_completion(); } crm_free(action_id); } void tengine_stonith_connection_destroy(gpointer user_data) { #if 0 crm_err("Fencing daemon has left us: Shutting down...NOW"); /* shutdown properly later */ CRM_DEV_ASSERT(FALSE/* fencing daemon died */); #else crm_err("Fencing daemon has left us"); #endif return; } gboolean tengine_stonith_dispatch(IPC_Channel *sender, void *user_data) { int lpc = 0; while(stonithd_op_result_ready()) { if (sender->ch_status == IPC_DISCONNECT) { /* The message which was pending for us is that * the IPC status is now IPC_DISCONNECT */ break; } if(ST_FAIL == stonithd_receive_ops_result(FALSE)) { crm_err("stonithd_receive_ops_result() failed"); } else { lpc++; } } crm_debug_2("Processed %d messages", lpc); if (sender->ch_status == IPC_DISCONNECT) { return FALSE; } return TRUE; }