diff --git a/crm/pengine/allocate.c b/crm/pengine/allocate.c index 4a4b75f35b..64f9ecc1b1 100644 --- a/crm/pengine/allocate.c +++ b/crm/pengine/allocate.c @@ -1,1402 +1,1413 @@ /* * 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 void set_alloc_actions(pe_working_set_t *data_set); void migrate_reload_madness(pe_working_set_t *data_set); resource_alloc_functions_t resource_class_alloc_functions[] = { { native_set_cmds, native_num_allowed_nodes, native_color, native_create_actions, native_create_probe, native_internal_constraints, native_agent_constraints, native_rsc_colocation_lh, native_rsc_colocation_rh, native_rsc_order_lh, native_rsc_order_rh, native_rsc_location, native_expand, native_migrate_reload, native_stonith_ordering, native_create_notify_element, }, { group_set_cmds, group_num_allowed_nodes, group_color, group_create_actions, group_create_probe, group_internal_constraints, group_agent_constraints, group_rsc_colocation_lh, group_rsc_colocation_rh, group_rsc_order_lh, group_rsc_order_rh, group_rsc_location, group_expand, group_migrate_reload, group_stonith_ordering, group_create_notify_element, }, { clone_set_cmds, clone_num_allowed_nodes, clone_color, clone_create_actions, clone_create_probe, clone_internal_constraints, clone_agent_constraints, clone_rsc_colocation_lh, clone_rsc_colocation_rh, clone_rsc_order_lh, clone_rsc_order_rh, clone_rsc_location, clone_expand, clone_migrate_reload, clone_stonith_ordering, clone_create_notify_element, }, { clone_set_cmds, clone_num_allowed_nodes, master_color, master_create_actions, clone_create_probe, master_internal_constraints, clone_agent_constraints, clone_rsc_colocation_lh, master_rsc_colocation_rh, clone_rsc_order_lh, clone_rsc_order_rh, clone_rsc_location, clone_expand, clone_migrate_reload, clone_stonith_ordering, clone_create_notify_element, } }; static gboolean check_rsc_parameters(resource_t *rsc, node_t *node, crm_data_t *rsc_entry, pe_working_set_t *data_set) { int attr_lpc = 0; gboolean force_restart = FALSE; gboolean delete_resource = FALSE; const char *value = NULL; const char *old_value = NULL; const char *attr_list[] = { XML_ATTR_TYPE, XML_AGENT_ATTR_CLASS, XML_AGENT_ATTR_PROVIDER }; for(; attr_lpc < DIMOF(attr_list); attr_lpc++) { value = crm_element_value(rsc->xml, attr_list[attr_lpc]); old_value = crm_element_value(rsc_entry, attr_list[attr_lpc]); if(value == old_value /* ie. NULL */ || crm_str_eq(value, old_value, TRUE)) { continue; } force_restart = TRUE; crm_notice("Forcing restart of %s on %s, %s changed: %s -> %s", rsc->id, node->details->uname, attr_list[attr_lpc], crm_str(old_value), crm_str(value)); } if(force_restart) { /* make sure the restart happens */ stop_action(rsc, node, FALSE); rsc->start_pending = TRUE; delete_resource = TRUE; } return delete_resource; } static gboolean check_action_definition(resource_t *rsc, node_t *active_node, crm_data_t *xml_op, pe_working_set_t *data_set) { char *key = NULL; int interval = 0; const char *interval_s = NULL; gboolean did_change = FALSE; gboolean start_op = FALSE; crm_data_t *params_all = NULL; crm_data_t *params_restart = NULL; GHashTable *local_rsc_params = NULL; char *digest_all_calc = NULL; const char *digest_all = NULL; const char *restart_list = NULL; const char *digest_restart = NULL; char *digest_restart_calc = NULL; action_t *action = NULL; const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK); const char *op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION); CRM_CHECK(active_node != NULL, return FALSE); interval_s = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL); interval = crm_parse_int(interval_s, "0"); /* we need to reconstruct the key because of the way we used to construct resource IDs */ key = generate_op_key(rsc->id, task, interval); if(interval > 0) { crm_data_t *op_match = NULL; crm_debug_2("Checking parameters for %s", key); op_match = find_rsc_op_entry(rsc, key); if(op_match == NULL && data_set->stop_action_orphans) { /* create a cancel action */ action_t *cancel = NULL; char *cancel_key = NULL; crm_info("Orphan action will be stopped: %s on %s", key, active_node->details->uname); cancel_key = generate_op_key( rsc->id, CRMD_ACTION_CANCEL, interval); cancel = custom_action( rsc, cancel_key, CRMD_ACTION_CANCEL, active_node, FALSE, TRUE, data_set); add_hash_param(cancel->meta, XML_LRM_ATTR_TASK, task); add_hash_param(cancel->meta, XML_LRM_ATTR_INTERVAL, interval_s); custom_action_order( rsc, NULL, cancel, rsc, stop_key(rsc), NULL, pe_order_implies_left, data_set); } if(op_match == NULL) { crm_debug("Orphan action detected: %s on %s", key, active_node->details->uname); crm_free(key); key = NULL; return TRUE; } } action = custom_action(rsc, key, task, active_node, TRUE, FALSE, data_set); local_rsc_params = g_hash_table_new_full( g_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); unpack_instance_attributes( rsc->xml, XML_TAG_ATTR_SETS, active_node->details->attrs, local_rsc_params, NULL, data_set->now); params_all = create_xml_node(NULL, XML_TAG_PARAMS); g_hash_table_foreach(action->extra, hash2field, params_all); g_hash_table_foreach(rsc->parameters, hash2field, params_all); g_hash_table_foreach(local_rsc_params, hash2field, params_all); filter_action_parameters(params_all, op_version); digest_all_calc = calculate_xml_digest(params_all, TRUE); digest_all = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST); digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST); restart_list = crm_element_value(xml_op, XML_LRM_ATTR_OP_RESTART); if(crm_str_eq(task, CRMD_ACTION_START, TRUE)) { start_op = TRUE; } if(start_op && digest_restart) { params_restart = copy_xml(params_all); if(restart_list) { filter_reload_parameters(params_restart, restart_list); } digest_restart_calc = calculate_xml_digest(params_restart, TRUE); if(safe_str_neq(digest_restart_calc, digest_restart)) { did_change = TRUE; crm_log_xml_info(params_restart, "params:restart"); crm_warn("Parameters to %s on %s changed: recorded %s vs. calculated (restart) %s", key, active_node->details->uname, crm_str(digest_restart), digest_restart_calc); key = generate_op_key(rsc->id, task, interval); custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set); goto cleanup; } } if(safe_str_neq(digest_all_calc, digest_all)) { action_t *op = NULL; did_change = TRUE; crm_log_xml_info(params_all, "params:all"); crm_warn("Parameters to %s on %s changed: recorded %s vs. calculated (all) %s", key, active_node->details->uname, crm_str(digest_all), digest_all_calc); key = generate_op_key(rsc->id, task, interval); op = custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set); if(start_op && digest_restart) { op->allow_reload_conversion = TRUE; } else if(interval > 0) { custom_action_order(rsc, start_key(rsc), NULL, NULL, crm_strdup(op->task), op, pe_order_runnable_left, data_set); } } cleanup: free_xml(params_all); free_xml(params_restart); crm_free(digest_all_calc); crm_free(digest_restart_calc); g_hash_table_destroy(local_rsc_params); pe_free_action(action); return did_change; } extern gboolean DeleteRsc(resource_t *rsc, node_t *node, pe_working_set_t *data_set); static void check_actions_for(crm_data_t *rsc_entry, node_t *node, pe_working_set_t *data_set) { const char *id = NULL; const char *task = NULL; int interval = 0; const char *interval_s = NULL; GListPtr op_list = NULL; GListPtr sorted_op_list = NULL; const char *rsc_id = ID(rsc_entry); gboolean is_probe = FALSE; + int start_index = 0, stop_index = 0; resource_t *rsc = pe_find_resource(data_set->resources, rsc_id); CRM_CHECK(rsc != NULL, return); CRM_CHECK(node != NULL, return); CRM_CHECK(rsc_id != NULL, return); if(rsc->orphan) { crm_debug_2("Skipping param check for %s: orphan", rsc->id); return; } else if(pe_find_node_id(rsc->running_on, node->details->id) == NULL) { crm_debug_2("Skipping param check for %s: no longer active on %s", rsc->id, node->details->uname); return; } crm_debug_3("Processing %s on %s", rsc->id, node->details->uname); if(check_rsc_parameters(rsc, node, rsc_entry, data_set)) { DeleteRsc(rsc, node, data_set); } xml_child_iter_filter( rsc_entry, rsc_op, XML_LRM_TAG_RSC_OP, op_list = g_list_append(op_list, rsc_op); ); sorted_op_list = g_list_sort(op_list, sort_op_by_callid); + calculate_active_ops(sorted_op_list, &start_index, &stop_index); + slist_iter( rsc_op, crm_data_t, sorted_op_list, lpc, + if(start_index < stop_index) { + /* stopped */ + continue; + } else if(lpc < start_index) { + /* action occurred prior to a start */ + continue; + } + id = ID(rsc_op); is_probe = FALSE; task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); interval_s = crm_element_value(rsc_op, XML_LRM_ATTR_INTERVAL); interval = crm_parse_int(interval_s, "0"); if(interval == 0 && safe_str_eq(task, CRMD_ACTION_STATUS)) { is_probe = TRUE; } if(is_probe || safe_str_eq(task, CRMD_ACTION_START) || interval > 0) { check_action_definition(rsc, node, rsc_op, data_set); } ); g_list_free(sorted_op_list); } static void check_actions(pe_working_set_t *data_set) { const char *id = NULL; node_t *node = NULL; crm_data_t *lrm_rscs = NULL; crm_data_t *status = get_object_root(XML_CIB_TAG_STATUS, data_set->input); xml_child_iter_filter( status, node_state, XML_CIB_TAG_STATE, id = crm_element_value(node_state, XML_ATTR_ID); lrm_rscs = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE); lrm_rscs = find_xml_node(lrm_rscs, XML_LRM_TAG_RESOURCES, FALSE); node = pe_find_node_id(data_set->nodes, id); if(node == NULL) { continue; } else if(can_run_resources(node) == FALSE) { crm_debug_2("Skipping param check for %s: cant run resources", node->details->uname); continue; } crm_debug_2("Processing node %s", node->details->uname); if(node->details->online || data_set->stonith_enabled) { xml_child_iter_filter( lrm_rscs, rsc_entry, XML_LRM_TAG_RESOURCE, check_actions_for(rsc_entry, node, data_set); ); } ); } static gboolean apply_placement_constraints(pe_working_set_t *data_set) { crm_debug_3("Applying constraints..."); slist_iter( cons, rsc_to_node_t, data_set->placement_constraints, lpc, cons->rsc_lh->cmds->rsc_location(cons->rsc_lh, cons); ); return TRUE; } void set_alloc_actions(pe_working_set_t *data_set) { slist_iter( rsc, resource_t, data_set->resources, lpc, rsc->cmds = &resource_class_alloc_functions[rsc->variant]; rsc->cmds->set_cmds(rsc); ); } gboolean stage0(pe_working_set_t *data_set) { crm_data_t * cib_constraints = get_object_root( XML_CIB_TAG_CONSTRAINTS, data_set->input); if(data_set->input == NULL) { return FALSE; } cluster_status(data_set); set_alloc_actions(data_set); unpack_constraints(cib_constraints, data_set); return TRUE; } /* * Check nodes for resources started outside of the LRM */ gboolean stage1(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, gboolean force_probe = FALSE; const char *probed = g_hash_table_lookup( node->details->attrs, CRM_OP_PROBED); crm_debug_2("%s probed: %s", node->details->uname, probed); if(node->details->online == FALSE) { continue; } else if(node->details->unclean) { continue; } else if(probe_complete == NULL) { probe_complete = custom_action( NULL, crm_strdup(CRM_OP_PROBED), CRM_OP_PROBED, NULL, FALSE, TRUE, data_set); probe_complete->pseudo = TRUE; probe_complete->optional = TRUE; } if(probed != NULL && crm_is_true(probed) == FALSE) { force_probe = TRUE; } probe_node_complete = custom_action( NULL, crm_strdup(CRM_OP_PROBED), CRM_OP_PROBED, node, FALSE, TRUE, data_set); probe_node_complete->optional = crm_is_true(probed); probe_node_complete->priority = INFINITY; add_hash_param(probe_node_complete->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); custom_action_order(NULL, NULL, probe_node_complete, NULL, NULL, probe_complete, pe_order_optional, data_set); slist_iter( rsc, resource_t, data_set->resources, lpc2, if(rsc->cmds->create_probe( rsc, node, probe_node_complete, force_probe, data_set)) { probe_complete->optional = FALSE; probe_node_complete->optional = FALSE; custom_action_order( NULL, NULL, probe_complete, rsc, start_key(rsc), NULL, pe_order_optional, 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 stage2(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; } /* * Create internal resource constraints before allocation */ gboolean stage3(pe_working_set_t *data_set) { slist_iter( rsc, resource_t, data_set->resources, lpc, rsc->cmds->internal_constraints(rsc, data_set); ); return TRUE; } /* * Check for orphaned or redefined actions */ gboolean stage4(pe_working_set_t *data_set) { check_actions(data_set); return TRUE; } gboolean stage5(pe_working_set_t *data_set) { /* Take (next) highest resource, assign it and create its actions */ slist_iter( rsc, resource_t, data_set->resources, lpc, rsc->cmds->color(rsc, data_set); rsc->cmds->create_actions(rsc, data_set); ); return TRUE; } /* * Create dependancies for stonith and shutdown operations */ gboolean stage6(pe_working_set_t *data_set) { action_t *dc_down = NULL; action_t *stonith_op = NULL; action_t *last_stonith = NULL; gboolean integrity_lost = FALSE; crm_debug_3("Processing fencing and shutdown cases"); slist_iter( node, node_t, data_set->nodes, lpc, stonith_op = NULL; 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); add_hash_param( stonith_op->meta, XML_LRM_ATTR_TARGET, node->details->uname); add_hash_param( stonith_op->meta, XML_LRM_ATTR_TARGET_UUID, node->details->id); add_hash_param( stonith_op->meta, "stonith_action", data_set->stonith_action); stonith_constraints(node, stonith_op, data_set); if(node->details->is_dc) { dc_down = stonith_op; } else { if(last_stonith) { order_actions(last_stonith, stonith_op, pe_order_implies_left); } last_stonith = stonith_op; } } else if(node->details->online && node->details->shutdown) { action_t *down_op = NULL; 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); shutdown_constraints(node, down_op, data_set); if(node->details->is_dc) { dc_down = down_op; } } if(node->details->unclean && stonith_op == NULL) { integrity_lost = TRUE; pe_warn("Node %s is unclean!", node->details->uname); } ); if(integrity_lost) { if(data_set->have_quorum == FALSE) { crm_notice("Cannot fence unclean nodes until quorum is" " attained (or no_quorum_policy is set to ignore)"); } else if(data_set->stonith_enabled == FALSE) { pe_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED"); pe_err("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE"); } } if(dc_down != NULL) { GListPtr shutdown_matches = find_actions( data_set->actions, CRM_OP_SHUTDOWN, NULL); crm_debug_2("Ordering shutdowns before %s on %s (DC)", dc_down->task, dc_down->node->details->uname); add_hash_param(dc_down->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); slist_iter( node_stop, action_t, shutdown_matches, lpc, if(node_stop->node->details->is_dc) { continue; } crm_debug("Ordering shutdown on %s before %s on %s", node_stop->node->details->uname, dc_down->task, dc_down->node->details->uname); order_actions(node_stop, dc_down, pe_order_implies_left); ); if(last_stonith && dc_down != last_stonith) { order_actions(last_stonith, dc_down, pe_order_implies_left); } g_list_free(shutdown_matches); } 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_4("Applying ordering constraints"); slist_iter( order, order_constraint_t, data_set->ordering_constraints, lpc, resource_t *rsc = order->lh_rsc; crm_debug_2("Applying ordering constraint: %d", order->id); if(rsc != NULL) { crm_debug_4("rsc_action-to-*"); rsc->cmds->rsc_order_lh(rsc, order, data_set); continue; } rsc = order->rh_rsc; if(rsc != NULL) { crm_debug_4("action-to-rsc_action"); rsc->cmds->rsc_order_rh(order->lh_action, rsc, order); } else { crm_debug_4("action-to-action"); order_actions( order->lh_action, order->rh_action, order->type); } ); update_action_states(data_set->actions); slist_iter( rsc, resource_t, data_set->resources, lpc, rsc->cmds->migrate_reload(rsc, data_set); ); return TRUE; } int transition_id = -1; /* * Create a dependency graph to send to the transitioner (via the CRMd) */ gboolean stage8(pe_working_set_t *data_set) { const char *value = NULL; char *transition_id_s = NULL; transition_id++; transition_id_s = crm_itoa(transition_id); value = pe_pref(data_set->config_hash, "cluster-delay"); crm_debug_2("Creating transition graph %d.", transition_id); data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH); crm_xml_add(data_set->graph, "cluster-delay", value); 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->cmds->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"); crm_debug_2("Created transition graph %d.", transition_id); return TRUE; } void cleanup_alloc_calculations(pe_working_set_t *data_set) { if(data_set == NULL) { return; } crm_debug_3("deleting order cons: %p", data_set->ordering_constraints); pe_free_ordering(data_set->ordering_constraints); data_set->ordering_constraints = NULL; crm_debug_3("deleting node cons: %p", data_set->placement_constraints); pe_free_rsc_to_node(data_set->placement_constraints); data_set->placement_constraints = NULL; cleanup_calculations(data_set); } gboolean unpack_constraints(crm_data_t * xml_constraints, pe_working_set_t *data_set) { crm_data_t *lifetime = NULL; xml_child_iter( xml_constraints, xml_obj, const char *id = crm_element_value(xml_obj, XML_ATTR_ID); if(id == NULL) { crm_config_err("Constraint <%s...> must have an id", crm_element_name(xml_obj)); continue; } crm_debug_3("Processing constraint %s %s", crm_element_name(xml_obj),id); lifetime = cl_get_struct(xml_obj, "lifetime"); if(test_ruleset(lifetime, NULL, data_set->now) == FALSE) { crm_info("Constraint %s %s is not active", crm_element_name(xml_obj), id); } else if(safe_str_eq(XML_CONS_TAG_RSC_ORDER, crm_element_name(xml_obj))) { unpack_rsc_order(xml_obj, data_set); } else if(safe_str_eq(XML_CONS_TAG_RSC_DEPEND, crm_element_name(xml_obj))) { unpack_rsc_colocation(xml_obj, data_set); } else if(safe_str_eq(XML_CONS_TAG_RSC_LOCATION, crm_element_name(xml_obj))) { unpack_rsc_location(xml_obj, data_set); } else { pe_err("Unsupported constraint type: %s", crm_element_name(xml_obj)); } ); return TRUE; } static const char * invert_action(const char *action) { if(safe_str_eq(action, CRMD_ACTION_START)) { return CRMD_ACTION_STOP; } else if(safe_str_eq(action, CRMD_ACTION_STOP)) { return CRMD_ACTION_START; } else if(safe_str_eq(action, CRMD_ACTION_PROMOTE)) { return CRMD_ACTION_DEMOTE; } else if(safe_str_eq(action, CRMD_ACTION_DEMOTE)) { return CRMD_ACTION_PROMOTE; } else if(safe_str_eq(action, CRMD_ACTION_PROMOTED)) { return CRMD_ACTION_DEMOTED; } else if(safe_str_eq(action, CRMD_ACTION_DEMOTED)) { return CRMD_ACTION_PROMOTED; } else if(safe_str_eq(action, CRMD_ACTION_STARTED)) { return CRMD_ACTION_STOPPED; } else if(safe_str_eq(action, CRMD_ACTION_STOPPED)) { return CRMD_ACTION_STARTED; } crm_config_warn("Unknown action: %s", action); return NULL; } gboolean unpack_rsc_order(crm_data_t * xml_obj, pe_working_set_t *data_set) { int score_i = 0; int order_id = 0; resource_t *rsc_lh = NULL; resource_t *rsc_rh = NULL; gboolean symmetrical_bool = TRUE; enum pe_ordering cons_weight = pe_order_optional; const char *id_rh = NULL; const char *id_lh = NULL; const char *action = NULL; const char *action_rh = NULL; const char *id = crm_element_value(xml_obj, XML_ATTR_ID); const char *type = crm_element_value(xml_obj, XML_ATTR_TYPE); const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); const char *symmetrical = crm_element_value( xml_obj, XML_CONS_ATTR_SYMMETRICAL); cl_str_to_boolean(symmetrical, &symmetrical_bool); if(xml_obj == NULL) { crm_config_err("No constraint object to process."); return FALSE; } else if(id == NULL) { crm_config_err("%s constraint must have an id", crm_element_name(xml_obj)); return FALSE; } if(safe_str_eq(type, "before")) { id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_TO); id_rh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM); action = crm_element_value(xml_obj, XML_CONS_ATTR_ACTION); action_rh = crm_element_value(xml_obj, XML_CONS_ATTR_TOACTION); } else { type="before"; id_rh = crm_element_value(xml_obj, XML_CONS_ATTR_TO); id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM); action = crm_element_value(xml_obj, XML_CONS_ATTR_TOACTION); action_rh = crm_element_value(xml_obj, XML_CONS_ATTR_ACTION); if(action == NULL) { action = action_rh; } } if(id_lh == NULL || id_rh == NULL) { crm_config_err("Constraint %s needs two sides lh: %s rh: %s", id, crm_str(id_lh), crm_str(id_rh)); return FALSE; } if(action == NULL) { action = CRMD_ACTION_START; } if(action_rh == NULL) { action_rh = action; } rsc_lh = pe_find_resource(data_set->resources, id_rh); rsc_rh = pe_find_resource(data_set->resources, id_lh); if(rsc_lh == NULL) { crm_config_err("Constraint %s: no resource found for LHS (%s)", id, id_rh); return FALSE; } else if(rsc_rh == NULL) { crm_config_err("Constraint %s: no resource found for RHS of (%s)", id, id_lh); return FALSE; } score_i = char2score(score); cons_weight = pe_order_optional; if(score == 0 && rsc_rh->restart_type == pe_restart_restart) { crm_debug_2("Upgrade : recovery - implies right"); cons_weight |= pe_order_implies_right; } if(score_i < 0) { crm_debug_2("Upgrade : implies left"); cons_weight |= pe_order_implies_left; } else if(score_i > 0) { crm_debug_2("Upgrade : implies right"); cons_weight |= pe_order_implies_right; if(safe_str_eq(action, CRMD_ACTION_START) || safe_str_eq(action, CRMD_ACTION_PROMOTE)) { crm_debug_2("Upgrade : runnable"); cons_weight |= pe_order_runnable_left; } } order_id = custom_action_order( rsc_lh, generate_op_key(rsc_lh->id, action, 0), NULL, rsc_rh, generate_op_key(rsc_rh->id, action_rh, 0), NULL, cons_weight, data_set); crm_debug("order-%d (%s): %s_%s %s %s_%s flags=0x%.6x", order_id, id, rsc_lh->id, action, type, rsc_rh->id, action_rh, cons_weight); if(symmetrical_bool == FALSE) { return TRUE; } action = invert_action(action); action_rh = invert_action(action_rh); cons_weight = pe_order_optional; if(score == 0 && rsc_rh->restart_type == pe_restart_restart) { crm_debug_2("Upgrade : recovery - implies left"); cons_weight |= pe_order_implies_left; } score_i *= -1; if(score_i < 0) { crm_debug_2("Upgrade : implies left"); cons_weight |= pe_order_implies_left; } else if(score_i > 0) { crm_debug_2("Upgrade : implies right"); cons_weight |= pe_order_implies_right; if(safe_str_eq(action, CRMD_ACTION_START) || safe_str_eq(action, CRMD_ACTION_PROMOTE)) { crm_debug_2("Upgrade : runnable"); cons_weight |= pe_order_runnable_left; } } if(action == NULL || action_rh == NULL) { crm_config_err("Cannot invert rsc_order constraint %s." " Please specify the inverse manually.", id); return TRUE; } order_id = custom_action_order( rsc_rh, generate_op_key(rsc_rh->id, action_rh, 0), NULL, rsc_lh, generate_op_key(rsc_lh->id, action, 0), NULL, cons_weight, data_set); crm_debug("order-%d (%s): %s_%s %s %s_%s flags=0x%.6x", order_id, id, rsc_rh->id, action_rh, type, rsc_lh->id, action, cons_weight); return TRUE; } gboolean unpack_rsc_location(crm_data_t * xml_obj, pe_working_set_t *data_set) { gboolean empty = TRUE; const char *id_lh = crm_element_value(xml_obj, "rsc"); const char *id = crm_element_value(xml_obj, XML_ATTR_ID); resource_t *rsc_lh = pe_find_resource(data_set->resources, id_lh); if(rsc_lh == NULL) { /* only a warn as BSC adds the constraint then the resource */ crm_config_warn("No resource (con=%s, rsc=%s)", id, id_lh); return FALSE; } else if(rsc_lh->is_managed == FALSE) { crm_debug_2("Ignoring constraint %s: resource %s not managed", id, id_lh); return FALSE; } xml_child_iter_filter( xml_obj, rule_xml, XML_TAG_RULE, empty = FALSE; crm_debug_2("Unpacking %s/%s", id, ID(rule_xml)); generate_location_rule(rsc_lh, rule_xml, data_set); ); if(empty) { crm_config_err("Invalid location constraint %s:" " rsc_location must contain at least one rule", ID(xml_obj)); } return TRUE; } static int get_node_score(const char *rule, const char *score, gboolean raw, node_t *node) { int score_f = 0; if(score == NULL) { pe_err("Rule %s: no score specified. Assuming 0.", rule); } else if(raw) { score_f = char2score(score); } else { const char *attr_score = g_hash_table_lookup( node->details->attrs, score); if(attr_score == NULL) { crm_debug("Rule %s: node %s did not have a value for %s", rule, node->details->uname, score); score_f = -INFINITY; } else { crm_debug("Rule %s: node %s had value %s for %s", rule, node->details->uname, attr_score, score); score_f = char2score(attr_score); } } return score_f; } rsc_to_node_t * generate_location_rule( resource_t *rsc, crm_data_t *rule_xml, pe_working_set_t *data_set) { const char *rule_id = NULL; const char *score = NULL; const char *boolean = NULL; const char *role = NULL; GListPtr match_L = NULL; int score_f = 0; gboolean do_and = TRUE; gboolean accept = TRUE; gboolean raw_score = TRUE; rsc_to_node_t *location_rule = NULL; rule_id = crm_element_value(rule_xml, XML_ATTR_ID); boolean = crm_element_value(rule_xml, XML_RULE_ATTR_BOOLEAN_OP); role = crm_element_value(rule_xml, XML_RULE_ATTR_ROLE); crm_debug_2("Processing rule: %s", rule_id); if(role != NULL && text2role(role) == RSC_ROLE_UNKNOWN) { pe_err("Bad role specified for %s: %s", rule_id, role); return NULL; } score = crm_element_value(rule_xml, XML_RULE_ATTR_SCORE); if(score != NULL) { score_f = char2score(score); } else { score = crm_element_value( rule_xml, XML_RULE_ATTR_SCORE_ATTRIBUTE); if(score == NULL) { score = crm_element_value( rule_xml, XML_RULE_ATTR_SCORE_MANGLED); } if(score != NULL) { raw_score = FALSE; } } if(safe_str_eq(boolean, "or")) { do_and = FALSE; } location_rule = rsc2node_new(rule_id, rsc, 0, NULL, data_set); if(location_rule == NULL) { return NULL; } if(role != NULL) { crm_debug_2("Setting role filter: %s", role); location_rule->role_filter = text2role(role); } if(do_and) { match_L = node_list_dup(data_set->nodes, TRUE, FALSE); slist_iter( node, node_t, match_L, lpc, node->weight = get_node_score(rule_id, score, raw_score, node); ); } xml_child_iter( rule_xml, expr, enum expression_type type = find_expression_type(expr); crm_debug_2("Processing expression: %s", ID(expr)); if(type == not_expr) { pe_err("Expression <%s id=%s...> is not valid", crm_element_name(expr), crm_str(ID(expr))); continue; } slist_iter( node, node_t, data_set->nodes, lpc, if(type == nested_rule) { accept = test_rule( expr, node->details->attrs, RSC_ROLE_UNKNOWN, data_set->now); } else { accept = test_expression( expr, node->details->attrs, RSC_ROLE_UNKNOWN, data_set->now); } score_f = get_node_score(rule_id, score, raw_score, node); /* if(accept && score_f == -INFINITY) { */ /* accept = FALSE; */ /* } */ if(accept) { node_t *local = pe_find_node_id( match_L, node->details->id); if(local == NULL && do_and) { continue; } else if(local == NULL) { local = node_copy(node); match_L = g_list_append(match_L, local); } if(do_and == FALSE) { local->weight = merge_weights( local->weight, score_f); } crm_debug_2("node %s now has weight %d", node->details->uname, local->weight); } else if(do_and && !accept) { /* remove it */ node_t *delete = pe_find_node_id( match_L, node->details->id); if(delete != NULL) { match_L = g_list_remove(match_L,delete); crm_debug_5("node %s did not match", node->details->uname); } crm_free(delete); } ); ); location_rule->node_list_rh = match_L; if(location_rule->node_list_rh == NULL) { crm_debug_2("No matching nodes for rule %s", rule_id); return NULL; } crm_debug_3("%s: %d nodes matched", rule_id, g_list_length(location_rule->node_list_rh)); return location_rule; } gboolean rsc_colocation_new(const char *id, const char *node_attr, int score, resource_t *rsc_lh, resource_t *rsc_rh, const char *state_lh, const char *state_rh) { rsc_colocation_t *new_con = NULL; if(rsc_lh == NULL){ crm_config_err("No resource found for LHS %s", id); return FALSE; } else if(rsc_rh == NULL){ crm_config_err("No resource found for RHS of %s", id); return FALSE; } crm_malloc0(new_con, sizeof(rsc_colocation_t)); if(new_con == NULL) { return FALSE; } if(state_lh == NULL || safe_str_eq(state_lh, RSC_ROLE_STARTED_S)) { state_lh = RSC_ROLE_UNKNOWN_S; } if(state_rh == NULL || safe_str_eq(state_rh, RSC_ROLE_STARTED_S)) { state_rh = RSC_ROLE_UNKNOWN_S; } new_con->id = id; new_con->rsc_lh = rsc_lh; new_con->rsc_rh = rsc_rh; new_con->score = score; new_con->role_lh = text2role(state_lh); new_con->role_rh = text2role(state_rh); new_con->node_attribute = node_attr; crm_debug_4("Adding constraint %s (%p) to %s", new_con->id, new_con, rsc_lh->id); rsc_lh->rsc_cons = g_list_insert_sorted( rsc_lh->rsc_cons, new_con, sort_cons_strength); return TRUE; } /* LHS before RHS */ int custom_action_order( resource_t *lh_rsc, char *lh_action_task, action_t *lh_action, resource_t *rh_rsc, char *rh_action_task, action_t *rh_action, enum pe_ordering type, pe_working_set_t *data_set) { order_constraint_t *order = NULL; if(lh_rsc == NULL && lh_action) { lh_rsc = lh_action->rsc; } if(rh_rsc == NULL && rh_action) { rh_rsc = rh_action->rsc; } if((lh_action == NULL && lh_rsc == NULL) || (rh_action == NULL && rh_rsc == NULL)){ crm_config_err("Invalid inputs %p.%p %p.%p", lh_rsc, lh_action, rh_rsc, rh_action); crm_free(lh_action_task); crm_free(rh_action_task); return -1; } crm_malloc0(order, sizeof(order_constraint_t)); crm_debug_3("Creating ordering constraint %d", data_set->order_id); order->id = data_set->order_id++; order->type = type; order->lh_rsc = lh_rsc; order->rh_rsc = rh_rsc; order->lh_action = lh_action; order->rh_action = rh_action; order->lh_action_task = lh_action_task; order->rh_action_task = rh_action_task; data_set->ordering_constraints = g_list_append( data_set->ordering_constraints, order); if(lh_rsc != NULL && rh_rsc != NULL) { crm_debug_4("Created ordering constraint %d (%s):" " %s/%s before %s/%s", order->id, ordering_type2text(order->type), lh_rsc->id, lh_action_task, rh_rsc->id, rh_action_task); } else if(lh_rsc != NULL) { crm_debug_4("Created ordering constraint %d (%s):" " %s/%s before action %d (%s)", order->id, ordering_type2text(order->type), lh_rsc->id, lh_action_task, rh_action->id, rh_action_task); } else if(rh_rsc != NULL) { crm_debug_4("Created ordering constraint %d (%s):" " action %d (%s) before %s/%s", order->id, ordering_type2text(order->type), lh_action->id, lh_action_task, rh_rsc->id, rh_action_task); } else { crm_debug_4("Created ordering constraint %d (%s):" " action %d (%s) before action %d (%s)", order->id, ordering_type2text(order->type), lh_action->id, lh_action_task, rh_action->id, rh_action_task); } return order->id; } gboolean unpack_rsc_colocation(crm_data_t * xml_obj, pe_working_set_t *data_set) { int score_i = 0; const char *id = crm_element_value(xml_obj, XML_ATTR_ID); const char *id_rh = crm_element_value(xml_obj, XML_CONS_ATTR_TO); const char *id_lh = crm_element_value(xml_obj, XML_CONS_ATTR_FROM); const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); const char *state_lh = crm_element_value(xml_obj, XML_RULE_ATTR_FROMSTATE); const char *state_rh = crm_element_value(xml_obj, XML_RULE_ATTR_TOSTATE); const char *attr = crm_element_value(xml_obj, "node_attribute"); const char *symmetrical = crm_element_value(xml_obj, XML_CONS_ATTR_SYMMETRICAL); resource_t *rsc_lh = pe_find_resource(data_set->resources, id_lh); resource_t *rsc_rh = pe_find_resource(data_set->resources, id_rh); if(rsc_lh == NULL) { crm_config_err("No resource (con=%s, rsc=%s)", id, id_lh); return FALSE; } else if(rsc_rh == NULL) { crm_config_err("No resource (con=%s, rsc=%s)", id, id_rh); return FALSE; } if(score) { score_i = char2score(score); } rsc_colocation_new( id, attr, score_i, rsc_lh, rsc_rh, state_lh, state_rh); if(crm_is_true(symmetrical)) { rsc_colocation_new( id, attr, score_i, rsc_rh, rsc_lh, state_rh, state_lh); } return TRUE; } gboolean is_active(rsc_to_node_t *cons) { return TRUE; } diff --git a/crm/pengine/testcases/bug-1572-1.dot b/crm/pengine/testcases/bug-1572-1.dot index 52f4ffe4f3..9ff789a429 100644 --- a/crm/pengine/testcases/bug-1572-1.dot +++ b/crm/pengine/testcases/bug-1572-1.dot @@ -1,142 +1,141 @@ digraph "g" { "IPaddr_147_81_84_133_monitor_25000 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "IPaddr_147_81_84_133_start_0 arc-tkincaidlx.wsicorp.com" -> "IPaddr_147_81_84_133_monitor_25000 arc-tkincaidlx.wsicorp.com" [ style = bold] "IPaddr_147_81_84_133_start_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "IPaddr_147_81_84_133_stop_0 arc-tkincaidlx.wsicorp.com" -> "IPaddr_147_81_84_133_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "IPaddr_147_81_84_133_stop_0 arc-tkincaidlx.wsicorp.com" -> "grp_pgsql_mirror_stopped_0" [ style = bold] "IPaddr_147_81_84_133_stop_0 arc-tkincaidlx.wsicorp.com" -> "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "IPaddr_147_81_84_133_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "do_shutdown arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "fs_mirror_start_0 arc-tkincaidlx.wsicorp.com" -> "pgsql_5555_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "fs_mirror_start_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" -> "fs_mirror_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" -> "grp_pgsql_mirror_stopped_0" [ style = bold] "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_demote_0" [ style = bold] "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "grp_pgsql_mirror_start_0" -> "fs_mirror_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "grp_pgsql_mirror_start_0" [ style=bold color="green" fontcolor="orange" ] "grp_pgsql_mirror_stop_0" -> "IPaddr_147_81_84_133_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "grp_pgsql_mirror_stop_0" -> "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "grp_pgsql_mirror_stop_0" -> "grp_pgsql_mirror_start_0" [ style = bold] "grp_pgsql_mirror_stop_0" -> "grp_pgsql_mirror_stopped_0" [ style = bold] "grp_pgsql_mirror_stop_0" -> "ms_drbd_7788_demote_0" [ style = bold] "grp_pgsql_mirror_stop_0" -> "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "grp_pgsql_mirror_stop_0" [ style=bold color="green" fontcolor="orange" ] "grp_pgsql_mirror_stopped_0" -> "grp_pgsql_mirror_start_0" [ style = bold] "grp_pgsql_mirror_stopped_0" -> "ms_drbd_7788_demote_0" [ style = bold] "grp_pgsql_mirror_stopped_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-post_notify_demote_0" -> "ms_drbd_7788_pre_notify_stop_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_demote_0" -> "ms_drbd_7788_stop_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-post_notify_promote_0" -> "grp_pgsql_mirror_start_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_promote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-post_notify_start_0" -> "ms_drbd_7788_pre_notify_promote_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_start_0" -> "ms_drbd_7788_promote_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-post_notify_stop_0" -> "ms_drbd_7788_pre_notify_start_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_stop_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-pre_notify_demote_0" -> "ms_drbd_7788_demote_0" [ style = bold] "ms_drbd_7788_confirmed-pre_notify_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-pre_notify_promote_0" -> "ms_drbd_7788_promote_0" [ style = bold] "ms_drbd_7788_confirmed-pre_notify_promote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-pre_notify_start_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_confirmed-pre_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-pre_notify_stop_0" -> "ms_drbd_7788_stop_0" [ style = bold] "ms_drbd_7788_confirmed-pre_notify_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_demote_0" -> "ms_drbd_7788_demoted_0" [ style = bold] "ms_drbd_7788_demote_0" -> "ms_drbd_7788_stop_0" [ style = bold] "ms_drbd_7788_demote_0" -> "rsc_drbd_7788:1_demote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_demoted_0" -> "ms_drbd_7788_post_notify_demote_0" [ style = bold] "ms_drbd_7788_demoted_0" -> "ms_drbd_7788_promote_0" [ style = bold] "ms_drbd_7788_demoted_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_demoted_0" -> "ms_drbd_7788_stop_0" [ style = bold] "ms_drbd_7788_demoted_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_post_notify_demote_0" -> "ms_drbd_7788_confirmed-post_notify_demote_0" [ style = bold] "ms_drbd_7788_post_notify_demote_0" -> "rsc_drbd_7788:0_post_notify_demote_0 arc-dknightlx" [ style = bold] "ms_drbd_7788_post_notify_demote_0" -> "rsc_drbd_7788:1_post_notify_demote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_post_notify_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_post_notify_promote_0" -> "ms_drbd_7788_confirmed-post_notify_promote_0" [ style = bold] "ms_drbd_7788_post_notify_promote_0" -> "rsc_drbd_7788:1_post_notify_promote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_post_notify_promote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_post_notify_start_0" -> "ms_drbd_7788_confirmed-post_notify_start_0" [ style = bold] "ms_drbd_7788_post_notify_start_0" -> "rsc_drbd_7788:1_post_notify_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_post_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_post_notify_stop_0" -> "ms_drbd_7788_confirmed-post_notify_stop_0" [ style = bold] "ms_drbd_7788_post_notify_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_pre_notify_demote_0" -> "ms_drbd_7788_confirmed-pre_notify_demote_0" [ style = bold] "ms_drbd_7788_pre_notify_demote_0" -> "rsc_drbd_7788:0_pre_notify_demote_0 arc-dknightlx" [ style = bold] "ms_drbd_7788_pre_notify_demote_0" -> "rsc_drbd_7788:1_pre_notify_demote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_pre_notify_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_pre_notify_promote_0" -> "ms_drbd_7788_confirmed-pre_notify_promote_0" [ style = bold] "ms_drbd_7788_pre_notify_promote_0" -> "rsc_drbd_7788:1_pre_notify_promote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_pre_notify_promote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_pre_notify_start_0" -> "ms_drbd_7788_confirmed-pre_notify_start_0" [ style = bold] "ms_drbd_7788_pre_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_pre_notify_stop_0" -> "ms_drbd_7788_confirmed-pre_notify_stop_0" [ style = bold] "ms_drbd_7788_pre_notify_stop_0" -> "rsc_drbd_7788:0_pre_notify_stop_0 arc-dknightlx" [ style = bold] "ms_drbd_7788_pre_notify_stop_0" -> "rsc_drbd_7788:1_pre_notify_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_pre_notify_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_promote_0" -> "rsc_drbd_7788:1_promote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_promote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_promoted_0" -> "ms_drbd_7788_post_notify_promote_0" [ style = bold] "ms_drbd_7788_promoted_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_running_0" -> "ms_drbd_7788_post_notify_start_0" [ style = bold] "ms_drbd_7788_running_0" -> "ms_drbd_7788_promote_0" [ style = bold] "ms_drbd_7788_running_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_start_0" -> "ms_drbd_7788_promote_0" [ style = bold] "ms_drbd_7788_start_0" -> "ms_drbd_7788_running_0" [ style = bold] "ms_drbd_7788_start_0" -> "rsc_drbd_7788:1_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_stop_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_stop_0" -> "ms_drbd_7788_stopped_0" [ style = bold] "ms_drbd_7788_stop_0" -> "rsc_drbd_7788:0_stop_0 arc-dknightlx" [ style = bold] "ms_drbd_7788_stop_0" -> "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_stopped_0" -> "ms_drbd_7788_post_notify_stop_0" [ style = bold] "ms_drbd_7788_stopped_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_stopped_0" [ style=bold color="green" fontcolor="orange" ] "pgsql_5555_monitor_30000 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "pgsql_5555_start_0 arc-tkincaidlx.wsicorp.com" -> "IPaddr_147_81_84_133_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "pgsql_5555_start_0 arc-tkincaidlx.wsicorp.com" -> "pgsql_5555_monitor_30000 arc-tkincaidlx.wsicorp.com" [ style = bold] "pgsql_5555_start_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" -> "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" -> "grp_pgsql_mirror_stopped_0" [ style = bold] "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" -> "pgsql_5555_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:0_post_notify_demote_0 arc-dknightlx" -> "ms_drbd_7788_confirmed-post_notify_demote_0" [ style = bold] "rsc_drbd_7788:0_post_notify_demote_0 arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:0_pre_notify_demote_0 arc-dknightlx" -> "ms_drbd_7788_confirmed-pre_notify_demote_0" [ style = bold] "rsc_drbd_7788:0_pre_notify_demote_0 arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:0_pre_notify_stop_0 arc-dknightlx" -> "ms_drbd_7788_confirmed-pre_notify_stop_0" [ style = bold] "rsc_drbd_7788:0_pre_notify_stop_0 arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:0_stop_0 arc-dknightlx" -> "do_shutdown arc-dknightlx" [ style = bold] "rsc_drbd_7788:0_stop_0 arc-dknightlx" -> "ms_drbd_7788_stopped_0" [ style = bold] "rsc_drbd_7788:0_stop_0 arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_demote_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_demoted_0" [ style = bold] "rsc_drbd_7788:1_demote_0 arc-tkincaidlx.wsicorp.com" -> "rsc_drbd_7788:1_promote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "rsc_drbd_7788:1_demote_0 arc-tkincaidlx.wsicorp.com" -> "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "rsc_drbd_7788:1_demote_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] -"rsc_drbd_7788:1_monitor_0 " [ style=filled color="black" fontcolor="black" fillcolor=red] "rsc_drbd_7788:1_post_notify_demote_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-post_notify_demote_0" [ style = bold] "rsc_drbd_7788:1_post_notify_demote_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_post_notify_promote_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-post_notify_promote_0" [ style = bold] "rsc_drbd_7788:1_post_notify_promote_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_post_notify_start_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-post_notify_start_0" [ style = bold] "rsc_drbd_7788:1_post_notify_start_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_pre_notify_demote_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-pre_notify_demote_0" [ style = bold] "rsc_drbd_7788:1_pre_notify_demote_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_pre_notify_promote_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-pre_notify_promote_0" [ style = bold] "rsc_drbd_7788:1_pre_notify_promote_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_pre_notify_stop_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-pre_notify_stop_0" [ style = bold] "rsc_drbd_7788:1_pre_notify_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_promote_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_promoted_0" [ style = bold] "rsc_drbd_7788:1_promote_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_start_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_running_0" [ style = bold] "rsc_drbd_7788:1_start_0 arc-tkincaidlx.wsicorp.com" -> "rsc_drbd_7788:1_promote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "rsc_drbd_7788:1_start_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_stopped_0" [ style = bold] "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" -> "rsc_drbd_7788:1_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] } diff --git a/crm/pengine/testcases/bug-1572-1.exp b/crm/pengine/testcases/bug-1572-1.exp index fe1d93c240..ec116ce7f6 100644 --- a/crm/pengine/testcases/bug-1572-1.exp +++ b/crm/pengine/testcases/bug-1572-1.exp @@ -1,740 +1,740 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/crm/pengine/testcases/bug-1572-2.dot b/crm/pengine/testcases/bug-1572-2.dot index dfeb64b006..330be152ee 100644 --- a/crm/pengine/testcases/bug-1572-2.dot +++ b/crm/pengine/testcases/bug-1572-2.dot @@ -1,99 +1,98 @@ digraph "g" { "IPaddr_147_81_84_133_stop_0 arc-tkincaidlx.wsicorp.com" -> "grp_pgsql_mirror_stopped_0" [ style = bold] "IPaddr_147_81_84_133_stop_0 arc-tkincaidlx.wsicorp.com" -> "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "IPaddr_147_81_84_133_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "do_shutdown arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" -> "grp_pgsql_mirror_stopped_0" [ style = bold] "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_demote_0" [ style = bold] "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "grp_pgsql_mirror_stop_0" -> "IPaddr_147_81_84_133_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "grp_pgsql_mirror_stop_0" -> "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "grp_pgsql_mirror_stop_0" -> "grp_pgsql_mirror_stopped_0" [ style = bold] "grp_pgsql_mirror_stop_0" -> "ms_drbd_7788_demote_0" [ style = bold] "grp_pgsql_mirror_stop_0" -> "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "grp_pgsql_mirror_stop_0" [ style=bold color="green" fontcolor="orange" ] "grp_pgsql_mirror_stopped_0" -> "ms_drbd_7788_demote_0" [ style = bold] "grp_pgsql_mirror_stopped_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-post_notify_demote_0" -> "ms_drbd_7788_pre_notify_stop_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_demote_0" -> "ms_drbd_7788_stop_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-post_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-post_notify_stop_0" -> "ms_drbd_7788_pre_notify_start_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_stop_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_confirmed-post_notify_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-pre_notify_demote_0" -> "ms_drbd_7788_demote_0" [ style = bold] "ms_drbd_7788_confirmed-pre_notify_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-pre_notify_start_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_confirmed-pre_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_confirmed-pre_notify_stop_0" -> "ms_drbd_7788_stop_0" [ style = bold] "ms_drbd_7788_confirmed-pre_notify_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_demote_0" -> "ms_drbd_7788_demoted_0" [ style = bold] "ms_drbd_7788_demote_0" -> "ms_drbd_7788_stop_0" [ style = bold] "ms_drbd_7788_demote_0" -> "rsc_drbd_7788:1_demote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_demoted_0" -> "ms_drbd_7788_post_notify_demote_0" [ style = bold] "ms_drbd_7788_demoted_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_demoted_0" -> "ms_drbd_7788_stop_0" [ style = bold] "ms_drbd_7788_demoted_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_post_notify_demote_0" -> "ms_drbd_7788_confirmed-post_notify_demote_0" [ style = bold] "ms_drbd_7788_post_notify_demote_0" -> "rsc_drbd_7788:0_post_notify_demote_0 arc-dknightlx" [ style = bold] "ms_drbd_7788_post_notify_demote_0" -> "rsc_drbd_7788:1_post_notify_demote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_post_notify_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_post_notify_start_0" -> "ms_drbd_7788_confirmed-post_notify_start_0" [ style = bold] "ms_drbd_7788_post_notify_start_0" -> "rsc_drbd_7788:1_post_notify_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_post_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_post_notify_stop_0" -> "ms_drbd_7788_confirmed-post_notify_stop_0" [ style = bold] "ms_drbd_7788_post_notify_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_pre_notify_demote_0" -> "ms_drbd_7788_confirmed-pre_notify_demote_0" [ style = bold] "ms_drbd_7788_pre_notify_demote_0" -> "rsc_drbd_7788:0_pre_notify_demote_0 arc-dknightlx" [ style = bold] "ms_drbd_7788_pre_notify_demote_0" -> "rsc_drbd_7788:1_pre_notify_demote_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_pre_notify_demote_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_pre_notify_start_0" -> "ms_drbd_7788_confirmed-pre_notify_start_0" [ style = bold] "ms_drbd_7788_pre_notify_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_pre_notify_stop_0" -> "ms_drbd_7788_confirmed-pre_notify_stop_0" [ style = bold] "ms_drbd_7788_pre_notify_stop_0" -> "rsc_drbd_7788:0_pre_notify_stop_0 arc-dknightlx" [ style = bold] "ms_drbd_7788_pre_notify_stop_0" -> "rsc_drbd_7788:1_pre_notify_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_pre_notify_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_running_0" -> "ms_drbd_7788_post_notify_start_0" [ style = bold] "ms_drbd_7788_running_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_start_0" -> "ms_drbd_7788_running_0" [ style = bold] "ms_drbd_7788_start_0" -> "rsc_drbd_7788:1_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_start_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_stop_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_stop_0" -> "ms_drbd_7788_stopped_0" [ style = bold] "ms_drbd_7788_stop_0" -> "rsc_drbd_7788:0_stop_0 arc-dknightlx" [ style = bold] "ms_drbd_7788_stop_0" -> "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "ms_drbd_7788_stop_0" [ style=bold color="green" fontcolor="orange" ] "ms_drbd_7788_stopped_0" -> "ms_drbd_7788_post_notify_stop_0" [ style = bold] "ms_drbd_7788_stopped_0" -> "ms_drbd_7788_start_0" [ style = bold] "ms_drbd_7788_stopped_0" [ style=bold color="green" fontcolor="orange" ] "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" -> "fs_mirror_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" -> "grp_pgsql_mirror_stopped_0" [ style = bold] "pgsql_5555_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:0_post_notify_demote_0 arc-dknightlx" -> "ms_drbd_7788_confirmed-post_notify_demote_0" [ style = bold] "rsc_drbd_7788:0_post_notify_demote_0 arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:0_pre_notify_demote_0 arc-dknightlx" -> "ms_drbd_7788_confirmed-pre_notify_demote_0" [ style = bold] "rsc_drbd_7788:0_pre_notify_demote_0 arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:0_pre_notify_stop_0 arc-dknightlx" -> "ms_drbd_7788_confirmed-pre_notify_stop_0" [ style = bold] "rsc_drbd_7788:0_pre_notify_stop_0 arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:0_stop_0 arc-dknightlx" -> "do_shutdown arc-dknightlx" [ style = bold] "rsc_drbd_7788:0_stop_0 arc-dknightlx" -> "ms_drbd_7788_stopped_0" [ style = bold] "rsc_drbd_7788:0_stop_0 arc-dknightlx" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_demote_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_demoted_0" [ style = bold] "rsc_drbd_7788:1_demote_0 arc-tkincaidlx.wsicorp.com" -> "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "rsc_drbd_7788:1_demote_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] -"rsc_drbd_7788:1_monitor_0 " [ style=filled color="black" fontcolor="black" fillcolor=red] "rsc_drbd_7788:1_post_notify_demote_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-post_notify_demote_0" [ style = bold] "rsc_drbd_7788:1_post_notify_demote_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_post_notify_start_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-post_notify_start_0" [ style = bold] "rsc_drbd_7788:1_post_notify_start_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_pre_notify_demote_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-pre_notify_demote_0" [ style = bold] "rsc_drbd_7788:1_pre_notify_demote_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_pre_notify_stop_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_confirmed-pre_notify_stop_0" [ style = bold] "rsc_drbd_7788:1_pre_notify_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_start_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_running_0" [ style = bold] "rsc_drbd_7788:1_start_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" -> "ms_drbd_7788_stopped_0" [ style = bold] "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" -> "rsc_drbd_7788:1_start_0 arc-tkincaidlx.wsicorp.com" [ style = bold] "rsc_drbd_7788:1_stop_0 arc-tkincaidlx.wsicorp.com" [ style=bold color="green" fontcolor="black" ] } diff --git a/crm/pengine/testcases/bug-1572-2.exp b/crm/pengine/testcases/bug-1572-2.exp index 2f3890203f..a2270e9d99 100644 --- a/crm/pengine/testcases/bug-1572-2.exp +++ b/crm/pengine/testcases/bug-1572-2.exp @@ -1,513 +1,513 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/crm/pengine/testcases/novell-251689.dot b/crm/pengine/testcases/novell-251689.dot index 13ebfd7753..7eaaadb9ed 100644 --- a/crm/pengine/testcases/novell-251689.dot +++ b/crm/pengine/testcases/novell-251689.dot @@ -1,8 +1,7 @@ digraph "g" { -"sles10_monitor_0 " [ style=filled color="black" fontcolor="black" fillcolor=red] "sles10_monitor_10000 node2" [ style=filled color="black" fontcolor="black" fillcolor=red] "sles10_start_0 " -> "sles10_monitor_10000 node2" [ style = bold] "sles10_start_0 " [ style=filled color="black" fontcolor="black" fillcolor=red] "sles10_stop_0 node2" -> "sles10_start_0 " [ style = bold] "sles10_stop_0 node2" [ style=bold color="green" fontcolor="black" ] } diff --git a/crm/pengine/testcases/novell-251689.exp b/crm/pengine/testcases/novell-251689.exp index 329fc3eb6f..5742e5279a 100644 --- a/crm/pengine/testcases/novell-251689.exp +++ b/crm/pengine/testcases/novell-251689.exp @@ -1,12 +1,12 @@ - + diff --git a/include/crm/pengine/common.h b/include/crm/pengine/common.h index e64f8c9f6f..64cc71106b 100644 --- a/include/crm/pengine/common.h +++ b/include/crm/pengine/common.h @@ -1,120 +1,121 @@ /* * 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 PE_COMMON__H #define PE_COMMON__H extern gboolean was_processing_error; extern gboolean was_processing_warning; extern unsigned int pengine_input_loglevel; /* order is significant here * items listed in order of accending severeness * more severe actions take precedent over lower ones */ enum action_fail_response { action_fail_ignore, action_fail_recover, action_migrate_failure, /* recovery from a failed atomic migration */ action_fail_migrate, /* recover by moving it somewhere else */ action_fail_block, action_fail_stop, action_fail_fence }; /* the "done" action must be the "pre" action +1 */ enum action_tasks { no_action, monitor_rsc, stop_rsc, stopped_rsc, start_rsc, started_rsc, action_notify, action_notified, action_promote, action_promoted, action_demote, action_demoted, shutdown_crm, stonith_node }; enum rsc_recovery_type { recovery_stop_start, recovery_stop_only, recovery_block }; enum rsc_start_requirement { rsc_req_nothing, rsc_req_quorum, rsc_req_stonith }; enum rsc_role_e { RSC_ROLE_UNKNOWN, RSC_ROLE_STOPPED, RSC_ROLE_STARTED, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, }; #define RSC_ROLE_MAX RSC_ROLE_MASTER+1 #define RSC_ROLE_UNKNOWN_S "Unknown" #define RSC_ROLE_STOPPED_S "Stopped" #define RSC_ROLE_STARTED_S "Started" #define RSC_ROLE_SLAVE_S "Slave" #define RSC_ROLE_MASTER_S "Master" enum pe_print_options { pe_print_log = 0x0001, pe_print_html = 0x0002, pe_print_ncurses = 0x0004, pe_print_printf = 0x0008, pe_print_dev = 0x0010, pe_print_details = 0x0020, pe_print_max_details = 0x0040, pe_print_rsconly = 0x0080, }; extern int merge_weights(int w1, int w2); extern const char *task2text(enum action_tasks task); extern enum action_tasks text2task(const char *task); extern enum rsc_role_e text2role(const char *role); extern const char *role2text(enum rsc_role_e role); extern const char *fail2text(enum action_fail_response fail); extern void add_hash_param(GHashTable *hash, const char *name, const char *value); extern void pe_metadata(void); extern void verify_pe_options(GHashTable *options); extern const char *pe_pref(GHashTable *options, const char *name); +extern void calculate_active_ops(GListPtr sorted_op_list, int *start_index, int *stop_index); /* Helper macros to avoid NULL pointers */ #define safe_val3(def, t,u,v) (t?t->u?t->u->v:def:def) #define safe_val5(def, t,u,v,w,x) (t?t->u?t->u->v?t->u->v->w?t->u->v->w->x:def:def:def:def) #define pe_err(fmt...) { was_processing_error = TRUE; crm_config_error = TRUE; crm_err(fmt); } #define pe_warn(fmt...) { was_processing_warning = TRUE; crm_config_warning = TRUE; crm_warn(fmt); } #define pe_proc_err(fmt...) { was_processing_error = TRUE; crm_err(fmt); } #define pe_proc_warn(fmt...) { was_processing_warning = TRUE; crm_warn(fmt); } #endif diff --git a/lib/crm/pengine/unpack.c b/lib/crm/pengine/unpack.c index bc609e9f69..3b345fee69 100644 --- a/lib/crm/pengine/unpack.c +++ b/lib/crm/pengine/unpack.c @@ -1,1267 +1,1285 @@ /* * 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 #include #include gboolean unpack_config(crm_data_t *config, pe_working_set_t *data_set) { const char *name = NULL; const char *value = NULL; GHashTable *config_hash = g_hash_table_new_full( g_str_hash,g_str_equal, g_hash_destroy_str,g_hash_destroy_str); data_set->config_hash = config_hash; unpack_instance_attributes( config, XML_CIB_TAG_PROPSET, NULL, config_hash, CIB_OPTIONS_FIRST, data_set->now); #if CRM_DEPRECATED_SINCE_2_0_1 xml_child_iter_filter( config, a_child, XML_CIB_TAG_NVPAIR, name = crm_element_value(a_child, XML_NVPAIR_ATTR_NAME); value = crm_element_value(a_child, XML_NVPAIR_ATTR_VALUE); if(g_hash_table_lookup(config_hash, name) == NULL) { g_hash_table_insert( config_hash,crm_strdup(name),crm_strdup(value)); } crm_config_err("Creating directly" "beneath has been depreciated since" " 2.0.1", ID(a_child), name); ); #else xml_child_iter_filter( config, a_child, XML_CIB_TAG_NVPAIR, name = crm_element_value(a_child, XML_NVPAIR_ATTR_NAME); crm_config_err("Creating directly" "beneath has been depreciated since" " 2.0.1 and is now disabled", ID(a_child), name); ); #endif verify_pe_options(data_set->config_hash); value = pe_pref(data_set->config_hash, "default-action-timeout"); data_set->transition_idle_timeout = crm_strdup(value); crm_debug("Default action timeout: %s", data_set->transition_idle_timeout); value = pe_pref(data_set->config_hash, "default-resource-stickiness"); data_set->default_resource_stickiness = char2score(value); crm_debug("Default stickiness: %d", data_set->default_resource_stickiness); value = pe_pref(data_set->config_hash, "default-resource-failure-stickiness"); data_set->default_resource_fail_stickiness = char2score(value); crm_debug("Default failure stickiness: %d", data_set->default_resource_fail_stickiness); value = pe_pref(data_set->config_hash, "stonith-enabled"); cl_str_to_boolean(value, &data_set->stonith_enabled); crm_debug("STONITH of failed nodes is %s", data_set->stonith_enabled?"enabled":"disabled"); data_set->stonith_action = pe_pref(data_set->config_hash, "stonith-action"); crm_debug_2("STONITH will %s nodes", data_set->stonith_action); value = pe_pref(data_set->config_hash, "symmetric-cluster"); cl_str_to_boolean(value, &data_set->symmetric_cluster); if(data_set->symmetric_cluster) { crm_debug("Cluster is symmetric" " - resources can run anywhere by default"); } value = pe_pref(data_set->config_hash, "no-quorum-policy"); if(safe_str_eq(value, "ignore")) { data_set->no_quorum_policy = no_quorum_ignore; } else if(safe_str_eq(value, "freeze")) { data_set->no_quorum_policy = no_quorum_freeze; } else { data_set->no_quorum_policy = no_quorum_stop; } switch (data_set->no_quorum_policy) { case no_quorum_freeze: crm_debug("On loss of CCM Quorum: Freeze resources"); break; case no_quorum_stop: crm_debug("On loss of CCM Quorum: Stop ALL resources"); break; case no_quorum_ignore: crm_notice("On loss of CCM Quorum: Ignore"); break; } value = pe_pref(data_set->config_hash, "stop-orphan-resources"); cl_str_to_boolean(value, &data_set->stop_rsc_orphans); crm_debug_2("Orphan resources are %s", data_set->stop_rsc_orphans?"stopped":"ignored"); value = pe_pref(data_set->config_hash, "stop-orphan-actions"); cl_str_to_boolean(value, &data_set->stop_action_orphans); crm_debug_2("Orphan resource actions are %s", data_set->stop_action_orphans?"stopped":"ignored"); value = pe_pref(data_set->config_hash, "remove-after-stop"); cl_str_to_boolean(value, &data_set->remove_after_stop); crm_debug_2("Stopped resources are removed from the status section: %s", data_set->remove_after_stop?"true":"false"); value = pe_pref(data_set->config_hash, "is-managed-default"); cl_str_to_boolean(value, &data_set->is_managed_default); crm_debug_2("By default resources are %smanaged", data_set->is_managed_default?"":"not "); return TRUE; } gboolean unpack_nodes(crm_data_t * xml_nodes, pe_working_set_t *data_set) { node_t *new_node = NULL; const char *id = NULL; const char *uname = NULL; const char *type = NULL; gboolean unseen_are_unclean = TRUE; const char *blind_faith = pe_pref( data_set->config_hash, "startup-fencing"); if(crm_is_true(blind_faith) == FALSE) { unseen_are_unclean = FALSE; crm_warn("Blind faith: not fencing unseen nodes"); } xml_child_iter_filter( xml_nodes, xml_obj, XML_CIB_TAG_NODE, new_node = NULL; id = crm_element_value(xml_obj, XML_ATTR_ID); uname = crm_element_value(xml_obj, XML_ATTR_UNAME); type = crm_element_value(xml_obj, XML_ATTR_TYPE); crm_debug_3("Processing node %s/%s", uname, id); if(id == NULL) { crm_config_err("Must specify id tag in "); continue; } if(type == NULL) { crm_config_err("Must specify type tag in "); continue; } crm_malloc0(new_node, sizeof(node_t)); if(new_node == NULL) { return FALSE; } new_node->weight = 0; new_node->fixed = FALSE; crm_malloc0(new_node->details, sizeof(struct node_shared_s)); if(new_node->details == NULL) { crm_free(new_node); return FALSE; } crm_debug_3("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->shutdown = FALSE; new_node->details->running_rsc = NULL; new_node->details->attrs = g_hash_table_new_full( g_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); /* if(data_set->have_quorum == FALSE */ /* && data_set->no_quorum_policy == no_quorum_stop) { */ /* /\* start shutting resources down *\/ */ /* new_node->weight = -INFINITY; */ /* } */ if(data_set->stonith_enabled == FALSE || unseen_are_unclean == FALSE) { /* blind faith... */ new_node->details->unclean = FALSE; } else { /* all nodes are unclean until we've seen their * status entry */ new_node->details->unclean = TRUE; } if(type == NULL || safe_str_eq(type, "member") || safe_str_eq(type, NORMALNODE)) { new_node->details->type = node_member; } add_node_attrs(xml_obj, new_node, data_set); if(crm_is_true(g_hash_table_lookup( new_node->details->attrs, "standby"))) { crm_info("Node %s is in standby-mode", new_node->details->uname); new_node->weight = -INFINITY; new_node->details->standby = TRUE; } data_set->nodes = g_list_append(data_set->nodes, new_node); crm_debug_3("Done with node %s", crm_element_value(xml_obj, XML_ATTR_UNAME)); ); return TRUE; } gboolean unpack_resources(crm_data_t * xml_resources, pe_working_set_t *data_set) { xml_child_iter( xml_resources, xml_obj, resource_t *new_rsc = NULL; crm_debug_3("Begining unpack... %s", xml_obj?crm_element_name(xml_obj):""); if(common_unpack(xml_obj, &new_rsc, NULL, data_set)) { data_set->resources = g_list_append( data_set->resources, new_rsc); print_resource(LOG_DEBUG_3, "Added", new_rsc, FALSE); } else { crm_config_err("Failed unpacking %s %s", crm_element_name(xml_obj), crm_element_value(xml_obj, XML_ATTR_ID)); if(new_rsc != NULL && new_rsc->fns != NULL) { new_rsc->fns->free(new_rsc); } } ); data_set->resources = g_list_sort( data_set->resources, sort_rsc_priority); return TRUE; } /* 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(crm_data_t * status, pe_working_set_t *data_set) { const char *id = NULL; const char *uname = NULL; crm_data_t * lrm_rsc = NULL; crm_data_t * attrs = NULL; node_t *this_node = NULL; crm_debug_3("Begining unpack"); xml_child_iter_filter( status, node_state, XML_CIB_TAG_STATE, id = crm_element_value(node_state, XML_ATTR_ID); uname = crm_element_value(node_state, XML_ATTR_UNAME); attrs = find_xml_node( node_state, XML_TAG_TRANSIENT_NODEATTRS, FALSE); lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE); lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE); crm_debug_3("Processing node %s", uname); this_node = pe_find_node_id(data_set->nodes, id); if(uname == NULL) { /* error */ continue; } else if(this_node == NULL) { crm_config_warn("Node %s in status section no longer exists", uname); continue; } /* Mark the node as provisionally clean * - at least we have seen it in the current cluster's lifetime */ this_node->details->unclean = FALSE; crm_debug_3("Adding runtime node attrs"); add_node_attrs(attrs, this_node, data_set); crm_debug_3("determining node state"); determine_online_status(node_state, this_node, data_set); if(this_node->details->online || data_set->stonith_enabled) { /* offline nodes run no resources... * unless stonith is enabled in which case we need to * make sure rsc start events happen after the stonith */ crm_debug_3("Processing lrm resource entries"); unpack_lrm_resources(this_node, lrm_rsc, data_set); } ); return TRUE; } static gboolean determine_online_status_no_fencing(crm_data_t * node_state, node_t *this_node) { gboolean online = FALSE; const char *join_state = crm_element_value(node_state, XML_CIB_ATTR_JOINSTATE); const char *crm_state = crm_element_value(node_state, XML_CIB_ATTR_CRMDSTATE); const char *ccm_state = crm_element_value(node_state, XML_CIB_ATTR_INCCM); const char *ha_state = crm_element_value(node_state, XML_CIB_ATTR_HASTATE); const char *exp_state = crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE); if(ha_state == NULL) { ha_state = DEADSTATUS; } if(!crm_is_true(ccm_state) || safe_str_eq(ha_state, DEADSTATUS)){ crm_debug_2("Node is down: ha_state=%s, ccm_state=%s", crm_str(ha_state), crm_str(ccm_state)); } else if(!crm_is_true(ccm_state) || safe_str_eq(ha_state, DEADSTATUS)) { } else if(safe_str_eq(crm_state, ONLINESTATUS)) { if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)) { online = TRUE; } else { crm_debug("Node is not ready to run resources: %s", join_state); } } else if(this_node->details->expected_up == FALSE) { crm_debug_2("CRMd is down: ha_state=%s, ccm_state=%s", crm_str(ha_state), crm_str(ccm_state)); crm_debug_2("\tcrm_state=%s, join_state=%s, expected=%s", crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); } else { /* mark it unclean */ this_node->details->unclean = TRUE; crm_warn("Node %s is partially & un-expectedly down", this_node->details->uname); crm_info("\tha_state=%s, ccm_state=%s," " crm_state=%s, join_state=%s, expected=%s", crm_str(ha_state), crm_str(ccm_state), crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); } return online; } static gboolean determine_online_status_fencing(crm_data_t * node_state, node_t *this_node) { gboolean online = FALSE; const char *join_state = crm_element_value(node_state, XML_CIB_ATTR_JOINSTATE); const char *crm_state = crm_element_value(node_state, XML_CIB_ATTR_CRMDSTATE); const char *ccm_state = crm_element_value(node_state, XML_CIB_ATTR_INCCM); const char *ha_state = crm_element_value(node_state, XML_CIB_ATTR_HASTATE); const char *exp_state = crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE); if(ha_state == NULL) { ha_state = DEADSTATUS; } if(crm_is_true(ccm_state) && safe_str_eq(ha_state, ACTIVESTATUS) && safe_str_eq(crm_state, ONLINESTATUS)) { online = TRUE; if(safe_str_neq(join_state, CRMD_JOINSTATE_MEMBER)) { crm_info("Node %s is not ready to run resources", this_node->details->uname); this_node->details->standby = TRUE; } } else if(crm_is_true(ccm_state) == FALSE && safe_str_eq(ha_state, DEADSTATUS) && safe_str_eq(crm_state, OFFLINESTATUS) && this_node->details->expected_up == FALSE) { crm_debug("Node %s is down: join_state=%s, expected=%s", this_node->details->uname, crm_str(join_state), crm_str(exp_state)); } else if(this_node->details->expected_up) { /* mark it unclean */ this_node->details->unclean = TRUE; crm_warn("Node %s (%s) is un-expectedly down", this_node->details->uname, this_node->details->id); crm_info("\tha_state=%s, ccm_state=%s," " crm_state=%s, join_state=%s, expected=%s", crm_str(ha_state), crm_str(ccm_state), crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); } else { crm_info("Node %s is comming up", this_node->details->uname); crm_debug("\tha_state=%s, ccm_state=%s," " crm_state=%s, join_state=%s, expected=%s", crm_str(ha_state), crm_str(ccm_state), crm_str(crm_state), crm_str(join_state), crm_str(exp_state)); } return online; } gboolean determine_online_status( crm_data_t * node_state, node_t *this_node, pe_working_set_t *data_set) { int shutdown = 0; gboolean online = FALSE; const char *exp_state = crm_element_value(node_state, XML_CIB_ATTR_EXPSTATE); if(this_node == NULL) { crm_config_err("No node to check"); return online; } ha_msg_value_int(node_state, XML_CIB_ATTR_SHUTDOWN, &shutdown); this_node->details->expected_up = FALSE; if(safe_str_eq(exp_state, CRMD_JOINSTATE_MEMBER)) { this_node->details->expected_up = TRUE; } this_node->details->shutdown = FALSE; if(shutdown != 0) { this_node->details->shutdown = TRUE; this_node->details->expected_up = FALSE; } if(data_set->stonith_enabled == FALSE) { online = determine_online_status_no_fencing( node_state, this_node); } else { online = determine_online_status_fencing( node_state, this_node); } if(online) { this_node->details->online = TRUE; } else { /* remove node from contention */ this_node->fixed = TRUE; this_node->weight = -INFINITY; } if(online && this_node->details->shutdown) { /* dont run resources here */ this_node->fixed = TRUE; this_node->weight = -INFINITY; } if(this_node->details->unclean) { pe_proc_warn("Node %s is unclean", this_node->details->uname); } else if(this_node->details->online) { crm_info("Node %s is %s", this_node->details->uname, this_node->details->shutdown?"shutting down": this_node->details->standby?"standby":"online"); } else { crm_debug_2("Node %s is offline", this_node->details->uname); } return online; } #define set_char(x) last_rsc_id[len] = x; complete = TRUE; static void increment_clone(char *last_rsc_id) { gboolean complete = FALSE; int len = 0; CRM_CHECK(last_rsc_id != NULL, return); if(last_rsc_id != NULL) { len = strlen(last_rsc_id); } len--; while(complete == FALSE && len > 0) { switch (last_rsc_id[len]) { case 0: len--; break; case '0': set_char('1'); break; case '1': set_char('2'); break; case '2': set_char('3'); break; case '3': set_char('4'); break; case '4': set_char('5'); break; case '5': set_char('6'); break; case '6': set_char('7'); break; case '7': set_char('8'); break; case '8': set_char('9'); break; case '9': last_rsc_id[len] = '0'; len--; break; default: crm_err("Unexpected char: %c (%d)", last_rsc_id[len], len); break; } } } static resource_t * create_fake_resource(const char *rsc_id, crm_data_t *rsc_entry, pe_working_set_t *data_set) { resource_t *rsc = NULL; crm_data_t *xml_rsc = create_xml_node(NULL, XML_CIB_TAG_RESOURCE); crm_log_xml_info(rsc_entry, "Orphan resource"); copy_in_properties(xml_rsc, rsc_entry); crm_xml_add(xml_rsc, XML_ATTR_ID, rsc_id); common_unpack(xml_rsc, &rsc, NULL, data_set); rsc->orphan = TRUE; data_set->resources = g_list_append(data_set->resources, rsc); return rsc; } static resource_t * unpack_find_resource( pe_working_set_t *data_set, node_t *node, const char *rsc_id, crm_data_t *rsc_entry) { resource_t *rsc = NULL; gboolean is_duped_clone = FALSE; char *alt_rsc_id = crm_strdup(rsc_id); while(rsc == NULL) { crm_debug_3("looking for: %s", alt_rsc_id); rsc = pe_find_resource(data_set->resources, alt_rsc_id); /* no match */ if(rsc == NULL) { crm_debug_2("%s not found: %d", alt_rsc_id, is_duped_clone); if(is_duped_clone) { /* create one */ rsc = create_fake_resource(alt_rsc_id, rsc_entry, data_set); crm_info("Making sure orphan %s/%s is stopped on %s", rsc_id, rsc->id, node->details->uname); resource_location(rsc, NULL, -INFINITY, "__orphan_clone_dont_run__", data_set); } break; /* not running anywhere else */ } else if(rsc->running_on == NULL) { crm_debug_3("not active yet"); break; /* always unique */ } else if(rsc->globally_unique) { crm_debug_3("unique"); break; /* running somewhere already but we dont care * find another clone instead */ } else { crm_debug_2("find another one"); rsc = NULL; is_duped_clone = TRUE; increment_clone(alt_rsc_id); } } crm_free(alt_rsc_id); if(rsc != NULL) { crm_free(rsc->clone_name); rsc->clone_name = NULL; if(is_duped_clone) { crm_info("Internally renamed %s on %s to %s", rsc_id, node->details->uname, rsc->id); rsc->clone_name = crm_strdup(rsc_id); } } return rsc; } static resource_t * process_orphan_resource(crm_data_t *rsc_entry, node_t *node, pe_working_set_t *data_set) { resource_t *rsc = NULL; const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID); crm_log_xml_info(rsc_entry, "Orphan resource"); crm_config_warn("Nothing known about resource %s running on %s", rsc_id, node->details->uname); rsc = create_fake_resource(rsc_id, rsc_entry, data_set); if(data_set->stop_rsc_orphans == FALSE) { rsc->is_managed = FALSE; } else { crm_info("Making sure orphan %s is stopped", rsc_id); print_resource(LOG_DEBUG_3, "Added orphan", rsc, FALSE); CRM_CHECK(rsc != NULL, return NULL); resource_location(rsc, NULL, -INFINITY, "__orphan_dont_run__", data_set); } return rsc; } static void process_rsc_state(resource_t *rsc, node_t *node, enum action_fail_response on_fail, crm_data_t *migrate_op, pe_working_set_t *data_set) { int fail_count = 0; char *fail_attr = NULL; const char *value = NULL; GHashTable *meta_hash = NULL; if(on_fail == action_migrate_failure) { node_t *from = NULL; const char *uuid = NULL; uuid = crm_element_value(migrate_op, CRMD_ACTION_MIGRATED); from = pe_find_node_id(data_set->nodes, uuid); process_rsc_state(rsc, from, action_fail_recover,NULL,data_set); on_fail = action_fail_recover; } crm_debug_2("Resource %s is %s on %s", rsc->id, role2text(rsc->role), node->details->uname); meta_hash = g_hash_table_new_full( g_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); get_meta_attributes(meta_hash, rsc, node, data_set); /* update resource preferences that relate to the current node */ value = g_hash_table_lookup(meta_hash, "resource_stickiness"); if(value != NULL && safe_str_neq("default", value)) { rsc->stickiness = char2score(value); } else { rsc->stickiness = data_set->default_resource_stickiness; } value = g_hash_table_lookup(meta_hash, XML_RSC_ATTR_FAIL_STICKINESS); if(value != NULL && safe_str_neq("default", value)) { rsc->fail_stickiness = char2score(value); } else { rsc->fail_stickiness = data_set->default_resource_fail_stickiness; } /* process failure stickiness */ fail_attr = crm_concat("fail-count", rsc->id, '-'); value = g_hash_table_lookup(node->details->attrs, fail_attr); if(value != NULL) { crm_debug("%s: %s", fail_attr, value); fail_count = crm_parse_int(value, "0"); } crm_free(fail_attr); if(fail_count > 0 && rsc->fail_stickiness != 0) { resource_location(rsc, node, fail_count * rsc->fail_stickiness, "fail_stickiness", data_set); crm_debug("Setting failure stickiness for %s on %s: %d", rsc->id, node->details->uname, fail_count * rsc->fail_stickiness); } /* process current state */ if(rsc->role != RSC_ROLE_UNKNOWN) { rsc->known_on = g_list_append(rsc->known_on, node); } if(rsc->role != RSC_ROLE_STOPPED && rsc->role != RSC_ROLE_UNKNOWN) { if(on_fail != action_fail_ignore) { rsc->failed = TRUE; crm_debug_2("Force stop"); } native_add_running(rsc, node, data_set); if(rsc->is_managed && rsc->stickiness != 0) { resource_location(rsc, node, rsc->stickiness, "stickiness", data_set); crm_debug_2("Resource %s: preferring current location" " (node=%s, weight=%d)", rsc->id, node->details->uname, rsc->stickiness); } if(on_fail == action_fail_ignore) { /* nothing to do */ } else if(node->details->unclean) { stop_action(rsc, node, FALSE); } else if(on_fail == action_fail_fence) { /* treat it as if it is still running * but also mark the node as unclean */ node->details->unclean = TRUE; stop_action(rsc, node, FALSE); } else if(on_fail == action_fail_block) { /* is_managed == FALSE will prevent any * actions being sent for the resource */ rsc->is_managed = FALSE; } else if(on_fail == action_fail_migrate) { stop_action(rsc, node, FALSE); /* make sure it comes up somewhere else * or not at all */ resource_location(rsc, node, -INFINITY, "__action_migration_auto__",data_set); } else { stop_action(rsc, node, FALSE); } } else if(rsc->clone_name) { crm_debug_2("Resetting clone_name %s for %s (stopped)", rsc->clone_name, rsc->id); crm_free(rsc->clone_name); rsc->clone_name = NULL; } else { char *key = stop_key(rsc); GListPtr possible_matches = find_actions(rsc->actions, key, node); slist_iter(stop, action_t, possible_matches, lpc, stop->optional = TRUE; ); crm_free(key); } g_hash_table_destroy(meta_hash); } /* create active recurring operations as optional */ static void process_recurring(node_t *node, resource_t *rsc, int start_index, int stop_index, GListPtr sorted_op_list, pe_working_set_t *data_set) { const char *task = NULL; const char *status = NULL; crm_debug_3("%s: Start index %d, stop index = %d", rsc->id, start_index, stop_index); slist_iter(rsc_op, crm_data_t, sorted_op_list, lpc, int interval = 0; char *key = NULL; const char *id = ID(rsc_op); const char *interval_s = NULL; if(node->details->online == FALSE) { crm_debug_4("Skipping %s/%s: node is offline", rsc->id, node->details->uname); break; } else if(start_index < stop_index) { crm_debug_4("Skipping %s/%s: not active", rsc->id, node->details->uname); break; } else if(lpc <= start_index) { crm_debug_4("Skipping %s/%s: old", id, node->details->uname); continue; } interval_s = crm_element_value(rsc_op,XML_LRM_ATTR_INTERVAL); interval = crm_parse_int(interval_s, "0"); if(interval == 0) { crm_debug_4("Skipping %s/%s: non-recurring", id, node->details->uname); continue; } status = crm_element_value(rsc_op, XML_LRM_ATTR_OPSTATUS); if(safe_str_eq(status, "-1")) { crm_debug_4("Skipping %s/%s: status", id, node->details->uname); continue; } task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); /* create the action */ key = generate_op_key(rsc->id, task, interval); crm_debug_3("Creating %s/%s", key, node->details->uname); custom_action(rsc, key, task, node, TRUE, TRUE, data_set); ); } +void +calculate_active_ops(GListPtr sorted_op_list, int *start_index, int *stop_index) +{ + const char *task = NULL; + const char *status = NULL; + + *stop_index = -1; + *start_index = -1; + + slist_iter( + rsc_op, crm_data_t, sorted_op_list, lpc, + + task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); + status = crm_element_value(rsc_op, XML_LRM_ATTR_OPSTATUS); + + if(safe_str_eq(task, CRMD_ACTION_STOP) + && safe_str_eq(status, "0")) { + *stop_index = lpc; + + } else if(safe_str_eq(task, CRMD_ACTION_START)) { + *start_index = lpc; + + } else if(*start_index <= *stop_index + && safe_str_eq(task, CRMD_ACTION_STATUS)) { + const char *rc = crm_element_value(rsc_op, XML_LRM_ATTR_RC); + if(safe_str_eq(rc, "0") || safe_str_eq(rc, "8")) { + *start_index = lpc; + } + } + ); +} + static void unpack_lrm_rsc_state( node_t *node, crm_data_t * rsc_entry, pe_working_set_t *data_set) { int stop_index = -1; int start_index = -1; int max_call_id = -1; const char *task = NULL; - const char *status = NULL; const char *value = NULL; const char *rsc_id = crm_element_value(rsc_entry, XML_ATTR_ID); resource_t *rsc = NULL; GListPtr op_list = NULL; GListPtr sorted_op_list = NULL; crm_data_t *migrate_op = NULL; enum action_fail_response on_fail = FALSE; enum rsc_role_e saved_role = RSC_ROLE_UNKNOWN; crm_debug_3("[%s] Processing %s on %s", crm_element_name(rsc_entry), rsc_id, node->details->uname); /* extract operations */ op_list = NULL; sorted_op_list = NULL; xml_child_iter_filter( rsc_entry, rsc_op, XML_LRM_TAG_RSC_OP, op_list = g_list_append(op_list, rsc_op); ); if(op_list == NULL) { /* if there are no operations, there is nothing to do */ return; } /* find the resource */ rsc = unpack_find_resource(data_set, node, rsc_id, rsc_entry); if(rsc == NULL) { rsc = process_orphan_resource(rsc_entry, node, data_set); } CRM_ASSERT(rsc != NULL); /* process operations */ max_call_id = -1; saved_role = rsc->role; on_fail = action_fail_ignore; rsc->role = RSC_ROLE_UNKNOWN; sorted_op_list = g_list_sort(op_list, sort_op_by_callid); slist_iter( rsc_op, crm_data_t, sorted_op_list, lpc, + task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); - status = crm_element_value(rsc_op, XML_LRM_ATTR_OPSTATUS); - if(safe_str_eq(task, CRMD_ACTION_STOP) - && safe_str_eq(status, "0")) { - stop_index = lpc; - - } else if(safe_str_eq(task, CRMD_ACTION_START)) { - start_index = lpc; - - } else if(start_index <= stop_index - && safe_str_eq(task, CRMD_ACTION_STATUS)) { - const char *rc = crm_element_value(rsc_op, XML_LRM_ATTR_RC); - if(safe_str_eq(rc, "0") - || safe_str_eq(rc, "8")) { - start_index = lpc; - } - } else if(safe_str_eq(task, CRMD_ACTION_MIGRATED)) { + if(safe_str_eq(task, CRMD_ACTION_MIGRATED)) { migrate_op = rsc_op; } unpack_rsc_op(rsc, node, rsc_op, &max_call_id, &on_fail, data_set); ); /* create active recurring operations as optional */ + calculate_active_ops(sorted_op_list, &start_index, &stop_index); process_recurring(node, rsc, start_index, stop_index, sorted_op_list, data_set); /* no need to free the contents */ g_list_free(sorted_op_list); process_rsc_state(rsc, node, on_fail, migrate_op, data_set); value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE); if(value != NULL && safe_str_neq("default", value)) { enum rsc_role_e req_role = text2role(value); if(req_role != RSC_ROLE_UNKNOWN && req_role != rsc->next_role){ if(rsc->next_role != RSC_ROLE_UNKNOWN) { crm_debug("%s: Overwriting calculated next role %s" " with requested next role %s", rsc->id, role2text(rsc->next_role), role2text(req_role)); } rsc->next_role = req_role; } } if(saved_role > rsc->role) { rsc->role = saved_role; } } gboolean unpack_lrm_resources(node_t *node, crm_data_t * lrm_rsc_list, pe_working_set_t *data_set) { CRM_CHECK(node != NULL, return FALSE); crm_debug_3("Unpacking resources on %s", node->details->uname); xml_child_iter_filter( lrm_rsc_list, rsc_entry, XML_LRM_TAG_RESOURCE, unpack_lrm_rsc_state(node, rsc_entry, data_set); ); return TRUE; } gboolean unpack_rsc_op(resource_t *rsc, node_t *node, crm_data_t *xml_op, int *max_call_id, enum action_fail_response *on_fail, pe_working_set_t *data_set) { const char *id = NULL; const char *task = NULL; const char *task_id = NULL; const char *actual_rc = NULL; /* const char *target_rc = NULL; */ const char *task_status = NULL; const char *interval_s = NULL; const char *op_digest = NULL; int interval = 0; int task_id_i = -1; int task_status_i = -2; int actual_rc_i = 0; action_t *action = NULL; gboolean is_probe = FALSE; gboolean is_stop_action = FALSE; CRM_CHECK(rsc != NULL, return FALSE); CRM_CHECK(node != NULL, return FALSE); CRM_CHECK(xml_op != NULL, return FALSE); id = ID(xml_op); task = crm_element_value(xml_op, XML_LRM_ATTR_TASK); task_id = crm_element_value(xml_op, XML_LRM_ATTR_CALLID); task_status = crm_element_value(xml_op, XML_LRM_ATTR_OPSTATUS); op_digest = crm_element_value(xml_op, XML_LRM_ATTR_OP_DIGEST); CRM_CHECK(id != NULL, return FALSE); CRM_CHECK(task != NULL, return FALSE); CRM_CHECK(task_status != NULL, return FALSE); task_status_i = crm_parse_int(task_status, NULL); CRM_CHECK(task_status_i <= LRM_OP_ERROR, return FALSE); CRM_CHECK(task_status_i >= LRM_OP_PENDING, return FALSE); if(safe_str_eq(task, CRMD_ACTION_NOTIFY)) { /* safe to ignore these */ return TRUE; } crm_debug_2("Unpacking task %s/%s (call_id=%s, status=%s) on %s (role=%s)", id, task, task_id, task_status, node->details->uname, role2text(rsc->role)); interval_s = crm_element_value(xml_op, XML_LRM_ATTR_INTERVAL); interval = crm_parse_int(interval_s, "0"); if(interval == 0 && safe_str_eq(task, CRMD_ACTION_STATUS)) { is_probe = TRUE; } if(safe_str_eq(task, CRMD_ACTION_STOP)) { is_stop_action = TRUE; } if(task_status_i != LRM_OP_PENDING) { task_id_i = crm_parse_int(task_id, "-1"); CRM_CHECK(task_id != NULL, return FALSE); CRM_CHECK(task_id_i >= 0, return FALSE); CRM_CHECK(task_id_i > *max_call_id, return FALSE); } if(*max_call_id < task_id_i) { *max_call_id = task_id_i; } if(node->details->unclean) { crm_debug_2("Node %s (where %s is running) is unclean." " Further action depends on the value of %s", node->details->uname, rsc->id, XML_RSC_ATTR_STOPFAIL); } actual_rc = crm_element_value(xml_op, XML_LRM_ATTR_RC); CRM_CHECK(actual_rc != NULL, return FALSE); actual_rc_i = crm_parse_int(actual_rc, NULL); if(EXECRA_NOT_INSTALLED == actual_rc_i) { resource_location(rsc, node, -INFINITY, "not-installed", data_set); if(is_probe) { /* treat these like stops */ is_stop_action = TRUE; task_status_i = LRM_OP_DONE; actual_rc_i = EXECRA_NOT_RUNNING; } else { task_status_i = LRM_OP_ERROR; } } else if(EXECRA_NOT_RUNNING == actual_rc_i) { if(is_probe) { /* treat these like stops */ is_stop_action = TRUE; } if(is_stop_action) { task_status_i = LRM_OP_DONE; } else { task_status_i = LRM_OP_ERROR; } } else if(EXECRA_RUNNING_MASTER == actual_rc_i) { if(is_probe || (rsc->role == RSC_ROLE_MASTER && safe_str_eq(task, CRMD_ACTION_STATUS))) { task_status_i = LRM_OP_DONE; } else { task_status_i = LRM_OP_ERROR; if(rsc->role != RSC_ROLE_MASTER) { crm_err("%s reported %s in master mode on %s", id, rsc->id, node->details->uname); } } rsc->role = RSC_ROLE_MASTER; } else if(EXECRA_FAILED_MASTER == actual_rc_i) { rsc->role = RSC_ROLE_MASTER; task_status_i = LRM_OP_ERROR; } else if(EXECRA_OK == actual_rc_i && interval > 0 && rsc->role == RSC_ROLE_MASTER) { /* catch status ops that return 0 instead of 8 while they * are supposed to be in master mode */ task_status_i = LRM_OP_ERROR; } if(task_status_i == LRM_OP_ERROR || task_status_i == LRM_OP_TIMEOUT || task_status_i == LRM_OP_NOTSUPPORTED) { action = custom_action(rsc, crm_strdup(id), task, NULL, TRUE, FALSE, data_set); if(action->on_fail == action_fail_ignore) { task_status_i = LRM_OP_DONE; } } switch(task_status_i) { case LRM_OP_PENDING: if(safe_str_eq(task, CRMD_ACTION_START)) { rsc->start_pending = TRUE; rsc->role = RSC_ROLE_STARTED; } else if(safe_str_eq(task, CRMD_ACTION_PROMOTE)) { rsc->role = RSC_ROLE_MASTER; } break; case LRM_OP_DONE: crm_debug_3("%s/%s completed on %s", rsc->id, task, node->details->uname); if(is_stop_action) { rsc->role = RSC_ROLE_STOPPED; /* clear any previous failure actions */ *on_fail = action_fail_ignore; rsc->next_role = RSC_ROLE_UNKNOWN; } else if(safe_str_eq(task, CRMD_ACTION_PROMOTE)) { rsc->role = RSC_ROLE_MASTER; } else if(safe_str_eq(task, CRMD_ACTION_DEMOTE)) { rsc->role = RSC_ROLE_SLAVE; } else if(rsc->role < RSC_ROLE_STARTED) { crm_debug_3("%s active on %s", rsc->id, node->details->uname); rsc->role = RSC_ROLE_STARTED; } break; case LRM_OP_ERROR: case LRM_OP_TIMEOUT: case LRM_OP_NOTSUPPORTED: crm_warn("Processing failed op (%s) on %s", id, node->details->uname); if(*on_fail < action->on_fail) { *on_fail = action->on_fail; } if(task_status_i == LRM_OP_NOTSUPPORTED || is_stop_action || safe_str_eq(task, CRMD_ACTION_START) ) { crm_warn("Handling failed %s for %s on %s", task, rsc->id, node->details->uname); resource_location(rsc, node, -INFINITY, "__dont_run__failed_stopstart__", data_set); } if(safe_str_eq(task, CRMD_ACTION_PROMOTE)) { rsc->role = RSC_ROLE_MASTER; } else if(safe_str_eq(task, CRMD_ACTION_DEMOTE)) { rsc->role = RSC_ROLE_MASTER; } else if(rsc->role < RSC_ROLE_STARTED) { rsc->role = RSC_ROLE_STARTED; } crm_debug_2("Resource %s: role=%s, unclean=%s, on_fail=%s, fail_role=%s", rsc->id, role2text(rsc->role), node->details->unclean?"true":"false", fail2text(action->on_fail), role2text(action->fail_role)); if(action->fail_role != RSC_ROLE_STARTED && rsc->next_role < action->fail_role) { rsc->next_role = action->fail_role; } if(action->fail_role == RSC_ROLE_STOPPED) { crm_err("Making sure %s doesn't come up again", rsc->id); /* make sure it doesnt come up again */ pe_free_shallow_adv(rsc->allowed_nodes, TRUE); rsc->allowed_nodes = node_list_dup( data_set->nodes, FALSE, FALSE); slist_iter( node, node_t, rsc->allowed_nodes, lpc, node->weight = -INFINITY; ); } pe_free_action(action); action = NULL; break; case LRM_OP_CANCELLED: /* do nothing?? */ pe_err("Dont know what to do for cancelled ops yet"); break; } crm_debug_3("Resource %s after %s: role=%s", rsc->id, task, role2text(rsc->role)); pe_free_action(action); return TRUE; } gboolean add_node_attrs(crm_data_t *xml_obj, node_t *node, pe_working_set_t *data_set) { g_hash_table_insert(node->details->attrs, crm_strdup("#"XML_ATTR_UNAME), crm_strdup(node->details->uname)); g_hash_table_insert(node->details->attrs, crm_strdup("#"XML_ATTR_ID), crm_strdup(node->details->id)); if(safe_str_eq(node->details->id, data_set->dc_uuid)) { data_set->dc_node = node; node->details->is_dc = TRUE; g_hash_table_insert(node->details->attrs, crm_strdup("#"XML_ATTR_DC), crm_strdup(XML_BOOLEAN_TRUE)); } else { g_hash_table_insert(node->details->attrs, crm_strdup("#"XML_ATTR_DC), crm_strdup(XML_BOOLEAN_FALSE)); } unpack_instance_attributes( xml_obj, XML_TAG_ATTR_SETS, NULL, node->details->attrs, NULL, data_set->now); return TRUE; }